struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / linksrc / lksdcclib.c
blobb0ea35c4abdec3b5ecae92135f95d5b0f337561a
1 /* lksdcclib.c - sdcc library format handling
3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
5 Copyright (C) 2008 Borut Razem, borut dot razem at siol dot net
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.
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.
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/>. */
21 * With contributions for the
22 * object libraries from
23 * Ken Hornstein
24 * kenh@cmf.nrl.navy.mil
29 * Extensions: P. Felber
32 #include <stdlib.h>
33 #include <string.h>
35 #include "sdld.h"
36 #include "lk_readnl.h"
37 #include "aslink.h"
38 #include "lklibr.h"
39 #include "lkrel.h"
41 #define EQ(A,B) !strcmp((A),(B))
42 #define MAXLINE 254 /* when using lk_readnl */
45 static int
46 is_sdcclib (FILE * libfp)
48 #define SDCCLIB_MAGIC "<SDCCLIB>"
49 #define SDCCLIB_MAGIC_LEN (sizeof ("<SDCCLIB>") - 1)
51 char buf[SDCCLIB_MAGIC_LEN];
53 if (fread (buf, 1, sizeof (buf), libfp) == sizeof (buf) && memcmp (buf, SDCCLIB_MAGIC, SDCCLIB_MAGIC_LEN) == 0)
55 switch (getc (libfp))
57 case '\r':
58 if (getc (libfp) == '\n')
59 return 1;
61 case '\n':
62 return 1;
65 rewind (libfp);
66 return 0;
69 /* Load a .rel file embedded in a sdcclib file */
70 static int
71 LoadRel (char *libfname, FILE * libfp, char *ModName)
73 char str[NINPUT];
74 int state = 0;
76 while (lk_readnl (str, sizeof (str), libfp) != NULL)
78 switch (state)
80 case 0:
81 if (EQ (str, "<FILE>"))
83 if (NULL != lk_readnl (str, sizeof (str), libfp) && EQ (str, ModName))
84 state = 1;
85 else
86 return 0;
88 else
89 return 0;
90 break;
92 case 1:
93 return EQ (str, "<REL>") ? load_rel (libfp, -1) : 0;
97 return 0;
100 #ifdef INDEXLIB
101 static pmlibraryfile
102 buildlibraryindex_sdcclib (struct lbname *lbnh, FILE * libfp, pmlibraryfile This, int type)
104 char FLine[MAXLINE];
105 int state = 0;
106 long IndexOffset = 0;
107 pmlibrarysymbol ThisSym = NULL;
109 while (lk_readnl (FLine, sizeof (FLine), libfp))
111 switch (state)
113 case 0:
114 if (EQ (FLine, "<INDEX>"))
116 /*The next line has the size of the index */
117 lk_readnl (FLine, sizeof (FLine), libfp);
118 IndexOffset = atol (FLine);
119 state = 1;
121 break;
123 case 1:
124 if (EQ (FLine, "<MODULE>"))
126 char buff[PATH_MAX];
127 char ModName[NCPS] = "";
128 long FileOffset;
130 /* The next line has the name of the module and the offset
131 of the corresponding embedded file in the library */
132 lk_readnl (FLine, sizeof (FLine), libfp);
133 sscanf (FLine, "%s %ld", ModName, &FileOffset);
134 state = 2;
136 /* Create a new libraryfile object for this module */
137 if (libr == NULL)
139 libr = This = (pmlibraryfile) new (sizeof (mlibraryfile));
141 else
143 This->next = (pmlibraryfile) new (sizeof (mlibraryfile));
144 This = This->next;
146 This->next = NULL;
147 This->loaded = -1;
148 This->offset = FileOffset + IndexOffset;
149 This->libspc = lbnh->libspc;
150 This->relfil = strdup (ModName);
151 sprintf (buff, "%s%s%c%s", lbnh->path, ModName, FSEPX, LKOBJEXT);
152 This->filspc = strdup (buff);
153 This->type = type;
155 This->symbols = ThisSym = NULL; /* Start a new linked list of symbols */
157 else if (EQ (FLine, "</INDEX>"))
159 return This; /* Finish, get out of here */
161 break;
163 case 2:
164 if (EQ (FLine, "</MODULE>"))
166 This->loaded = 0;
167 /* Create the index for the next module */
168 state = 1;
170 else
172 /* Add the symbols */
173 if (ThisSym == NULL) /* First symbol of the current module */
175 ThisSym = This->symbols = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
177 else
179 ThisSym->next = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
180 ThisSym = ThisSym->next;
182 ThisSym->next = NULL;
183 ThisSym->name = strdup (FLine);
185 break;
187 default:
188 return This; /* State machine should never reach this point, but just in case... */
189 break;
193 return This; /* State machine should never reach this point, but just in case... */
196 #else
198 /* Load an .adb file embedded in a sdcclib file. If there is
199 something between <ADB> and </ADB> returns 1, otherwise returns 0.
200 This way the aomf51 will not have useless empty modules. */
202 static int
203 LoadAdb (FILE * libfp)
205 char str[MAXLINE];
206 int state = 0;
207 int ret = 0;
209 while (lk_readnl (str, sizeof (str), libfp) != NULL)
211 switch (state)
213 case 0:
214 if (EQ (str, "<ADB>"))
215 state = 1;
216 break;
218 case 1:
219 if (EQ (str, "</ADB>"))
220 return ret;
221 fprintf (yfp, "%s\n", str);
222 ret = 1;
223 break;
226 return ret;
229 /* Check for a symbol in a SDCC library. If found, add the embedded .rel and
230 .adb files from the library. The library must be created with the SDCC
231 librarian 'sdcclib' since the linking process depends on the correct file offsets
232 embedded in the library file. */
234 static int
235 findsym_sdcclib (const char *name, struct lbname *lbnh, FILE * libfp, int type)
237 struct lbfile *lbfh;
238 char ModName[NCPS] = "";
239 char FLine[MAXLINE];
240 int state = 0;
241 long IndexOffset = 0, FileOffset;
243 while (lk_readnl (FLine, sizeof (FLine), libfp))
245 char filspc[PATH_MAX];
247 if (lbnh->path != NULL)
249 strcpy (filspc, lbnh->path);
250 #ifdef OTHERSYSTEM
251 if (*filspc != '\0' && (filspc[strlen (filspc) - 1] != '/') && (filspc[strlen (filspc) - 1] != LKDIRSEP))
253 strcat (filspc, LKDIRSEPSTR);
255 #endif
258 switch (state)
260 case 0:
261 if (EQ (FLine, "<INDEX>"))
263 /* The next line has the size of the index */
264 lk_readnl (FLine, sizeof (FLine), libfp);
265 IndexOffset = atol (FLine);
266 state = 1;
268 break;
270 case 1:
271 if (EQ (FLine, "<MODULE>"))
273 /* The next line has the name of the module and the offset
274 of the corresponding embedded file in the library */
275 lk_readnl (FLine, sizeof (FLine), libfp);
276 sscanf (FLine, "%s %ld", ModName, &FileOffset);
277 state = 2;
279 else if (EQ (FLine, "</INDEX>"))
281 /* Reached the end of the index. The symbol is not in this library. */
282 return 0;
284 break;
286 case 2:
287 if (EQ (FLine, "</MODULE>"))
289 /* The symbol is not in this module, try the next one */
290 state = 1;
292 else
294 /* Check if this is the symbol we are looking for. */
295 if (strncmp (name, FLine, NCPS) == 0)
297 /* The symbol is in this module. */
299 /* As in the original library format, it is assumed that the .rel
300 files reside in the same directory as the lib files. */
301 sprintf (&filspc[strlen (filspc)], "%s%c%s", ModName, FSEPX, LKOBJEXT);
303 /* If this module has been loaded already don't load it again. */
304 if (is_module_loaded (filspc))
305 return 1;
307 /* Add the embedded file to the list of files to be loaded in
308 the second pass. That is performed latter by the function
309 library() below. */
310 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
311 if (lbfhead == NULL)
313 lbfhead = lbfh;
315 else
317 struct lbfile *lbf;
319 for (lbf = lbfhead; lbf->next; lbf = lbf->next)
322 lbf->next = lbfh;
325 lbfh->libspc = lbnh->libspc;
326 lbfh->filspc = strdup (filspc);
327 lbfh->relfil = strdup (ModName);
328 lbfh->f_obj = lbnh->f_obj;
329 /* Library embedded file, so lbfh->offset must be >=0 */
330 lbfh->offset = IndexOffset + FileOffset;
331 obj_flag = lbfh->f_obj;
333 /* Jump to where the .rel begins and load it. */
334 fseek (libfp, lbfh->offset, SEEK_SET);
335 if (!LoadRel (lbnh->libspc, libfp, ModName))
337 fclose (libfp);
338 fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, ModName);
339 lkexit (1);
341 /* if cdb information required & .adb file present */
342 if (yflag && yfp)
344 if (LoadAdb (libfp))
345 SaveLinkedFilePath (filspc);
347 return 1; /* Found the symbol, so success! */
350 break;
352 default:
353 return 0; /* It should never reach this point, but just in case... */
354 break;
358 return 0; /* The symbol is not in this library */
361 #endif
363 static void
364 loadfile_sdcclib (struct lbfile *lbfh)
366 FILE *fp;
367 int res;
368 fp = fopen (lbfh->libspc, "rb");
369 if (fp != NULL)
371 fseek (fp, lbfh->offset, SEEK_SET);
372 res = LoadRel (lbfh->libspc, fp, lbfh->relfil);
373 fclose (fp);
375 if (!res)
377 fprintf (stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n", lbfh->libspc, lbfh->relfil);
378 lkexit (1);
381 else
383 fprintf (stderr, "?ASlink-Error-Opening library '%s'\n", lbfh->libspc);
384 lkexit (1);
388 struct aslib_target aslib_target_sdcclib = {
389 &is_sdcclib,
390 #ifdef INDEXLIB
391 &buildlibraryindex_sdcclib,
392 #else
393 &findsym_sdcclib,
394 #endif
395 &loadfile_sdcclib,