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