Mercurial > hg-old > index.cgi
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 } |