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