cdc3077bf342db47bff42d507da4a00940023085
[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           free (obj_name);
458
459           /* Opened OK - create a new libraryfile object for it */
460           if (This == NULL)
461             {
462               assert (libr == NULL);
463               libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
464             }
465           else
466             {
467               This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
468               This = This->next;
469             }
470           This->next = NULL;
471           This->loaded = -1;
472           This->libspc = lbnh->libspc;
473           This->offset = moduleOffset - hdr_size;
474
475           This->relfil = obj_name;              /* member name */
476           This->filspc = strdup (This->relfil); /* member file name */
477
478           D ("  Indexing module: %s\n", This->relfil);
479
480           This->type = type;
481
482           /* start a new linked list of symbols for this module. */
483           This->symbols = NULL;
484
485           add_rel_index (libfp, hdr.ar_size, This);
486
487           fseek (libfp, moduleOffset + hdr.ar_size, SEEK_SET);
488         }
489
490       if (hdr.ar_size & 1)
491         {
492           int c = getc (libfp);
493           assert (c == EOF || c == '\n');
494         }
495     }
496
497   if (NULL != sym_tab)
498     {
499       free (sym_tab);
500       sym_tab = NULL;
501       sym_tab_size = 0;
502     }
503
504   return This;
505 }
506
507 #else
508
509 #if 0
510 static int
511 load_adb (FILE * libfp, struct lbfile *lbfh)
512 {
513   struct ar_hdr hdr;
514   char *adb_name;
515   char *obj_name;
516   size_t hdr_size;
517
518   /* check if it is a .rel file */
519   if (0 != stricmp (&lbfh->relfil[strlen (lbfh->relfil) - 4], ".rel"))
520     return 0;
521
522
523   adb_name = (char *) new (strlen (lbfh->relfil) + 1);
524   memcpy (adb_name, lbfh->relfil, strlen (lbfh->relfil) - 4);
525   memcpy (&adb_name[strlen (lbfh->relfil) - 4], ".adb", 5);
526
527   if (!is_ar (libfp))
528     {
529       fprintf (stderr, "?ASlink-Error-%s is not an archive\n", lbfh->libspc);
530       fclose (libfp);
531       lkexit (1);
532     }
533
534
535   /* walk trough all archive members */
536   while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
537     {
538       if (AR_IS_STRING_TABLE (obj_name))
539         {
540           free (obj_name);
541
542           if (sym_tab)
543             free (sym_tab);
544
545           sym_tab = (char *) new (hdr.ar_size);
546
547           if ((off_t) fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
548             {
549               free (sym_tab);
550               sym_tab_size = 0;
551               return 0;
552             }
553           sym_tab_size = hdr.ar_size;
554         }
555       if (AR_IS_SYMBOL_TABLE (obj_name) || 0 != stricmp (obj_name, adb_name))
556         {
557           free (obj_name);
558
559           /* skip the mamber */
560           fseek (libfp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR);
561         }
562       else
563         {
564           long left = hdr.ar_size;
565           char buf[4096];
566
567           free (obj_name);
568
569           while (left)
570             {
571               size_t n = min (left, sizeof buf);
572
573               if (fread (buf, 1, n, libfp) != n)
574                 {
575                   assert (0);
576                 }
577
578               fwrite (buf, 1, n, dfp);
579
580               left -= n;
581             }
582
583           if (hdr.ar_size & 1)
584             {
585               int c = getc (libfp);
586               assert (c == EOF || c == '\n');
587             }
588
589           free (adb_name);
590           return 1;
591         }
592     }
593
594   free (adb_name);
595   return 0;
596 }
597 #endif
598
599 static int
600 fndsym_ar (const char *name, struct lbname *lbnh, FILE * libfp, int type)
601 {
602   struct ar_hdr hdr;
603   int ret = 0;
604   size_t hdr_size;
605   char *obj_name;
606
607   /* walk trough all archive members */
608   while ((hdr_size = ar_get_header (&hdr, libfp, &obj_name)) != 0)
609     {
610       char filspc[PATH_MAX];
611
612       if (lbnh->path != NULL)
613         {
614           strcpy (filspc, lbnh->path);
615 #ifdef  OTHERSYSTEM
616           if (*filspc != '\0' && (filspc[strlen (filspc) - 1] != '/') && (filspc[strlen (filspc) - 1] != LKDIRSEP))
617             {
618               strcat (filspc, LKDIRSEPSTR);
619             }
620 #endif
621         }
622
623       if (AR_IS_SYMBOL_TABLE (obj_name))
624         {
625           char *buf, *po, *ps;
626           int i;
627           long nsym;
628
629           free (obj_name);
630
631           buf = (char *) new (hdr.ar_size);
632
633           if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
634             {
635               free (buf);
636               return 0;
637             }
638
639           nsym = sgetl (buf);
640
641           po = buf + 4;
642           ps = po + nsym * 4;
643
644           for (i = 0; i < nsym; ++i)
645             {
646               char *sym;
647               long offset;
648
649               offset = sgetl (po);
650               po += 4;
651
652               sym = ps;
653               while (*ps++ != '\0')
654                 ;
655
656               if (0 == strcmp (name, sym))
657                 {
658                   fseek (libfp, offset, SEEK_SET);
659                   if (ar_get_header (&hdr, libfp, NULL))
660                     {
661                       sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
662
663                       /* If this module has been loaded already don't load it again. */
664                       if (!is_module_loaded (filspc))
665                         {
666                           struct lbfile *lbfh, *lbf;
667
668                           lbfh = (struct lbfile *) new (sizeof (struct lbfile));
669                           lbfh->libspc = strdup (lbnh->libspc);
670                           lbfh->relfil = strdup (hdr.ar_name);
671                           lbfh->filspc = strdup (filspc);
672                           lbfh->offset = offset;
673                           lbfh->type = type;
674
675                           if (lbfhead == NULL)
676                             {
677                               lbfhead = lbfh;
678                             }
679                           else
680                             {
681                               for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
682                                 ;
683
684                               lbf->next = lbfh;
685                             }
686
687                           D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
688                           load_rel (libfp, hdr.ar_size);
689                           ///* if cdb information required & .adb file present */
690                           //if (dflag && dfp)
691                           //  {
692                           //    if (load_adb(FILE *libfp, struct lbfile *lbfh))
693                           //      SaveLinkedFilePath (filspc);
694                           //  }
695                           ret = 1;
696                           break;
697                         }
698                     }
699                   else
700                     {
701                       fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbnh->libspc, name);
702                       fclose (libfp);
703                       lkexit (1);
704                     }
705                 }
706             }
707           free (buf);
708
709           break;
710         }
711       else if (AR_IS_BSD_SYMBOL_TABLE (obj_name))
712         {
713           char *buf, *po, *ps;
714           int i;
715           long nsym, tablesize;
716
717           free (obj_name);
718
719           buf = (char *) new (hdr.ar_size);
720
721           if (fread (buf, 1, hdr.ar_size, libfp) != hdr.ar_size)
722             {
723               free (buf);
724               return 0;
725             }
726
727           tablesize = sgetl (buf);
728           nsym = tablesize / 8;
729
730           po = buf + 4;
731
732           ps = po + tablesize + 4;
733
734           for (i = 0; i < nsym; ++i)
735             {
736               char *sym;
737               long offset;
738
739               sym = ps + sgetl (po);
740               po += 4;
741               offset = sgetl (po);
742               po += 4;
743
744               if (0 == strcmp (name, sym))
745                 {
746                   fseek (libfp, offset, SEEK_SET);
747                   if (ar_get_header (&hdr, libfp, NULL))
748                     {
749                       sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
750
751                       /* If this module has been loaded already don't load it again. */
752                       if (!is_module_loaded (filspc))
753                         {
754                           struct lbfile *lbfh, *lbf;
755
756                           lbfh = (struct lbfile *) new (sizeof (struct lbfile));
757                           lbfh->libspc = strdup (lbnh->libspc);
758                           lbfh->relfil = strdup (hdr.ar_name);
759                           lbfh->filspc = strdup (filspc);
760                           lbfh->offset = offset;
761                           lbfh->type = type;
762
763                           if (lbfhead == NULL)
764                             {
765                               lbfhead = lbfh;
766                             }
767                           else
768                             {
769                               for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
770                                 ;
771
772                               lbf->next = lbfh;
773                             }
774
775                           D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
776                           load_rel (libfp, hdr.ar_size);
777                           ///* if cdb information required & .adb file present */
778                           //if (dflag && dfp)
779                           //  {
780                           //    if (load_adb(FILE *libfp, struct lbfile *lbfh))
781                           //      SaveLinkedFilePath (filspc);
782                           //  }
783                           ret = 1;
784                           break;
785                         }
786                     }
787                   else
788                     {
789                       fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbnh->libspc, name);
790                       fclose (libfp);
791                       lkexit (1);
792                     }
793                 }
794             }
795           free (buf);
796
797           break;
798         }
799       else if (AR_IS_STRING_TABLE (obj_name))
800         {
801           free (obj_name);
802
803           if (sym_tab)
804             free (sym_tab);
805
806           sym_tab = (char *) new (hdr.ar_size);
807
808           if (fread (sym_tab, 1, hdr.ar_size, libfp) != hdr.ar_size)
809             {
810               free (sym_tab);
811               sym_tab = NULL;
812               sym_tab_size = 0;
813               return 0;
814             }
815           sym_tab_size = hdr.ar_size;
816         }
817       else
818         {
819           long moduleOffset = ftell (libfp);
820
821           free (obj_name);
822
823           D ("  Module: %s\n", hdr.ar_name);
824
825           sprintf (&filspc[strlen (filspc)], "%s", hdr.ar_name);
826
827           /* Opened OK - create a new libraryfile object for it */
828           ret = add_rel_file (name, lbnh, hdr.ar_name, filspc, moduleOffset - hdr_size, libfp, hdr.ar_size, type);
829           ///* if cdb information required & .adb file present */
830           //if (dflag && dfp)
831           //  {
832           //    if (load_adb(FILE *libfp, struct lbfile *lbfh))
833           //      SaveLinkedFilePath (filspc);
834           //  }
835           if (ret)
836             break;
837
838           fseek (libfp, moduleOffset + hdr.ar_size, SEEK_SET);
839         }
840
841       if (hdr.ar_size & 1)
842         {
843           int c = getc (libfp);
844           assert (c == EOF || c == '\n');
845         }
846     }
847
848   if (NULL != sym_tab)
849     {
850       free (sym_tab);
851       sym_tab = NULL;
852       sym_tab_size = 0;
853     }
854
855   return ret;
856 }
857 #endif
858
859 static void
860 loadfile_ar (struct lbfile *lbfh)
861 {
862   FILE *fp;
863
864 #ifdef __CYGWIN__
865   char posix_path[PATH_MAX];
866   void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path);
867   cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path);
868   fp = fopen (posix_path, "rb");
869 #else
870   fp = fopen (lbfh->libspc, "rb");
871 #endif
872
873   if (fp != NULL)
874     {
875       struct ar_hdr hdr;
876
877       fseek (fp, lbfh->offset, SEEK_SET);
878       if (ar_get_header (&hdr, fp, NULL) != 0)
879         {
880           D ("Loading module %s from file %s.\n", hdr.ar_name, lbfh->libspc);
881           load_rel (fp, hdr.ar_size);
882           fclose (fp);
883         }
884       else
885         {
886           fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil);
887           fclose (fp);
888           lkexit (1);
889         }
890     }
891   else
892     {
893       fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc);
894       lkexit (1);
895     }
896 }
897
898 struct aslib_target aslib_target_ar = {
899   &is_ar,
900 #ifdef INDEXLIB
901   &buildlibraryindex_ar,
902 #else
903   &fndsym_ar,
904 #endif
905   &loadfile_ar,
906 };