95f927d4063b23a7e723d12e85ccf590527c6721
[fw/sdcc] / as / link / lksdcclib.c
1 /* lksdcclib.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  *
11  * With contributions for the
12  * object libraries from
13  * Ken Hornstein
14  * kenh@cmf.nrl.navy.mil
15  *
16  */
17
18 /*
19  * Extensions: P. Felber
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "getline.h"
26 #include "aslink.h"
27 #include "lklibr.h"
28 #include "lkrel.h"
29
30 #define EQ(A,B) !strcmp((A),(B))
31 #define MAXLINE 254             /*when using getline */
32
33
34 static int
35 is_sdcclib (FILE * libfp)
36 {
37 #define SDCCLIB_MAGIC "<SDCCLIB>"
38 #define SDCCLIB_MAGIC_LEN (sizeof ("<SDCCLIB>") - 1)
39
40   char buf[SDCCLIB_MAGIC_LEN];
41
42   if (fread (buf, 1, sizeof (buf), libfp) == sizeof (buf) && memcmp (buf, SDCCLIB_MAGIC, SDCCLIB_MAGIC_LEN) == 0)
43     {
44       switch (getc (libfp))
45         {
46         case '\r':
47           if (getc (libfp) == '\n')
48             return 1;
49
50         case '\n':
51           return 1;
52         }
53     }
54   rewind (libfp);
55   return 0;
56 }
57
58 /* Load a .rel file embedded in a sdcclib file */
59 static void
60 LoadRel (char *libfname, FILE * libfp, char *ModName)
61 {
62   char str[NINPUT];
63   int state = 0;
64
65   while (getline (str, sizeof (str), libfp) != NULL)
66     {
67       switch (state)
68         {
69         case 0:
70           if (EQ (str, "<FILE>"))
71             {
72               getline (str, sizeof (str), libfp);
73               if (EQ (str, ModName))
74                 state = 1;
75               else
76                 {
77                   fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", libfname, ModName);
78                   lkexit (1);
79                 }
80             }
81           break;
82         case 1:
83           if (EQ (str, "<REL>"))
84             state = 2;
85           break;
86         case 2:
87           load_rel (libfp, -1);
88           break;
89         }
90     }
91 }
92
93 #ifdef INDEXLIB
94 static pmlibraryfile
95 buildlibraryindex_sdcclib (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int type)
96 {
97   char ModName[NCPS] = "";
98   char FLine[MAXLINE];
99   char buff[PATH_MAX];
100   int state = 0;
101   long IndexOffset = 0, FileOffset;
102   pmlibrarysymbol ThisSym = NULL;
103
104   while (getline (FLine, sizeof (FLine), libfp))
105     {
106       switch (state)
107         {
108         case 0:
109           if (EQ (FLine, "<INDEX>"))
110             {
111               /*The next line has the size of the index */
112               getline (FLine, sizeof (FLine), libfp);
113               IndexOffset = atol (FLine);
114               state = 1;
115             }
116           break;
117         case 1:
118           if (EQ (FLine, "<MODULE>"))
119             {
120               /* The next line has the name of the module and the offset
121                  of the corresponding embedded file in the library */
122               getline (FLine, sizeof (FLine), libfp);
123               sscanf (FLine, "%s %ld", ModName, &FileOffset);
124               state = 2;
125
126               /* Create a new libraryfile object for this module */
127               if (libr == NULL)
128                 {
129                   libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
130                 }
131               else
132                 {
133                   This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
134                   This = This->next;
135                 }
136               This->next = NULL;
137               This->loaded = -1;
138               This->offset = FileOffset + IndexOffset;
139               This->libspc = lbnh->libspc;
140               This->relfil = strdup (ModName);
141               sprintf (buff, "%s%s%c%s", lbnh->path, ModName, FSEPX, LKOBJEXT);
142               This->filename = strdup (buff);
143               This->type = type;
144
145               This->symbols = ThisSym = NULL;   /* Start a new linked list of symbols */
146             }
147           else if (EQ (FLine, "</INDEX>"))
148             {
149               return This;      /* Finish, get out of here */
150             }
151           break;
152         case 2:
153           if (EQ (FLine, "</MODULE>"))
154             {
155               This->loaded = 0;
156               /* Create the index for the next module */
157               state = 1;
158             }
159           else
160             {
161               /* Add the symbols */
162               if (ThisSym == NULL)      /* First symbol of the current module */
163                 {
164                   ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
165                 }
166               else
167                 {
168                   ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
169                   ThisSym = ThisSym->next;
170                 }
171               ThisSym->next = NULL;
172               ThisSym->name = strdup (FLine);
173             }
174           break;
175
176         default:
177           return This;          /* State machine should never reach this point, but just in case... */
178           break;
179         }
180     }
181
182   return This;                  /* State machine should never reach this point, but just in case... */
183 }
184
185 #else
186
187 /* Load an .adb file embedded in a sdcclib file. If there is
188 something between <ADB> and </ADB> returns 1, otherwise returns 0.
189 This way the aomf51 will not have useless empty modules. */
190
191 static int
192 LoadAdb (FILE * libfp)
193 {
194   char str[MAXLINE];
195   int state = 0;
196   int ToReturn = 0;
197
198   while (getline (str, sizeof (str), libfp) != NULL)
199     {
200       switch (state)
201         {
202         case 0:
203           if (EQ (str, "<ADB>"))
204             state = 1;
205           break;
206         case 1:
207           if (EQ (str, "</ADB>"))
208             return ToReturn;
209           fprintf (dfp, "%s\n", str);
210           ToReturn = 1;
211           break;
212         }
213     }
214   return ToReturn;
215 }
216
217 /* Check for a symbol in a SDCC library. If found, add the embedded .rel and
218    .adb files from the library.  The library must be created with the SDCC
219    librarian 'sdcclib' since the linking process depends on the correct file offsets
220    embedded in the library file. */
221
222 static int
223 findsym_sdcclib (const char *name, struct lbname *lbnh, FILE * libfp, int type)
224 {
225   struct lbfile *lbfh, *lbf;
226   char ModName[NCPS] = "";
227   char FLine[MAXLINE];
228   int state = 0;
229   long IndexOffset = 0, FileOffset;
230
231   while (getline (FLine, sizeof (FLine), libfp))
232     {
233       char str[PATH_MAX];
234
235       if (lbnh->path != NULL)
236         {
237           strcpy (str, lbnh->path);
238 #ifdef  OTHERSYSTEM
239           if (*str != '\0' && (str[strlen (str) - 1] != '/') && (str[strlen (str) - 1] != LKDIRSEP))
240             {
241               strcat (str, LKDIRSEPSTR);
242             }
243 #endif
244         }
245
246       switch (state)
247         {
248         case 0:
249           if (EQ (FLine, "<INDEX>"))
250             {
251               /* The next line has the size of the index */
252               getline (FLine, sizeof (FLine), libfp);
253               IndexOffset = atol (FLine);
254               state = 1;
255             }
256           break;
257         case 1:
258           if (EQ (FLine, "<MODULE>"))
259             {
260               /* The next line has the name of the module and the offset
261                  of the corresponding embedded file in the library */
262               getline (FLine, sizeof (FLine), libfp);
263               sscanf (FLine, "%s %ld", ModName, &FileOffset);
264               state = 2;
265             }
266           else if (EQ (FLine, "</INDEX>"))
267             {
268               /* Reached the end of the index.  The symbol is not in this library. */
269               return 0;
270             }
271           break;
272         case 2:
273           if (EQ (FLine, "</MODULE>"))
274             {
275               /* The symbol is not in this module, try the next one */
276               state = 1;
277             }
278           else
279             {
280               /* Check if this is the symbol we are looking for. */
281               if (strncmp (name, FLine, NCPS) == 0)
282                 {
283                   /* The symbol is in this module. */
284
285                   /* As in the original library format, it is assumed that the .rel
286                      files reside in the same directory as the lib files. */
287                   sprintf (&str[strlen (str)], "%s%c%s", ModName, FSEPX, LKOBJEXT);
288
289                   /* If this module has been loaded already don't load it again. */
290                   lbf = lbfhead;
291                   while (lbf)
292                     {
293                       if (EQ (str, lbf->filspc))
294                         return 1;       /* Already loaded */
295                       lbf = lbf->next;
296                     }
297
298                   /* Add the embedded file to the list of files to be loaded in
299                      the second pass.  That is performed latter by the function
300                      library() below. */
301                   lbfh = (struct lbfile *) new (sizeof (struct lbfile));
302                   if (lbfhead == NULL)
303                     {
304                       lbfhead = lbfh;
305                     }
306                   else
307                     {
308                       lbf = lbfhead;
309                       while (lbf->next)
310                         {
311                           lbf = lbf->next;
312                         }
313                       lbf->next = lbfh;
314                     }
315
316                   lbfh->libspc = lbnh->libspc;
317                   lbfh->filspc = str;
318                   lbfh->relfil = strdup (ModName);
319                   /* Library embedded file, so lbfh->offset must be >=0 */
320                   lbfh->offset = IndexOffset + FileOffset;
321
322                   /* Jump to where the .rel begins and load it. */
323                   fseek (libfp, lbfh->offset, SEEK_SET);
324                   LoadRel (lbnh->libspc, libfp, ModName);
325
326                   /* if cdb information required & .adb file present */
327                   if (dflag && dfp)
328                     {
329                       if (LoadAdb (libfp))
330                         SaveLinkedFilePath (str);
331                     }
332                   return 1;     /* Found the symbol, so success! */
333                 }
334             }
335           break;
336
337         default:
338           return 0;             /* It should never reach this point, but just in case... */
339           break;
340         }
341     }
342
343   return 0;                     /* The symbol is not in this library */
344 }
345
346 #endif
347
348 static void
349 loadfile_sdcclib (struct lbfile *lbfh)
350 {
351   FILE *fp;
352 #ifdef __CYGWIN__
353   char posix_path[PATH_MAX];
354   void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path);
355   cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path);
356   fp = fopen (posix_path, "rb");
357 #else
358   fp = fopen (lbfh->libspc, "rb");
359 #endif
360
361   if (fp != NULL)
362     {
363       fseek (fp, lbfh->offset, SEEK_SET);
364       LoadRel (lbfh->libspc, fp, lbfh->relfil);
365       fclose (fp);
366     }
367   else
368     {
369       fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc);
370       fclose (fp);
371       lkexit (1);
372     }
373 }
374
375 struct aslib_target aslib_target_sdcclib = {
376   &is_sdcclib,
377 #ifdef INDEXLIB
378   &buildlibraryindex_sdcclib,
379 #else
380   &findsym_sdcclib,
381 #endif
382   &loadfile_sdcclib,
383 };