* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
authorborutr <borutr@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 5 Feb 2009 19:10:08 +0000 (19:10 +0000)
committerborutr <borutr@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 5 Feb 2009 19:10:08 +0000 (19:10 +0000)
  added support for BSD (Mac OS X) ar format

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@5354 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
as/asranlib/asranlib.c
as/link/lkar.c
as/link/lkar.h

index dc2d8322a0d09c5c8b5ac31dbeb060f5375823b8..5891d3c4c00070ce5553b653797482ea96eab992 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-02-05 Borut Razem <borut.razem AT siol.net>
+
+       * asranlib/asranlib.c, link/lkar.h, link/lkar.c:
+         added support for BSD (Mac OS X) ar format
+
 2009-02-02 Borut Razem <borut.razem AT siol.net>
 
        * device/lib/gbz80/Makefile.in, device/lib/hc08/Makefile.in,
index e5449cfdf7490cb8c2e68b4b68b2169d6f57e3ce..ba92f7e17b4842d7bf663be3945df859ea148299 100644 (file)
@@ -5,7 +5,7 @@
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -33,6 +32,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 #define NELEM(x)  (sizeof (x) / sizeof (*x))
 
 
+int verbose = 0;
+int list = 0;
+int print_index = 0;
+
 int
 is_ar (FILE * libfp)
 {
@@ -45,17 +48,139 @@ is_ar (FILE * libfp)
   return ret;
 }
 
-static struct ar_hdr *
-ar_get_header (struct ar_hdr *hdr, FILE * libfp)
+static char *sym_tab;
+static int sym_tab_size;
+
+char *
+get_member_name (char *name, size_t *p_size, int allocate, FILE * libfp)
+{
+  *p_size = 0;
+
+  if (0 == memcmp (name, "#1/", 3))
+    {
+      char *p;
+      size_t len = strtoul (&name [3], &p, 10);
+      if (p > &name [3])
+        {
+          /* BSD appends real file name to the file header */
+          if (p_size != NULL)
+            *p_size = len;
+
+          if (allocate)
+            {
+              char *n = (char *) malloc (len);
+              if (fread (n, 1, len, libfp) != len)
+                {
+                  /* not an ar archive or broken ar archive */
+                  return NULL;
+                }
+              else
+                return n;
+            }
+          else
+            {
+              /* just advance the file pointer */
+              fseek (libfp, len, SEEK_CUR);
+              return NULL;
+            }
+        }
+      else
+        {
+          /* not an ar archive or broken ar archive */
+          return NULL;
+        }
+    }
+  else if (allocate)
+    {
+      if (name[0] == '/')
+        {
+          if (NULL != sym_tab)
+            {
+              char *p;
+
+              int name_offset = strtol (++name, &p, 0);
+              if (p != name && name_offset < sym_tab_size)
+                {
+                  int len = p - name + 1;
+                  while (len < AR_NAME_LEN && name[len++] == ' ')
+                    ;
+                  if (len == AR_NAME_LEN)
+                    {
+                      char *n;
+
+                      /* long name: get it from the symbol table */
+                      name = &sym_tab[name_offset];
+                      for (p = name; *p != '/' && *p != '\n'; ++p)
+                        assert (p < &sym_tab[sym_tab_size]);
+
+                      if (p[0] != '/' || p[1] != '\n')
+                        while (*++p != '\n')
+                          assert (p < &sym_tab[sym_tab_size]);
+
+                      n = (char *) malloc (p - name + 1);
+                      memcpy (n, name, p - name);
+                      n[p - name] = '\0';
+                      return n;
+                    }
+                }
+            }
+        }
+      else
+        {
+          char *p = strrchr (name, '/');
+
+          if (NULL != p)
+            {
+              int len = p - name;
+              while (name[++len] == ' ')
+                ;
+              if (len == AR_NAME_LEN)
+                {
+                  char *n = (char *) malloc (p - name + 1);
+                  memcpy (n, name, p - name);
+                  n[p - name] = '\0';
+                  return n;
+                }
+            }
+          else
+            {
+              /* BSD formed member name:
+                 trim trailing spaces */
+              char *n;
+
+              p = name + AR_NAME_LEN;
+              while (*--p == ' ' && p >= name)
+                ;
+              ++p;
+              n = (char *) malloc (p - name + 1);
+              memcpy (n, name, p - name);
+              n[p - name] = '\0';
+              return n;
+            }
+        }
+
+      /* bad formed member name:
+       just return it */
+
+      return strdup (name);
+    }
+  else
+    return NULL;
+}
+
+size_t
+ar_get_header (struct ar_hdr *hdr, FILE * libfp, char **p_obj_name)
 {
   char header[ARHDR_LEN];
   char buf[AR_DATE_LEN + 1];
+  char *obj_name;
+  size_t size;
 
-  if (fread (header, 1, sizeof (header), libfp) != sizeof (header) ||
-      memcmp (header + AR_FMAG_OFFSET, ARFMAG, AR_FMAG_LEN) != 0)
+  if (fread (header, 1, sizeof (header), libfp) != sizeof (header)
+      || memcmp (header + AR_FMAG_OFFSET, ARFMAG, AR_FMAG_LEN) != 0)
     {
       /* not an ar archive */
-      return NULL;
+      return 0;
     }
 
   memcpy (hdr->ar_name, &header[AR_NAME_OFFSET], AR_NAME_LEN);
@@ -81,9 +206,26 @@ ar_get_header (struct ar_hdr *hdr, FILE * libfp)
   buf[AR_SIZE_LEN] = '\0';
   hdr->ar_size = strtol (buf, NULL, 0);
 
-  return hdr;
+  obj_name = get_member_name (hdr->ar_name, &size, p_obj_name != NULL, libfp);
+
+  if (p_obj_name != NULL)
+    *p_obj_name = obj_name;
+
+  /* treat BSD appended real file name as a part of the header */
+  hdr->ar_size -= size;
+
+  return size + ARHDR_LEN;
 }
 
+static char *
+get_member_name_by_offset (FILE * fp, long offset)
+{
+  struct ar_hdr hdr;
+  char *name;
+
+  fseek (fp, offset, SEEK_SET);
+  return (ar_get_header (&hdr, fp, &name) != 0) ? name : NULL;
+}
 
 struct symbol_s
   {
@@ -103,6 +245,9 @@ add_symbol (const char *sym, void *param)
   if ((s = (struct symbol_s *) malloc (sizeof (struct symbol_s))) == NULL)
     return 0;
 
+  if (verbose)
+    printf ("%s\n", sym);
+
   s->name = strdup (sym);
   s->offset = offset - first_member_offset;
   s->next = NULL;
@@ -212,21 +357,152 @@ enum_symbols (FILE * fp, long size, int (*func) (const char *sym, void *param),
   return 0;
 }
 
+
+static int
+process_symbol_table (struct ar_hdr *hdr, FILE *fp)
+{
+  if (print_index)
+    {
+      char *buf, *po, *ps;
+      int i;
+      long nsym;
+      long pos;
+
+      printf ("Archive index:\n");
+
+      buf = (char *) malloc (hdr->ar_size);
+
+      if (fread (buf, 1, hdr->ar_size, fp) != hdr->ar_size)
+        {
+          free (buf);
+          return 0;
+        }
+
+      pos = ftell (fp);
+
+      nsym = sgetl (buf);
+
+      po = buf + 4;
+      ps = po + nsym * 4;
+
+      for (i = 0; i < nsym; ++i)
+        {
+          char *obj;
+
+          offset = sgetl (po);
+          po += 4;
+
+          printf ("%s in ", ps);
+          ps += strlen(ps) + 1;
+
+          obj = get_member_name_by_offset (fp, offset);  /* member name */
+          printf ("%s\n", obj);
+          free (obj);
+
+        }
+      free (buf);
+
+      fseek (fp, pos, SEEK_SET);
+
+      putchar ('\n');
+    }
+  else
+    {
+      /* skip the symbol table */
+      fseek (fp, hdr->ar_size + (hdr->ar_size & 1), SEEK_CUR);
+    }
+
+  return 1;
+}
+
+static int
+process_bsd_symbol_table (struct ar_hdr *hdr, FILE *fp)
+{
+  if (print_index)
+    {
+      char *buf, *po, *ps;
+      int i;
+      long tablesize;
+      long nsym;
+      long pos;
+
+      printf ("Archive index:\n");
+
+      buf = (char *) malloc (hdr->ar_size);
+
+      if (fread (buf, 1, hdr->ar_size, fp) != hdr->ar_size)
+        {
+          free (buf);
+          return 0;
+        }
+
+      pos = ftell (fp);
+
+      tablesize = sgetl (buf);
+      nsym = tablesize / 8;
+
+      po = buf + 4;
+
+      ps = po + tablesize + 4;
+
+      for (i = 0; i < nsym; ++i)
+        {
+          char *obj;
+          long sym;
+
+          sym = sgetl (po);
+          po += 4;
+          offset = sgetl (po);
+          po += 4;
+
+          printf ("%s in ", ps + sym);
+
+          obj = get_member_name_by_offset (fp, offset);  /* member name */
+          printf ("%s\n", obj);
+          free (obj);
+        }
+      free (buf);
+
+      fseek (fp, pos, SEEK_SET);
+
+      putchar ('\n');
+    }
+  else
+    {
+      /* skip the symbol table */
+      fseek (fp, hdr->ar_size + (hdr->ar_size & 1), SEEK_CUR);
+    }
+
+  return 1;
+}
+
 int
 get_symbols (FILE * fp, const char *archive)
 {
   struct ar_hdr hdr;
+  char *name;
 
-  if (!is_ar (fp) || !ar_get_header (&hdr, fp))
+  if (!is_ar (fp) || !ar_get_header (&hdr, fp, &name))
     {
       fprintf (stderr, "asranlib: %s: File format not recognized\n", archive);
       exit (1);
     }
 
-  if (AR_IS_SYMBOL_TABLE (hdr))
+  if (AR_IS_SYMBOL_TABLE (name))
     {
-      /* skip the symbol table */
-      fseek (fp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR);
+      free (name);
+
+      process_symbol_table (&hdr, fp);
+      if (!ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL))
+        return 1;
+    }
+  else if (AR_IS_BSD_SYMBOL_TABLE (name))
+    {
+      free (name);
+
+      process_bsd_symbol_table (&hdr, fp);
+      if (!ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL))
+        return 1;
     }
 
   first_member_offset = ftell (fp) - ARHDR_LEN;
@@ -236,32 +512,49 @@ get_symbols (FILE * fp, const char *archive)
     {
       if (is_rel (fp))
         {
-          long mdule_offset = ftell (fp);
+          if (verbose || list)
+            {
+              printf ("%s%s\n", name, verbose ? ":" : "");
+              free (name);
+            }
 
-          offset = mdule_offset - ARHDR_LEN;
+          if (!list)
+            {
+              long mdule_offset = ftell (fp);
 
-          enum_symbols (fp, hdr.ar_size, add_symbol, NULL);
+              offset = mdule_offset - ARHDR_LEN;
 
-          fseek (fp, mdule_offset + hdr.ar_size, SEEK_SET);
+              enum_symbols (fp, hdr.ar_size, add_symbol, NULL);
 
-          if (hdr.ar_size & 1)
-            {
-              int c = getc (fp);
-              assert (c == EOF || c == '\n');
+              fseek (fp, mdule_offset + hdr.ar_size, SEEK_SET);
+
+              if (hdr.ar_size & 1)
+                {
+                  int c = getc (fp);
+                  assert (c == EOF || c == '\n');
+                }
             }
+
+          if (verbose)
+            putchar ('\n');
         }
       else
         {
+          if (verbose || list)
+            {
+              fprintf (stderr, "asranlib: %s: File format not recognized\n", name);
+              free (name);
+            }
+
           /* skip if the member is not a .REL format */
           fseek (fp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR);
         }
     }
-  while (ar_get_header (&hdr, fp));
+  while (ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL));
 
   return 1;
 }
 
-
 void
 do_ranlib (const char *archive)
 {
@@ -276,25 +569,43 @@ do_ranlib (const char *archive)
 
   if (get_symbols (infp, archive))
     {
-      FILE *outfp = NULL;
+      FILE *outfp;
       struct symbol_s *symp;
       char buf[4];
-      int str_length = 0;
-      int pad = 0;
+      int str_length;
+      int pad;
       int nsym;
       int symtab_size;
       char tmpfile[] = "arXXXXXX";
 
-      if (NULL == mktemp (tmpfile) || NULL == (outfp = fopen (tmpfile, "wb")))
+#ifdef _WIN32
+      if (NULL == _mktemp (tmpfile) || NULL == (outfp = fopen (tmpfile, "wb")))
         {
           fclose (infp);
           fprintf (stderr, "asranlib: %s: ", tmpfile);
           perror (NULL);
           exit (1);
         }
+#else
+      if ((pad = mkstemp (tmpfile)) < 0)
+        {
+          fclose (infp);
+          fprintf (stderr, "asranlib: %s: ", tmpfile);
+          perror (NULL);
+          exit (1);
+        }
+
+      if (NULL == (outfp = fdopen (pad, "wb")))
+        {
+          close (pad);
+          fclose (infp);
+          perror ("asranlib");
+          exit (1);
+        }
+#endif
 
       /* calculate the size of symbol table */
-      for (nsym = 0, symp = symlist; symp; ++nsym, symp = symp->next)
+      for (str_length = 0, nsym = 0, symp = symlist; symp; ++nsym, symp = symp->next)
         {
           str_length += strlen (symp->name) + 1;
         }
@@ -355,6 +666,11 @@ do_ranlib (const char *archive)
     fclose (infp);
 }
 
+void
+do_verbose (void)
+{
+  verbose = 1;
+}
 
 void
 print_version (void)
@@ -363,35 +679,64 @@ print_version (void)
   exit (0);
 }
 
-
 void
-usage (void)
+do_list (void)
 {
-  printf ("Usage: asranlib [options] archive\n"
-    " Generate an index to speed access to archives\n"
-    " The options are:\n"
-    "  -h --help                    Print this help message\n"
-    "  -V --version                 Print version information\n"
-    "asranlib: supported targets: asxxxx\n");
+  list = 1;
+}
 
-  exit (1);
+void
+print_armap (void)
+{
+  print_index = 1;
 }
 
+void usage (void);
 
 struct opt_s
   {
-    const char *opt;
+    const char *short_opt;
+    const char *long_opt;
     void (*optfnc) (void);
+    const char *comment;
   }
 opts[] =
   {
-    { "-v", &print_version, },
-    { "-V", &print_version, },
-    { "--version", &print_version, },
-    { "-h", &usage, },
-    { "--help", &usage, },
+    { "-v", "--verbose", &do_verbose, "Be more verbose about the operation" },
+    { "-V", "--version", &print_version, "Print this help message" },
+    { "-h", "--help", &usage, "Print version information" },
+    { "-t", "--list", &do_list, "List the contents of an archive" },
+    { "-s", "--print-armap", &print_armap, "Print the archive index" },
   };
 
+void
+usage (void)
+{
+  int i;
+
+  printf ("Usage: asranlib [options] archive\n"
+    " Generate an index to speed access to archives\n"
+    " The options are:\n");
+
+  for (i = 0; i < NELEM (opts); ++i)
+    {
+      int len = 3;
+      printf ("  %s ", (NULL != opts[i].short_opt) ? opts[i].short_opt : "  ");
+      if (NULL != opts[i].long_opt)
+        {
+          printf ("%s ", opts[i].long_opt);
+          len += strlen (opts[i].long_opt);
+        }
+
+      while (len++ < 32)
+        putchar (' ');
+      printf ("%s\n", opts[i].comment);
+    }
+
+  printf ("asranlib: supported targets: asxxxx\n");
+
+  exit (1);
+}
 
 void
 process_options (int argc, char *argv[])
@@ -413,26 +758,28 @@ process_options (int argc, char *argv[])
 
           for (i = 0; i < NELEM (opts); ++i)
             {
-              if (0 == strcmp (*argp, opts[i].opt))
+              if (0 == strcmp (*argp, opts[i].short_opt) || 0 == strcmp (*argp, opts[i].long_opt))
                 {
                   if (NULL != opts[i].optfnc)
                     {
                       (*opts[i].optfnc) ();
-                      continue;
+                      break;
                     }
                 }
             }
         }
 
-      do_ranlib (*argp);
-      ++narch;
+      else
+        {
+          do_ranlib (*argp);
+          ++narch;
+        }
     }
 
   if (!narch)
     usage ();
 }
 
-
 int
 main (int argc, char *argv[])
 {
index b137ffde58a45394a69d9411f4418daf3f9abdc4..3334b29dcfe17c857d3d9c88dc63d4e0a2782151 100644 (file)
@@ -6,7 +6,7 @@
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 /*
  * With contributions for the
@@ -62,17 +61,139 @@ is_ar (FILE * libfp)
   return ret;
 }
 
-static struct ar_hdr *
-ar_get_header (struct ar_hdr *hdr, FILE * libfp)
+static char *sym_tab;
+static int sym_tab_size;
+
+char *
+get_member_name (char *name, size_t *p_size, int allocate, FILE * libfp)
+{
+  *p_size = 0;
+
+  if (0 == memcmp (name, "#1/", 3))
+    {
+      char *p;
+      size_t len = strtoul (&name [3], &p, 10);
+      if (p > &name [3])
+        {
+          /* BSD appends real file name to the file header */
+          if (p_size != NULL)
+            *p_size = len;
+
+          if (allocate)
+            {
+              char *n = (char *) malloc (len);
+              if (fread (n, 1, len, libfp) != len)
+                {
+                  /* not an ar archive or broken ar archive */
+                  return NULL;
+                }
+              else
+                return n;
+            }
+          else
+            {
+              /* just advance the file pointer */
+              fseek (libfp, len, SEEK_CUR);
+              return NULL;
+            }
+        }
+      else
+        {
+          /* not an ar archive or broken ar archive */
+          return NULL;
+        }
+    }
+  else if (allocate)
+    {
+      if (name[0] == '/')
+        {
+          if (NULL != sym_tab)
+            {
+              char *p;
+
+              int name_offset = strtol (++name, &p, 0);
+              if (p != name && name_offset < sym_tab_size)
+                {
+                  int len = p - name + 1;
+                  while (len < AR_NAME_LEN && name[len++] == ' ')
+                    ;
+                  if (len == AR_NAME_LEN)
+                    {
+                      char *n;
+
+                      /* long name: get it from the symbol table */
+                      name = &sym_tab[name_offset];
+                      for (p = name; *p != '/' && *p != '\n'; ++p)
+                        assert (p < &sym_tab[sym_tab_size]);
+
+                      if (p[0] != '/' || p[1] != '\n')
+                        while (*++p != '\n')
+                          assert (p < &sym_tab[sym_tab_size]);
+
+                      n = (char *) malloc (p - name + 1);
+                      memcpy (n, name, p - name);
+                      n[p - name] = '\0';
+                      return n;
+                    }
+                }
+            }
+        }
+      else
+        {
+          char *p = strrchr (name, '/');
+
+          if (NULL != p)
+            {
+              int len = p - name;
+              while (name[++len] == ' ')
+                ;
+              if (len == AR_NAME_LEN)
+                {
+                  char *n = (char *) malloc (p - name + 1);
+                  memcpy (n, name, p - name);
+                  n[p - name] = '\0';
+                  return n;
+                }
+            }
+          else
+            {
+              /* BSD formed member name:
+                 trim trailing spaces */
+              char *n;
+
+              p = name + AR_NAME_LEN;
+              while (*--p == ' ' && p >= name)
+                ;
+              ++p;
+              n = (char *) malloc (p - name + 1);
+              memcpy (n, name, p - name);
+              n[p - name] = '\0';
+              return n;
+            }
+        }
+
+      /* bad formed member name:
+       just return it */
+
+      return strdup (name);
+    }
+  else
+    return NULL;
+}
+
+size_t
+ar_get_header (struct ar_hdr *hdr, FILE * libfp, char **p_obj_name)
 {
   char header[ARHDR_LEN];
   char buf[AR_DATE_LEN + 1];
+  char *obj_name;
+  size_t size;
 
   if (fread (header, 1, sizeof (header), libfp) != sizeof (header)
       || memcmp (header + AR_FMAG_OFFSET, ARFMAG, AR_FMAG_LEN) != 0)
     {
       /* not an ar archive */
-      return NULL;
+      return 0;
     }
 
   memcpy (hdr->ar_name, &header[AR_NAME_OFFSET], AR_NAME_LEN);
@@ -98,122 +219,26 @@ ar_get_header (struct ar_hdr *hdr, FILE * libfp)
   buf[AR_SIZE_LEN] = '\0';
   hdr->ar_size = strtol (buf, NULL, 0);
 
-  return hdr;
-}
+  obj_name = get_member_name (hdr->ar_name, &size, p_obj_name != NULL, libfp);
 
-static char *sym_tab;
-static int sym_tab_size;
+  if (p_obj_name != NULL)
+    *p_obj_name = obj_name;
 
-static void
-loadfile_ar (struct lbfile *lbfh)
-{
-  FILE *fp;
+  /* treat BSD appended real file name as a part of the header */
+  hdr->ar_size -= size;
 
-#ifdef __CYGWIN__
-  char posix_path[PATH_MAX];
-  void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path);
-  cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path);
-  fp = fopen (posix_path, "rb");
-#else
-  fp = fopen (lbfh->libspc, "rb");
-#endif
-
-  if (fp != NULL)
-    {
-      struct ar_hdr hdr;
-
-      fseek (fp, lbfh->offset, SEEK_SET);
-      if (ar_get_header (&hdr, fp))
-        {
-          D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
-          load_rel (fp, hdr.ar_size);
-          fclose (fp);
-        }
-      else
-        {
-          fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil);
-          fclose (fp);
-          lkexit (1);
-        }
-    }
-  else
-    {
-      fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc);
-      lkexit (1);
-    }
+  return size + ARHDR_LEN;
 }
 
 #if INDEXLIB
-char *
-get_member_name (char *name)
-{
-  if (name[0] == '/')
-    {
-      if (NULL != sym_tab)
-        {
-          char *p;
-
-          int name_offset = strtol (++name, &p, 0);
-          if (p != name && name_offset < sym_tab_size)
-            {
-              int len = p - name + 1;
-              while (len < AR_NAME_LEN && name[len++] == ' ')
-                ;
-              if (len == AR_NAME_LEN)
-                {
-                  char *n;
-
-                  /* long name: get it from the symbol table */
-                  name = &sym_tab[name_offset];
-                  for (p = name; *p != '/' && *p != '\n'; ++p)
-                    assert (p < &sym_tab[sym_tab_size]);
-
-                  if (p[0] != '/' || p[1] != '\n')
-                    while (*++p != '\n')
-                      assert (p < &sym_tab[sym_tab_size]);
-
-                  n = (char *) malloc (p - name + 1);
-                  memcpy (n, name, p - name);
-                  n[p - name] = '\0';
-                  return n;
-                }
-            }
-        }
-    }
-  else
-    {
-      char *p = strrchr (name, '/');
-
-      if (NULL != p)
-        {
-          int len = p - name;
-          while (name[++len] == ' ')
-            ;
-          if (len == AR_NAME_LEN)
-            {
-              char *n = (char *) malloc (p - name + 1);
-              memcpy (n, name, p - name);
-              n[p - name] = '\0';
-              return n;
-            }
-        }
-    }
-
-  /* bad formed member name:
-     just return it */
-
-  return strdup (name);
-}
-
 static char *
 get_member_name_by_offset (FILE * fp, long offset)
 {
   struct ar_hdr hdr;
+  char *name;
 
   fseek (fp, offset, SEEK_SET);
-
-  /* walk trough all archive members */
-  return (NULL != ar_get_header (&hdr, fp)) ? get_member_name (hdr.ar_name) : NULL;
+  return (ar_get_header (&hdr, fp, &name) != 0) ? name : NULL;
 }
 
 static pmlibraryfile
@@ -221,6 +246,7 @@ find_member_by_offset (const char *libspc, long offset)
 {
   pmlibraryfile p;
 
+  /* walk trough all archive members */
   for (p = libr; p; p = p->next)
     {
       if (0 == strcmp (libspc, p->libspc) && p->offset == offset)
@@ -234,24 +260,31 @@ static pmlibraryfile
 buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int type)
 {
   struct ar_hdr hdr;
+  char *obj_name;
+  size_t hdr_size;
 
   /* walk trough all archive members */
-  while (ar_get_header (&hdr, libfp))
+  while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
     {
-      if (AR_IS_SYMBOL_TABLE (hdr))
+      if (AR_IS_SYMBOL_TABLE (obj_name))
         {
           char *buf, *po, *ps;
           int i;
           long nsym;
+          long pos;
+
+          free (obj_name);
 
           buf = (char *) new (hdr.ar_size);
 
-          if ((off_t) fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
+          if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
             {
               free (buf);
               return This;
             }
 
+          pos = ftell (libfp);
+
           nsym = sgetl (buf);
 
           po = buf + 4;
@@ -268,8 +301,92 @@ buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int
               po += 4;
 
               sym = strdup (ps);
-              while (*ps++ != '\0')
-                ;
+              ps += strlen (ps) + 1;
+
+              if ((entry = find_member_by_offset (lbnh->libspc, offset)) != NULL)
+                {
+                  for (ThisSym = entry->symbols; ThisSym->next != NULL; ThisSym = ThisSym->next)
+                    ;
+                }
+              else
+                {
+                  /* Opened OK - create a new libraryfile object for it */
+                  if (This == NULL)
+                    {
+                      assert (libr == NULL);
+                      libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
+                    }
+                  else
+                    {
+                      This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
+                      This = This->next;
+                    }
+                  This->next = NULL;
+                  This->loaded = 0;
+                  This->libspc = lbnh->libspc;
+                  This->offset = offset;
+                  This->relfil = get_member_name_by_offset (libfp, offset);     /* member name */
+                  This->filspc = strdup (This->relfil); /* member file name */
+                  This->type = type;
+
+                  /* start a new linked list of symbols for this module. */
+                  This->symbols = ThisSym = NULL;
+                }
+
+              if (ThisSym == NULL)
+                ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
+              else
+                {
+                  ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
+                  ThisSym = ThisSym->next;
+                }
+              ThisSym->next = NULL;
+              ThisSym->name = sym;
+            }
+          free (buf);
+
+          fseek (libfp, pos, SEEK_SET);
+          break;
+        }
+      else if (AR_IS_BSD_SYMBOL_TABLE (obj_name))
+        {
+          char *buf, *po, *ps;
+          int i;
+          long nsym, tablesize;
+          long pos;
+
+          free (obj_name);
+
+          buf = (char *) new (hdr.ar_size);
+
+          if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
+            {
+              free (buf);
+              return This;
+            }
+
+          pos = ftell (libfp);
+
+          tablesize = sgetl (buf);
+          nsym = tablesize / 8;
+
+          po = buf + 4;
+
+          ps = po + tablesize + 4;
+
+          for (i = 0; i < nsym; ++i)
+            {
+              pmlibrarysymbol ThisSym;
+              char *sym;
+              long offset;
+              pmlibraryfile entry;
+
+              sym = ps + sgetl (po);
+              po += 4;
+              offset = sgetl (po);
+              po += 4;
+
+              sym = strdup (ps);
 
               if ((entry = find_member_by_offset (lbnh->libspc, offset)) != NULL)
                 {
@@ -313,16 +430,19 @@ buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int
             }
           free (buf);
 
+          fseek (libfp, pos, SEEK_SET);
           break;
         }
-      else if (AR_IS_STRING_TABLE (hdr))
+      else if (AR_IS_STRING_TABLE (obj_name))
         {
+          free (obj_name);
+
           if (sym_tab)
             free (sym_tab);
 
           sym_tab = (char *) new (hdr.ar_size);
 
-          if ((off_t) fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
+          if (fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
             {
               free (sym_tab);
               sym_tab_size = 0;
@@ -348,9 +468,9 @@ buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int
           This->next = NULL;
           This->loaded = -1;
           This->libspc = lbnh->libspc;
-          This->offset = moduleOffset - ARHDR_LEN;
+          This->offset = moduleOffset - hdr_size;
 
-          This->relfil = get_member_name (hdr.ar_name); /* member name */
+          This->relfil = obj_name;              /* member name */
           This->filspc = strdup (This->relfil); /* member file name */
 
           D ("  Indexing module: %s\n", This->relfil);
@@ -390,6 +510,8 @@ load_adb (FILE * libfp, struct lbfile *lbfh)
 {
   struct ar_hdr hdr;
   char *adb_name;
+  char *obj_name;
+  size_t hdr_size;
 
   /* check if it is a .rel file */
   if (0 != stricmp (&lbfh->relfil[strlen (lbfh->relfil) - 4], ".rel"))
@@ -409,10 +531,12 @@ load_adb (FILE * libfp, struct lbfile *lbfh)
 
 
   /* walk trough all archive members */
-  while (ar_get_header (&hdr, libfp))
+  while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
     {
-      if (AR_IS_STRING_TABLE (hdr))
+      if (AR_IS_STRING_TABLE (obj_name))
         {
+          free (obj_name);
+
           if (sym_tab)
             free (sym_tab);
 
@@ -426,8 +550,10 @@ load_adb (FILE * libfp, struct lbfile *lbfh)
             }
           sym_tab_size = hdr.ar_size;
         }
-      if (AR_IS_SYMBOL_TABLE (hdr) || 0 != stricmp (get_member_name (hdr.ar_name), adb_name))
+      if (AR_IS_SYMBOL_TABLE (obj_name) || 0 != stricmp (obj_name, adb_name))
         {
+          free (obj_name);
+
           /* skip the mamber */
           fseek (libfp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR);
         }
@@ -436,6 +562,8 @@ load_adb (FILE * libfp, struct lbfile *lbfh)
           long left = hdr.ar_size;
           char buf[4096];
 
+          free (obj_name);
+
           while (left)
             {
               size_t n = min (left, sizeof buf);
@@ -471,9 +599,10 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type)
 {
   struct ar_hdr hdr;
   int ret = 0;
+  size_t hdr_size;
 
   /* walk trough all archive members */
-  while (ar_get_header (&hdr, libfp))
+  while ((hdr_size = ar_get_header (&hdr, libfp, NULL)) != 0)
     {
       char filspc[PATH_MAX];
 
@@ -488,12 +617,14 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type)
 #endif
         }
 
-      if (AR_IS_SYMBOL_TABLE (hdr))
+      if (AR_IS_SYMBOL_TABLE (obj_name))
         {
           char *buf, *po, *ps;
           int i;
           long nsym;
 
+          free (obj_name);
+
           buf = (char *) new (hdr.ar_size);
 
           if ((off_t) fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
@@ -574,7 +705,95 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type)
 
           break;
         }
-      else if (AR_IS_STRING_TABLE (hdr))
+      else if (AR_IS_BSD_SYMBOL_TABLE (obj_name))
+        {
+          char *buf, *po, *ps;
+          int i;
+          long nsym, tablesize;
+
+          free (obj_name);
+
+          buf = (char *) new (hdr.ar_size);
+
+          if ((off_t) fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
+            {
+              free (buf);
+              return 0;
+            }
+
+          tablesize = sgetl (buf);
+          nsym = tablesize / 8;
+
+          po = buf + 4;
+
+          ps = po + tablesize + 4;
+
+          for (i = 0; i < nsym; ++i)
+            {
+              char *sym;
+              long offset;
+
+              sym = ps + sgetl (po);
+              po += 4;
+              offset = sgetl (po);
+              po += 4;
+
+              if (0 == strcmp (name, sym))
+                {
+                  fseek (libfp, offset, SEEK_SET);
+                  if (ar_get_header (&hdr, libfp))
+                    {
+                      sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
+
+                      /* If this module has been loaded already don't load it again. */
+                      if (!is_module_loaded (filspc))
+                        {
+                          struct lbfile *lbfh, *lbf;
+
+                          lbfh = (struct lbfile *) new (sizeof (struct lbfile));
+                          lbfh->libspc = strdup (lbnh->libspc);
+                          lbfh->relfil = strdup (hdr.ar_name);
+                          lbfh->filspc = strdup (filspc);
+                          lbfh->offset = offset;
+                          lbfh->type = type;
+
+                          if (lbfhead == NULL)
+                            {
+                              lbfhead = lbfh;
+                            }
+                          else
+                            {
+                              for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
+                                ;
+
+                              lbf->next = lbfh;
+                            }
+
+                          D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
+                          load_rel (libfp, hdr.ar_size);
+                          ///* if cdb information required & .adb file present */
+                          //if (dflag && dfp)
+                          //  {
+                          //    if (load_adb(FILE *libfp, struct lbfile *lbfh))
+                          //      SaveLinkedFilePath (filspc);
+                          //  }
+                          ret = 1;
+                          break;
+                        }
+                    }
+                  else
+                    {
+                      fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbnh->libspc, name);
+                      fclose (libfp);
+                      lkexit (1);
+                    }
+                }
+            }
+          free (buf);
+
+          break;
+        }
+      else if (AR_IS_STRING_TABLE (obj_name))
         {
           if (sym_tab)
             free (sym_tab);
@@ -599,7 +818,7 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type)
           sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
 
           /* Opened OK - create a new libraryfile object for it */
-          ret = add_rel_file (name, lbnh, hdr.ar_name, filspc, moduleOffset - ARHDR_LEN, libfp, hdr.ar_size, type);
+          ret = add_rel_file (name, lbnh, hdr.ar_name, filspc, moduleOffset - hdr_size, libfp, hdr.ar_size, type);
           ///* if cdb information required & .adb file present */
           //if (dflag && dfp)
           //  {
@@ -630,6 +849,45 @@ fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type)
 }
 #endif
 
+static void
+loadfile_ar (struct lbfile *lbfh)
+{
+  FILE *fp;
+
+#ifdef __CYGWIN__
+  char posix_path[PATH_MAX];
+  void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path);
+  cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path);
+  fp = fopen (posix_path, "rb");
+#else
+  fp = fopen (lbfh->libspc, "rb");
+#endif
+
+  if (fp != NULL)
+    {
+      struct ar_hdr hdr;
+
+      fseek (fp, lbfh->offset, SEEK_SET);
+      if (ar_get_header (&hdr, fp, NULL) != 0)
+        {
+          D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
+          load_rel (fp, hdr.ar_size);
+          fclose (fp);
+        }
+      else
+        {
+          fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil);
+          fclose (fp);
+          lkexit (1);
+        }
+    }
+  else
+    {
+      fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc);
+      lkexit (1);
+    }
+}
+
 struct aslib_target aslib_target_ar = {
   &is_ar,
 #ifdef INDEXLIB
index 748c7f44a79e76b4e5a38d4d9dceb7015337b51b..af77754bfd2a66cc0bf07a6e20b776769abe679a 100644 (file)
@@ -4,7 +4,7 @@
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -13,8 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #ifndef __LKAR_H
 #define __LKAR_H
@@ -61,11 +60,16 @@ typedef _off_t off_t;
 
 #define ARHDR_LEN (AR_NAME_LEN + AR_DATE_LEN + AR_UID_LEN + AR_GID_LEN + AR_MODE_LEN + AR_SIZE_LEN + AR_FMAG_LEN)
 
-#define AR_SYMBOL_TABLE_NAME "/               "
-#define AR_STRING_TABLE_NAME "//              "
+#define AR_SYMBOL_TABLE_NAME            "/               "
+#define AR_STRING_TABLE_NAME            "//              "
 
-#define AR_IS_SYMBOL_TABLE(hdr) (0 == strcmp((hdr).ar_name, AR_SYMBOL_TABLE_NAME))
-#define AR_IS_STRING_TABLE(hdr) (0 == strcmp((hdr).ar_name, AR_STRING_TABLE_NAME))
+#define AR_BSD_SYMBOL_TABLE_NAME        "__.SYMDEF       "
+#define AR_BSD_SORTED_SYMBOL_TABLE_NAME "__.SYMDEF SORTED"
+
+#define AR_IS_SYMBOL_TABLE(name) (0 == strcmp((name), AR_SYMBOL_TABLE_NAME))
+#define AR_IS_STRING_TABLE(name) (0 == strcmp((name), AR_STRING_TABLE_NAME))
+
+#define AR_IS_BSD_SYMBOL_TABLE(name) (0 == strcmp((name), AR_BSD_SYMBOL_TABLE_NAME) || 0 == strcmp((name), AR_BSD_SORTED_SYMBOL_TABLE_NAME))
 
 
 struct ar_hdr                     /* archive member header */