* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / link / lkar.c
1 /* lkar.c - ar library format handling
2
3    Copyright (C) 1989-1995 Alan R. Baldwin
4    721 Berkeley St., Kent, Ohio 44240
5    Copyright (C) 2008-2009 Borut Razem, borut dot razem at siol dot net
6
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3, or (at your option) any
10 later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
19
20 /*
21  * With contributions for the
22  * object libraries from
23  * Ken Hornstein
24  * kenh@cmf.nrl.navy.mil
25  *
26  */
27
28 /*
29  * Extensions: P. Felber
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36
37 #include "aslink.h"
38 #include "lklibr.h"
39 #include "lkrel.h"
40 #include "lkar.h"
41
42
43 #ifndef max
44 # define max(a,b) ((a) > (b) ? (a) : (b))
45 #endif
46
47 #ifndef min
48 # define min(a,b) ((a) < (b) ? (a) : (b))
49 #endif
50
51
52 static int
53 is_ar (FILE * libfp)
54 {
55   char buf[SARMAG];
56   int ret;
57
58   if (!(ret = fread (buf, 1, sizeof (buf), libfp) == sizeof (buf) && memcmp (buf, ARMAG, SARMAG) == 0))
59     rewind (libfp);
60
61   return ret;
62 }
63
64 static char *sym_tab;
65 static int sym_tab_size;
66
67 char *
68 get_member_name (char *name, size_t *p_size, int allocate, FILE * libfp)
69 {
70   *p_size = 0;
71
72   if (0 == memcmp (name, "#1/", 3))
73     {
74       char *p;
75       size_t len = strtoul (&name [3], &p, 10);
76       if (p > &name [3])
77         {
78           /* BSD appends real file name to the file header */
79           if (p_size != NULL)
80             *p_size = len;
81
82           if (allocate)
83             {
84               char *n = (char *) malloc (len);
85               if (fread (n, 1, len, libfp) != len)
86                 {
87                   /* not an ar archive or broken ar archive */
88                   return NULL;
89                 }
90               else
91                 return n;
92             }
93           else
94             {
95               /* just advance the file pointer */
96               fseek (libfp, len, SEEK_CUR);
97               return NULL;
98             }
99         }
100       else
101         {
102           /* not an ar archive or broken ar archive */
103           return NULL;
104         }
105     }
106   else if (allocate)
107     {
108       if (name[0] == '/')
109         {
110           if (NULL != sym_tab)
111             {
112               char *p;
113
114               int name_offset = strtol (++name, &p, 0);
115               if (p != name && name_offset < sym_tab_size)
116                 {
117                   int len = p - name + 1;
118                   while (len < AR_NAME_LEN && name[len++] == ' ')
119                     ;
120                   if (len == AR_NAME_LEN)
121                     {
122                       char *n;
123
124                       /* long name: get it from the symbol table */
125                       name = &sym_tab[name_offset];
126                       for (p = name; *p != '/' && *p != '\n'; ++p)
127                         assert (p < &sym_tab[sym_tab_size]);
128
129                       if (p[0] != '/' || p[1] != '\n')
130                         while (*++p != '\n')
131                           assert (p < &sym_tab[sym_tab_size]);
132
133                       n = (char *) malloc (p - name + 1);
134                       memcpy (n, name, p - name);
135                       n[p - name] = '\0';
136                       return n;
137                     }
138                 }
139             }
140         }
141       else
142         {
143           char *p = strrchr (name, '/');
144
145           if (NULL != p)
146             {
147               int len = p - name;
148               while (name[++len] == ' ')
149                 ;
150               if (len == AR_NAME_LEN)
151                 {
152                   char *n = (char *) malloc (p - name + 1);
153                   memcpy (n, name, p - name);
154                   n[p - name] = '\0';
155                   return n;
156                 }
157             }
158           else
159             {
160               /* BSD formed member name:
161                  trim trailing spaces */
162               char *n;
163
164               p = name + AR_NAME_LEN;
165               while (*--p == ' ' && p >= name)
166                 ;
167               ++p;
168               n = (char *) malloc (p - name + 1);
169               memcpy (n, name, p - name);
170               n[p - name] = '\0';
171               return n;
172             }
173         }
174
175       /* bad formed member name:
176        just return it */
177
178       return strdup (name);
179     }
180   else
181     return NULL;
182 }
183
184 size_t
185 ar_get_header (struct ar_hdr *hdr, FILE * libfp, char **p_obj_name)
186 {
187   char header[ARHDR_LEN];
188   char buf[AR_DATE_LEN + 1];
189   char *obj_name;
190   size_t size;
191
192   if (fread (header, 1, sizeof (header), libfp) != sizeof (header)
193       || memcmp (header + AR_FMAG_OFFSET, ARFMAG, AR_FMAG_LEN) != 0)
194     {
195       /* not an ar archive */
196       return 0;
197     }
198
199   memcpy (hdr->ar_name, &header[AR_NAME_OFFSET], AR_NAME_LEN);
200   hdr->ar_name[AR_NAME_LEN] = '\0';
201
202   memcpy (buf, &header[AR_DATE_OFFSET], AR_DATE_LEN);
203   buf[AR_DATE_LEN] = '\0';
204   hdr->ar_date = strtol (buf, NULL, 0);
205
206   memcpy (buf, &header[AR_UID_OFFSET], AR_GID_LEN);
207   buf[AR_GID_LEN] = '\0';
208   hdr->ar_uid = (uid_t) strtol (buf, NULL, 0);
209
210   memcpy (buf, &header[AR_GID_OFFSET], AR_DATE_LEN);
211   buf[AR_DATE_LEN] = '\0';
212   hdr->ar_gid = (gid_t) strtol (buf, NULL, 0);
213
214   memcpy (buf, &header[AR_MODE_OFFSET], AR_MODE_LEN);
215   buf[AR_MODE_LEN] = '\0';
216   hdr->ar_mode = (mode_t) strtoul (buf, NULL, 0);
217
218   memcpy (buf, &header[AR_SIZE_OFFSET], AR_SIZE_LEN);
219   buf[AR_SIZE_LEN] = '\0';
220   hdr->ar_size = strtol (buf, NULL, 0);
221
222   obj_name = get_member_name (hdr->ar_name, &size, p_obj_name != NULL, libfp);
223
224   if (p_obj_name != NULL)
225     *p_obj_name = obj_name;
226
227   /* treat BSD appended real file name as a part of the header */
228   hdr->ar_size -= size;
229
230   return size + ARHDR_LEN;
231 }
232
233 #if INDEXLIB
234 static char *
235 get_member_name_by_offset (FILE * fp, long offset)
236 {
237   struct ar_hdr hdr;
238   char *name;
239
240   fseek (fp, offset, SEEK_SET);
241   return (ar_get_header (&hdr, fp, &name) != 0) ? name : NULL;
242 }
243
244 static pmlibraryfile
245 find_member_by_offset (const char *libspc, long offset)
246 {
247   pmlibraryfile p;
248
249   /* walk trough all archive members */
250   for (p = libr; p; p = p->next)
251     {
252       if (0 == strcmp (libspc, p->libspc) && p->offset == offset)
253         return p;
254     }
255
256   return NULL;
257 }
258
259 static pmlibraryfile
260 buildlibraryindex_ar (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int type)
261 {
262   struct ar_hdr hdr;
263   char *obj_name;
264   size_t hdr_size;
265
266   /* walk trough all archive members */
267   while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
268     {
269       if (AR_IS_SYMBOL_TABLE (obj_name))
270         {
271           char *buf, *po, *ps;
272           int i;
273           long nsym;
274           long pos;
275
276           free (obj_name);
277
278           buf = (char *) new (hdr.ar_size);
279
280           if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
281             {
282               free (buf);
283               return This;
284             }
285
286           pos = ftell (libfp);
287
288           nsym = sgetl (buf);
289
290           po = buf + 4;
291           ps = po + nsym * 4;
292
293           for (i = 0; i < nsym; ++i)
294             {
295               pmlibrarysymbol ThisSym;
296               char *sym;
297               long offset;
298               pmlibraryfile entry;
299
300               offset = sgetl (po);
301               po += 4;
302
303               sym = strdup (ps);
304               ps += strlen (ps) + 1;
305
306               if ((entry = find_member_by_offset (lbnh->libspc, offset)) != NULL)
307                 {
308                   for (ThisSym = entry->symbols; ThisSym->next != NULL; ThisSym = ThisSym->next)
309                     ;
310                 }
311               else
312                 {
313                   /* Opened OK - create a new libraryfile object for it */
314                   if (This == NULL)
315                     {
316                       assert (libr == NULL);
317                       libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
318                     }
319                   else
320                     {
321                       This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
322                       This = This->next;
323                     }
324                   This->next = NULL;
325                   This->loaded = 0;
326                   This->libspc = lbnh->libspc;
327                   This->offset = offset;
328                   This->relfil = get_member_name_by_offset (libfp, offset);     /* member name */
329                   This->filspc = strdup (This->relfil); /* member file name */
330                   This->type = type;
331
332                   /* start a new linked list of symbols for this module. */
333                   This->symbols = ThisSym = NULL;
334                 }
335
336               if (ThisSym == NULL)
337                 ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
338               else
339                 {
340                   ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
341                   ThisSym = ThisSym->next;
342                 }
343               ThisSym->next = NULL;
344               ThisSym->name = sym;
345             }
346           free (buf);
347
348           fseek (libfp, pos, SEEK_SET);
349           break;
350         }
351       else if (AR_IS_BSD_SYMBOL_TABLE (obj_name))
352         {
353           char *buf, *po, *ps;
354           int i;
355           long nsym, tablesize;
356           long pos;
357
358           free (obj_name);
359
360           buf = (char *) new (hdr.ar_size);
361
362           if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
363             {
364               free (buf);
365               return This;
366             }
367
368           pos = ftell (libfp);
369
370           tablesize = sgetl (buf);
371           nsym = tablesize / 8;
372
373           po = buf + 4;
374
375           ps = po + tablesize + 4;
376
377           for (i = 0; i < nsym; ++i)
378             {
379               pmlibrarysymbol ThisSym;
380               char *sym;
381               long offset;
382               pmlibraryfile entry;
383
384               sym = ps + sgetl (po);
385               po += 4;
386               offset = sgetl (po);
387               po += 4;
388
389               sym = strdup (ps);
390
391               if ((entry = find_member_by_offset (lbnh->libspc, offset)) != NULL)
392                 {
393                   for (ThisSym = entry->symbols; ThisSym->next != NULL; ThisSym = ThisSym->next)
394                     ;
395                 }
396               else
397                 {
398                   /* Opened OK - create a new libraryfile object for it */
399                   if (This == NULL)
400                     {
401                       assert (libr == NULL);
402                       libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
403                     }
404                   else
405                     {
406                       This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
407                       This = This->next;
408                     }
409                   This->next = NULL;
410                   This->loaded = 0;
411                   This->libspc = lbnh->libspc;
412                   This->offset = offset;
413                   This->relfil = get_member_name_by_offset (libfp, offset);     /* member name */
414                   This->filspc = strdup (This->relfil); /* member file name */
415                   This->type = type;
416
417                   /* start a new linked list of symbols for this module. */
418                   This->symbols = ThisSym = NULL;
419                 }
420
421               if (ThisSym == NULL)
422                 ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
423               else
424                 {
425                   ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
426                   ThisSym = ThisSym->next;
427                 }
428               ThisSym->next = NULL;
429               ThisSym->name = sym;
430             }
431           free (buf);
432
433           fseek (libfp, pos, SEEK_SET);
434           break;
435         }
436       else if (AR_IS_STRING_TABLE (obj_name))
437         {
438           free (obj_name);
439
440           if (sym_tab)
441             free (sym_tab);
442
443           sym_tab = (char *) new (hdr.ar_size);
444
445           if (fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
446             {
447               free (sym_tab);
448               sym_tab_size = 0;
449               return This;
450             }
451           sym_tab_size = hdr.ar_size;
452         }
453       else
454         {
455           long moduleOffset = ftell (libfp);
456
457           /* Opened OK - create a new libraryfile object for it */
458           if (This == NULL)
459             {
460               assert (libr == NULL);
461               libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
462             }
463           else
464             {
465               This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
466               This = This->next;
467             }
468           This->next = NULL;
469           This->loaded = -1;
470           This->libspc = lbnh->libspc;
471           This->offset = moduleOffset - hdr_size;
472
473           This->relfil = obj_name;              /* member name */
474           This->filspc = strdup (This->relfil); /* member file name */
475
476           D ("  Indexing module: %s\n", This->relfil);
477
478           This->type = type;
479
480           /* start a new linked list of symbols for this module. */
481           This->symbols = NULL;
482
483           add_rel_index (libfp, hdr.ar_size, This);
484
485           fseek (libfp, moduleOffset + hdr.ar_size, SEEK_SET);
486         }
487
488       if (hdr.ar_size & 1)
489         {
490           int c = getc (libfp);
491           assert (c == EOF || c == '\n');
492         }
493     }
494
495   if (NULL != sym_tab)
496     {
497       free (sym_tab);
498       sym_tab = NULL;
499       sym_tab_size = 0;
500     }
501
502   return This;
503 }
504
505 #else
506
507 #if 0
508 static int
509 load_adb (FILE * libfp, struct lbfile *lbfh)
510 {
511   struct ar_hdr hdr;
512   char *adb_name;
513   char *obj_name;
514   size_t hdr_size;
515
516   /* check if it is a .rel file */
517   if (0 != stricmp (&lbfh->relfil[strlen (lbfh->relfil) - 4], ".rel"))
518     return 0;
519
520
521   adb_name = (char *) new (strlen (lbfh->relfil) + 1);
522   memcpy (adb_name, lbfh->relfil, strlen (lbfh->relfil) - 4);
523   memcpy (&adb_name[strlen (lbfh->relfil) - 4], ".adb", 5);
524
525   if (!is_ar (libfp))
526     {
527       fprintf (stderr, "?ASlink-Error-%s is not an archive\n", lbfh->libspc);
528       fclose (libfp);
529       lkexit (1);
530     }
531
532
533   /* walk trough all archive members */
534   while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
535     {
536       if (AR_IS_STRING_TABLE (obj_name))
537         {
538           free (obj_name);
539
540           if (sym_tab)
541             free (sym_tab);
542
543           sym_tab = (char *) new (hdr.ar_size);
544
545           if ((off_t) fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
546             {
547               free (sym_tab);
548               sym_tab_size = 0;
549               return 0;
550             }
551           sym_tab_size = hdr.ar_size;
552         }
553       if (AR_IS_SYMBOL_TABLE (obj_name) || 0 != stricmp (obj_name, adb_name))
554         {
555           free (obj_name);
556
557           /* skip the mamber */
558           fseek (libfp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR);
559         }
560       else
561         {
562           long left = hdr.ar_size;
563           char buf[4096];
564
565           free (obj_name);
566
567           while (left)
568             {
569               size_t n = min (left, sizeof buf);
570
571               if (fread (buf, 1, n, libfp) != n)
572                 {
573                   assert (0);
574                 }
575
576               fwrite (buf, 1, n, dfp);
577
578               left -= n;
579             }
580
581           if (hdr.ar_size & 1)
582             {
583               int c = getc (libfp);
584               assert (c == EOF || c == '\n');
585             }
586
587           free (adb_name);
588           return 1;
589         }
590     }
591
592   free (adb_name);
593   return 0;
594 }
595 #endif
596
597 static int
598 fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type)
599 {
600   struct ar_hdr hdr;
601   int ret = 0;
602   size_t hdr_size;
603
604   /* walk trough all archive members */
605   while ((hdr_size = ar_get_header (&hdr, libfp, NULL)) != 0)
606     {
607       char filspc[PATH_MAX];
608
609       if (lbnh->path != NULL)
610         {
611           strcpy (filspc, lbnh->path);
612 #ifdef  OTHERSYSTEM
613           if (*filspc != '\0' && (filspc[strlen (filspc) - 1] != '/') && (filspc[strlen (filspc) - 1] != LKDIRSEP))
614             {
615               strcat (filspc, LKDIRSEPSTR);
616             }
617 #endif
618         }
619
620       if (AR_IS_SYMBOL_TABLE (obj_name))
621         {
622           char *buf, *po, *ps;
623           int i;
624           long nsym;
625
626           free (obj_name);
627
628           buf = (char *) new (hdr.ar_size);
629
630           if ((off_t) fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
631             {
632               free (buf);
633               return 0;
634             }
635
636           nsym = sgetl (buf);
637
638           po = buf + 4;
639           ps = po + nsym * 4;
640
641           for (i = 0; i < nsym; ++i)
642             {
643               char *sym;
644               long offset;
645
646               offset = sgetl (po);
647               po += 4;
648
649               sym = ps;
650               while (*ps++ != '\0')
651                 ;
652
653               if (0 == strcmp (name, sym))
654                 {
655                   fseek (libfp, offset, SEEK_SET);
656                   if (ar_get_header (&hdr, libfp))
657                     {
658                       sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
659
660                       /* If this module has been loaded already don't load it again. */
661                       if (!is_module_loaded (filspc))
662                         {
663                           struct lbfile *lbfh, *lbf;
664
665                           lbfh = (struct lbfile *) new (sizeof (struct lbfile));
666                           lbfh->libspc = strdup (lbnh->libspc);
667                           lbfh->relfil = strdup (hdr.ar_name);
668                           lbfh->filspc = strdup (filspc);
669                           lbfh->offset = offset;
670                           lbfh->type = type;
671
672                           if (lbfhead == NULL)
673                             {
674                               lbfhead = lbfh;
675                             }
676                           else
677                             {
678                               for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
679                                 ;
680
681                               lbf->next = lbfh;
682                             }
683
684                           D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
685                           load_rel (libfp, hdr.ar_size);
686                           ///* if cdb information required & .adb file present */
687                           //if (dflag && dfp)
688                           //  {
689                           //    if (load_adb(FILE *libfp, struct lbfile *lbfh))
690                           //      SaveLinkedFilePath (filspc);
691                           //  }
692                           ret = 1;
693                           break;
694                         }
695                     }
696                   else
697                     {
698                       fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbnh->libspc, name);
699                       fclose (libfp);
700                       lkexit (1);
701                     }
702                 }
703             }
704           free (buf);
705
706           break;
707         }
708       else if (AR_IS_BSD_SYMBOL_TABLE (obj_name))
709         {
710           char *buf, *po, *ps;
711           int i;
712           long nsym, tablesize;
713
714           free (obj_name);
715
716           buf = (char *) new (hdr.ar_size);
717
718           if ((off_t) fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
719             {
720               free (buf);
721               return 0;
722             }
723
724           tablesize = sgetl (buf);
725           nsym = tablesize / 8;
726
727           po = buf + 4;
728
729           ps = po + tablesize + 4;
730
731           for (i = 0; i < nsym; ++i)
732             {
733               char *sym;
734               long offset;
735
736               sym = ps + sgetl (po);
737               po += 4;
738               offset = sgetl (po);
739               po += 4;
740
741               if (0 == strcmp (name, sym))
742                 {
743                   fseek (libfp, offset, SEEK_SET);
744                   if (ar_get_header (&hdr, libfp))
745                     {
746                       sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
747
748                       /* If this module has been loaded already don't load it again. */
749                       if (!is_module_loaded (filspc))
750                         {
751                           struct lbfile *lbfh, *lbf;
752
753                           lbfh = (struct lbfile *) new (sizeof (struct lbfile));
754                           lbfh->libspc = strdup (lbnh->libspc);
755                           lbfh->relfil = strdup (hdr.ar_name);
756                           lbfh->filspc = strdup (filspc);
757                           lbfh->offset = offset;
758                           lbfh->type = type;
759
760                           if (lbfhead == NULL)
761                             {
762                               lbfhead = lbfh;
763                             }
764                           else
765                             {
766                               for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
767                                 ;
768
769                               lbf->next = lbfh;
770                             }
771
772                           D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
773                           load_rel (libfp, hdr.ar_size);
774                           ///* if cdb information required & .adb file present */
775                           //if (dflag && dfp)
776                           //  {
777                           //    if (load_adb(FILE *libfp, struct lbfile *lbfh))
778                           //      SaveLinkedFilePath (filspc);
779                           //  }
780                           ret = 1;
781                           break;
782                         }
783                     }
784                   else
785                     {
786                       fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbnh->libspc, name);
787                       fclose (libfp);
788                       lkexit (1);
789                     }
790                 }
791             }
792           free (buf);
793
794           break;
795         }
796       else if (AR_IS_STRING_TABLE (obj_name))
797         {
798           if (sym_tab)
799             free (sym_tab);
800
801           sym_tab = (char *) new (hdr.ar_size);
802
803           if ((off_t) fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
804             {
805               free (sym_tab);
806               sym_tab = NULL;
807               sym_tab_size = 0;
808               return 0;
809             }
810           sym_tab_size = hdr.ar_size;
811         }
812       else
813         {
814           long moduleOffset = ftell (libfp);
815
816           D ("  Module: %s\n", hdr.ar_name);
817
818           sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
819
820           /* Opened OK - create a new libraryfile object for it */
821           ret = add_rel_file (name, lbnh, hdr.ar_name, filspc, moduleOffset - hdr_size, libfp, hdr.ar_size, type);
822           ///* if cdb information required & .adb file present */
823           //if (dflag && dfp)
824           //  {
825           //    if (load_adb(FILE *libfp, struct lbfile *lbfh))
826           //      SaveLinkedFilePath (filspc);
827           //  }
828           if (ret)
829             break;
830
831           fseek (libfp, moduleOffset + hdr.ar_size, SEEK_SET);
832         }
833
834       if (hdr.ar_size & 1)
835         {
836           int c = getc (libfp);
837           assert (c == EOF || c == '\n');
838         }
839     }
840
841   if (NULL != sym_tab)
842     {
843       free (sym_tab);
844       sym_tab = NULL;
845       sym_tab_size = 0;
846     }
847
848   return ret;
849 }
850 #endif
851
852 static void
853 loadfile_ar (struct lbfile *lbfh)
854 {
855   FILE *fp;
856
857 #ifdef __CYGWIN__
858   char posix_path[PATH_MAX];
859   void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path);
860   cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path);
861   fp = fopen (posix_path, "rb");
862 #else
863   fp = fopen (lbfh->libspc, "rb");
864 #endif
865
866   if (fp != NULL)
867     {
868       struct ar_hdr hdr;
869
870       fseek (fp, lbfh->offset, SEEK_SET);
871       if (ar_get_header (&hdr, fp, NULL) != 0)
872         {
873           D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
874           load_rel (fp, hdr.ar_size);
875           fclose (fp);
876         }
877       else
878         {
879           fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil);
880           fclose (fp);
881           lkexit (1);
882         }
883     }
884   else
885     {
886       fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc);
887       lkexit (1);
888     }
889 }
890
891 struct aslib_target aslib_target_ar = {
892   &is_ar,
893 #ifdef INDEXLIB
894   &buildlibraryindex_ar,
895 #else
896   &fndsym_ar,
897 #endif
898   &loadfile_ar,
899 };