comparison lwlink/script.c @ 139:106c2fe3c9d9

repo reorg
author lost
date Wed, 28 Jan 2009 05:59:14 +0000
parents lwlink-old/trunk/src/script.c@050864a47b38
children 6ebb93b409ba
comparison
equal deleted inserted replaced
138:050864a47b38 139:106c2fe3c9d9
1 /*
2 script.c
3 Copyright © 2009 William Astle
4
5 This file is part of LWLINK.
6
7 LWLINK is free software: you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation, either version 3 of the License, or (at your option) any later
10 version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
16
17 You should have received a copy of the GNU General Public License along with
18 this program. If not, see <http://www.gnu.org/licenses/>.
19
20
21 Read and parse linker scripts
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "lwlink.h"
34 #include "util.h"
35
36 // the built-in DECB target linker script
37 static char *decb_script =
38 "section init load 2000\n"
39 "section code\n"
40 "section *,!bss\n"
41 "section *,bss\n"
42 "entry 2000\n"
43 ;
44
45 // the built-in RAW target linker script
46 static char *raw_script =
47 "section init load 0000\n"
48 "section code\n"
49 "section *,!bss\n"
50 "section *,bss\n"
51 ;
52
53 // the "simple" script
54 static char *simple_script =
55 "section *,!bss\n"
56 "section *,bss\n"
57 ;
58
59 linkscript_t linkscript = { 0, NULL, -1 };
60
61 void setup_script()
62 {
63 char *script, *oscript;
64 long size;
65
66 // read the file if needed
67 if (scriptfile)
68 {
69 FILE *f;
70 long bread;
71
72 f = fopen(scriptfile, "rb");
73 if (!f)
74 {
75 fprintf(stderr, "Can't open file %s:", scriptfile);
76 perror("");
77 exit(1);
78 }
79 fseek(f, 0, SEEK_END);
80 size = ftell(f);
81 rewind(f);
82
83 script = lw_malloc(size + 2);
84
85 bread = fread(script, 1, size, f);
86 if (bread < size)
87 {
88 fprintf(stderr, "Short read on file %s (%ld/%ld):", scriptfile, bread, size);
89 perror("");
90 exit(1);
91 }
92 fclose(f);
93
94 script[size] = '\n';
95 script[size + 1] = '\0';
96 }
97 else
98 {
99 // fetch defaults based on output mode
100 switch (outformat)
101 {
102 case OUTPUT_RAW:
103 script = raw_script;
104 break;
105
106 case OUTPUT_DECB:
107 script = decb_script;
108 break;
109
110 default:
111 script = simple_script;
112 break;
113 }
114
115 size = strlen(script);
116 }
117
118 oscript = script;
119 // now parse the script file
120 while (*script)
121 {
122 char *ptr, *ptr2, *line;
123
124 for (ptr = script; *ptr && *ptr != '\n' && *ptr != '\r'; ptr++)
125 /* do nothing */ ;
126
127 line = lw_malloc(ptr - script + 1);
128 memcpy(line, script, ptr - script);
129 line[ptr - script] = '\0';
130
131 // skip line terms
132 for (script = ptr + 1; *script == '\n' || *script == '\r'; script++)
133 /* do nothing */ ;
134
135 // ignore leading whitespace
136 for (ptr = line; *ptr && isspace(*ptr); ptr++)
137 /* do nothing */ ;
138
139 // ignore blank lines
140 if (!*ptr)
141 continue;
142
143 for (ptr = line; *ptr && !isspace(*ptr); ptr++)
144 /* do nothing */ ;
145
146 // now ptr points to the char past the first word
147 // NUL it out
148 if (*ptr)
149 *ptr++ = '\0';
150
151 // skip spaces after the first word
152 for ( ; *ptr && isspace(*ptr); ptr++)
153 /* do nothing */ ;
154
155 if (!strcmp(line, "pad"))
156 {
157 // padding
158 // parse the hex number and stow it
159 linkscript.padsize = strtol(ptr, NULL, 16);
160 if (linkscript.padsize < 0)
161 linkscript.padsize = 0;
162 }
163 else if (!strcmp(line, "entry"))
164 {
165 int eaddr;
166
167 eaddr = strtol(ptr, &ptr2, 16);
168 if (*ptr2)
169 {
170 linkscript.execaddr = -1;
171 linkscript.execsym = lw_strdup(ptr);
172 }
173 else
174 {
175 linkscript.execaddr = eaddr;
176 linkscript.execsym = NULL;
177 }
178 }
179 else if (!strcmp(line, "section"))
180 {
181 // section
182 // parse out the section name and flags
183 for (ptr2 = ptr; *ptr2 && !isspace(*ptr2); ptr2++)
184 /* do nothing */ ;
185
186 if (*ptr2)
187 *ptr2++ = '\0';
188
189 while (*ptr2 && isspace(*ptr2))
190 ptr2++;
191
192 // ptr now points to the section name and flags and ptr2
193 // to the first non-space character following
194
195 // then look for "load <addr>" clause
196 if (*ptr2)
197 {
198 if (!strncmp(ptr2, "load", 4))
199 {
200 ptr2 += 4;
201 while (*ptr2 && isspace(*ptr2))
202 ptr2++;
203
204 }
205 else
206 {
207 fprintf(stderr, "%s: bad script\n", scriptfile);
208 exit(1);
209 }
210 }
211
212 // now ptr2 points to the load address if there is one
213 // or NUL if not
214 linkscript.lines = lw_realloc(linkscript.lines, sizeof(struct scriptline_s) * (linkscript.nlines + 1));
215
216 linkscript.lines[linkscript.nlines].noflags = 0;
217 linkscript.lines[linkscript.nlines].yesflags = 0;
218 if (*ptr2)
219 linkscript.lines[linkscript.nlines].loadat = strtol(ptr2, NULL, 16);
220 else
221 linkscript.lines[linkscript.nlines].loadat = -1;
222 for (ptr2 = ptr; *ptr2 && *ptr2 != ','; ptr2++)
223 /* do nothing */ ;
224 if (*ptr2)
225 {
226 *ptr2++ = '\0';
227 if (!strcmp(ptr2, "!bss"))
228 {
229 linkscript.lines[linkscript.nlines].noflags = SECTION_BSS;
230 }
231 else if (!strcmp(ptr2, "bss"))
232 {
233 linkscript.lines[linkscript.nlines].yesflags = SECTION_BSS;
234 }
235 else
236 {
237 fprintf(stderr, "%s: bad script\n", scriptfile);
238 exit(1);
239 }
240 }
241 if (ptr[0] == '*' && ptr[1] == '\0')
242 linkscript.lines[linkscript.nlines].sectname = NULL;
243 else
244 linkscript.lines[linkscript.nlines].sectname = lw_strdup(ptr);
245 linkscript.nlines++;
246 }
247 else
248 {
249 fprintf(stderr, "%s: bad script\n", scriptfile);
250 exit(1);
251 }
252 lw_free(line);
253 }
254
255 if (scriptfile)
256 lw_free(oscript);
257 }