7b5a931cfa02c68b2761a99dbaa9159a2b780498
[fw/sdcc] / as / link / lkrel.c
1 /* lkrel.c - .rel object file 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 2, 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, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 /*
22  * With contributions for the
23  * object libraries from
24  * Ken Hornstein
25  * kenh@cmf.nrl.navy.mil
26  *
27  */
28
29 /*
30  * Extensions: P. Felber
31  */
32
33 #include <string.h>
34 #include <assert.h>
35
36 #include "getline.h"
37 #include "aslink.h"
38 #include "lkrel.h"
39
40 int
41 is_rel (FILE * libfp)
42 {
43   int c;
44   long pos = ftell (libfp);
45   int ret = 0;
46
47   /* [XDQ][HL] */
48   if (((c = getc (libfp)) == 'X' || c == 'D' || c == 'Q') && ((c = getc (libfp)) == 'H' || c == 'L'))
49     {
50       switch (getc (libfp))
51         {
52         case '\r':
53           if (getc (libfp) == '\n')
54             ret = 1;
55           break;
56
57         case '\n':
58           ret = 1;
59         }
60     }
61   else if (c == ';')
62     {
63       char buf[6];
64
65       if (fread (buf, 1, sizeof (buf), libfp) == sizeof (buf) && memcmp (buf, "!FILE ", 6) == 0)
66         ret = 1;
67     }
68   fseek (libfp, pos, SEEK_SET);
69   return ret;
70 }
71
72 /* Load a standalone or embedded .rel */
73 int
74 load_rel (FILE * libfp, long size)
75 {
76   if (is_rel (libfp))
77     {
78       char str[NINPUT];
79       long end;
80
81       end = (size >= 0) ? ftell (libfp) + size : -1;
82
83       while ((end < 0 || ftell (libfp) < end) && getline (str, sizeof (str), libfp) != NULL)
84         {
85           if (0 == strcmp (str, "</REL>"))
86             return 1;
87
88           ip = str;
89           link_main ();
90         }
91
92       return 1;
93     }
94   else
95     return 0;
96 }
97
98 int
99 enum_symbols (FILE * fp, long size, int (*func) (const char *symvoid, void *param), void *param)
100 {
101   char buf[NINPUT];
102   long end = (size >= 0) ? ftell (fp) + size : -1;
103
104   assert (func != NULL);
105
106   /*
107    * Read in the object file.  Look for lines that
108    * begin with "S" and end with "D".  These are
109    * symbol table definitions.  If we find one, see
110    * if it is our symbol.  Make sure we only read in
111    * our object file and don't go into the next one.
112    */
113
114   while ((end < 0 || ftell (fp) < end) && getline (buf, sizeof (buf), fp) != NULL)
115     {
116       char symname[NINPUT];
117       char c;
118
119       /*
120        * When a 'T line' is found terminate file scan.
121        * All 'S line's preceed 'T line's in .REL files.
122        */
123       if (buf[0] == 'T')
124         break;
125
126       /*
127        * Skip everything that's not a symbol record.
128        */
129       if (buf[0] != 'S')
130         continue;
131
132       sscanf (buf, "S %s %c", symname, &c);
133
134       /* If it's an actual symbol, record it */
135       if (c == 'D')
136         {
137           if ((*func) (symname, param))
138             return 1;
139         }
140     }
141
142   return 0;
143 }