* as/link/lksdcclib.c:
[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 int
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               if (NULL != getline (str, sizeof (str), libfp) && EQ (str, ModName))
73                 state = 1;
74               else
75                 return 0;
76             }
77           else
78             return 0;
79           break;
80
81         case 1:
82           return EQ (str, "<REL>") ? load_rel (libfp, -1) : 0;
83         }
84     }
85
86   return 0;
87 }
88
89 #ifdef INDEXLIB
90 static pmlibraryfile
91 buildlibraryindex_sdcclib (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int type)
92 {
93   char ModName[NCPS] = "";
94   char FLine[MAXLINE];
95   char buff[PATH_MAX];
96   int state = 0;
97   long IndexOffset = 0, FileOffset;
98   pmlibrarysymbol ThisSym = NULL;
99
100   while (getline (FLine, sizeof (FLine), libfp))
101     {
102       switch (state)
103         {
104         case 0:
105           if (EQ (FLine, "<INDEX>"))
106             {
107               /*The next line has the size of the index */
108               getline (FLine, sizeof (FLine), libfp);
109               IndexOffset = atol (FLine);
110               state = 1;
111             }
112           break;
113
114         case 1:
115           if (EQ (FLine, "<MODULE>"))
116             {
117               /* The next line has the name of the module and the offset
118                  of the corresponding embedded file in the library */
119               getline (FLine, sizeof (FLine), libfp);
120               sscanf (FLine, "%s %ld", ModName, &FileOffset);
121               state = 2;
122
123               /* Create a new libraryfile object for this module */
124               if (libr == NULL)
125                 {
126                   libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
127                 }
128               else
129                 {
130                   This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
131                   This = This->next;
132                 }
133               This->next = NULL;
134               This->loaded = -1;
135               This->offset = FileOffset + IndexOffset;
136               This->libspc = lbnh->libspc;
137               This->relfil = strdup (ModName);
138               sprintf (buff, "%s%s%c%s", lbnh->path, ModName, FSEPX, LKOBJEXT);
139               This->filename = strdup (buff);
140               This->type = type;
141
142               This->symbols = ThisSym = NULL;   /* Start a new linked list of symbols */
143             }
144           else if (EQ (FLine, "</INDEX>"))
145             {
146               return This;      /* Finish, get out of here */
147             }
148           break;
149
150         case 2:
151           if (EQ (FLine, "</MODULE>"))
152             {
153               This->loaded = 0;
154               /* Create the index for the next module */
155               state = 1;
156             }
157           else
158             {
159               /* Add the symbols */
160               if (ThisSym == NULL)      /* First symbol of the current module */
161                 {
162                   ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
163                 }
164               else
165                 {
166                   ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
167                   ThisSym = ThisSym->next;
168                 }
169               ThisSym->next = NULL;
170               ThisSym->name = strdup (FLine);
171             }
172           break;
173
174         default:
175           return This;          /* State machine should never reach this point, but just in case... */
176           break;
177         }
178     }
179
180   return This;                  /* State machine should never reach this point, but just in case... */
181 }
182
183 #else
184
185 /* Load an .adb file embedded in a sdcclib file. If there is
186 something between <ADB> and </ADB> returns 1, otherwise returns 0.
187 This way the aomf51 will not have useless empty modules. */
188
189 static int
190 LoadAdb (FILE * libfp)
191 {
192   char str[MAXLINE];
193   int state = 0;
194   int ret = 0;
195
196   while (getline (str, sizeof (str), libfp) != NULL)
197     {
198       switch (state)
199         {
200         case 0:
201           if (EQ (str, "<ADB>"))
202             state = 1;
203           break;
204
205         case 1:
206           if (EQ (str, "</ADB>"))
207             return ret;
208           fprintf (dfp, "%s\n", str);
209           ret = 1;
210           break;
211         }
212     }
213   return ret;
214 }
215
216 /* Check for a symbol in a SDCC library. If found, add the embedded .rel and
217    .adb files from the library.  The library must be created with the SDCC
218    librarian 'sdcclib' since the linking process depends on the correct file offsets
219    embedded in the library file. */
220
221 static int
222 findsym_sdcclib (const char *name, struct lbname *lbnh, FILE * libfp, int type)
223 {
224   struct lbfile *lbfh, *lbf;
225   char ModName[NCPS] = "";
226   char FLine[MAXLINE];
227   int state = 0;
228   long IndexOffset = 0, FileOffset;
229
230   while (getline (FLine, sizeof (FLine), libfp))
231     {
232       char str[PATH_MAX];
233
234       if (lbnh->path != NULL)
235         {
236           strcpy (str, lbnh->path);
237 #ifdef  OTHERSYSTEM
238           if (*str != '\0' && (str[strlen (str) - 1] != '/') && (str[strlen (str) - 1] != LKDIRSEP))
239             {
240               strcat (str, LKDIRSEPSTR);
241             }
242 #endif
243         }
244
245       switch (state)
246         {
247         case 0:
248           if (EQ (FLine, "<INDEX>"))
249             {
250               /* The next line has the size of the index */
251               getline (FLine, sizeof (FLine), libfp);
252               IndexOffset = atol (FLine);
253               state = 1;
254             }
255           break;
256
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
273         case 2:
274           if (EQ (FLine, "</MODULE>"))
275             {
276               /* The symbol is not in this module, try the next one */
277               state = 1;
278             }
279           else
280             {
281               /* Check if this is the symbol we are looking for. */
282               if (strncmp (name, FLine, NCPS) == 0)
283                 {
284                   /* The symbol is in this module. */
285
286                   /* As in the original library format, it is assumed that the .rel
287                      files reside in the same directory as the lib files. */
288                   sprintf (&str[strlen (str)], "%s%c%s", ModName, FSEPX, LKOBJEXT);
289
290                   /* If this module has been loaded already don't load it again. */
291                   lbf = lbfhead;
292                   while (lbf)
293                     {
294                       if (EQ (str, lbf->filspc))
295                         return 1;       /* Already loaded */
296                       lbf = lbf->next;
297                     }
298
299                   /* Add the embedded file to the list of files to be loaded in
300                      the second pass.  That is performed latter by the function
301                      library() below. */
302                   lbfh = (struct lbfile *) new (sizeof (struct lbfile));
303                   if (lbfhead == NULL)
304                     {
305                       lbfhead = lbfh;
306                     }
307                   else
308                     {
309                       lbf = lbfhead;
310                       while (lbf->next)
311                         {
312                           lbf = lbf->next;
313                         }
314                       lbf->next = lbfh;
315                     }
316
317                   lbfh->libspc = lbnh->libspc;
318                   lbfh->filspc = strdup (str);
319                   lbfh->relfil = strdup (ModName);
320                   /* Library embedded file, so lbfh->offset must be >=0 */
321                   lbfh->offset = IndexOffset + FileOffset;
322
323                   /* Jump to where the .rel begins and load it. */
324                   fseek (libfp, lbfh->offset, SEEK_SET);
325                   if (!LoadRel (lbnh->libspc, libfp, ModName))
326                     {
327                       fclose (libfp);
328                       fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, ModName);
329                       lkexit (1);
330                     }
331                   /* if cdb information required & .adb file present */
332                   if (dflag && dfp)
333                     {
334                       if (LoadAdb (libfp))
335                         SaveLinkedFilePath (str);
336                     }
337                   return 1;     /* Found the symbol, so success! */
338                 }
339             }
340           break;
341
342         default:
343           return 0;             /* It should never reach this point, but just in case... */
344           break;
345         }
346     }
347
348   return 0;                     /* The symbol is not in this library */
349 }
350
351 #endif
352
353 static void
354 loadfile_sdcclib (struct lbfile *lbfh)
355 {
356   FILE *fp;
357   int res;
358
359 #ifdef __CYGWIN__
360   char posix_path[PATH_MAX];
361   void cygwin_conv_to_full_posix_path (char *win_path, char *posix_path);
362   cygwin_conv_to_full_posix_path (lbfh->libspc, posix_path);
363   fp = fopen (posix_path, "rb");
364 #else
365   fp = fopen (lbfh->libspc, "rb");
366 #endif
367
368   if (fp != NULL)
369     {
370       fseek (fp, lbfh->offset, SEEK_SET);
371       res = LoadRel (lbfh->libspc, fp, lbfh->relfil);
372       fclose (fp);
373
374       if (!res)
375         {
376           fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil);
377           lkexit (1);
378         }
379     }
380   else
381     {
382       fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc);
383       lkexit (1);
384     }
385 }
386
387 struct aslib_target aslib_target_sdcclib = {
388   &is_sdcclib,
389 #ifdef INDEXLIB
390   &buildlibraryindex_sdcclib,
391 #else
392   &findsym_sdcclib,
393 #endif
394   &loadfile_sdcclib,
395 };