Mercurial > hg-old > index.cgi
comparison src/script.c @ 299:460d96987670
parse linking scripts
author | lost |
---|---|
date | Wed, 21 Jan 2009 04:54:32 +0000 |
parents | |
children | 48945dac8178 |
comparison
equal
deleted
inserted
replaced
298:96a35a4245f3 | 299:460d96987670 |
---|---|
1 /* | |
2 script.c | |
3 Copyright © 2008 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 at 2000\n" | |
39 "section code\n" | |
40 "section *,!bss\n" | |
41 "section *,bss\n" | |
42 ; | |
43 | |
44 // the built-in RAW target linker script | |
45 static char *raw_script = | |
46 "section init load at 0000\n" | |
47 "section code\n" | |
48 "section *,!bss\n" | |
49 "section *,bss\n" | |
50 ; | |
51 | |
52 // the "simple" script | |
53 static char *simple_script = | |
54 "section *,!bss\n" | |
55 "section *,bss\n" | |
56 ; | |
57 | |
58 linkscript_t linkscript = { 0, NULL, -1 }; | |
59 | |
60 void setup_script() | |
61 { | |
62 char *script; | |
63 long size; | |
64 | |
65 // read the file if needed | |
66 if (scriptfile) | |
67 { | |
68 FILE *f; | |
69 long bread; | |
70 | |
71 f = fopen(scriptfile, "rb"); | |
72 if (!f) | |
73 { | |
74 fprintf(stderr, "Can't open file %s:", scriptfile); | |
75 perror(""); | |
76 exit(1); | |
77 } | |
78 fseek(f, 0, SEEK_END); | |
79 size = ftell(f); | |
80 rewind(f); | |
81 | |
82 script = lw_malloc(size + 2); | |
83 | |
84 bread = fread(script, 1, size, f); | |
85 if (bread < size) | |
86 { | |
87 fprintf(stderr, "Short read on file %s (%ld/%ld):", scriptfile, bread, size); | |
88 perror(""); | |
89 exit(1); | |
90 } | |
91 fclose(f); | |
92 | |
93 script[size] = '\n'; | |
94 script[size + 1] = '\0'; | |
95 } | |
96 else | |
97 { | |
98 // fetch defaults based on output mode | |
99 switch (outformat) | |
100 { | |
101 case OUTPUT_RAW: | |
102 script = raw_script; | |
103 break; | |
104 | |
105 case OUTPUT_DECB: | |
106 script = decb_script; | |
107 break; | |
108 | |
109 default: | |
110 script = simple_script; | |
111 break; | |
112 } | |
113 | |
114 size = strlen(script); | |
115 } | |
116 | |
117 // now parse the script file | |
118 while (*script) | |
119 { | |
120 char *ptr, *ptr2, *line; | |
121 | |
122 for (ptr = script; *ptr && *ptr != '\n' && *ptr != '\r'; ptr++) | |
123 /* do nothing */ ; | |
124 | |
125 line = lw_malloc(ptr - script + 1); | |
126 memcpy(line, script, ptr - script); | |
127 line[ptr - script] = '\0'; | |
128 | |
129 // skip line terms | |
130 for (script = ptr + 1; *script == '\n' || *script == '\r'; script++) | |
131 /* do nothing */ ; | |
132 | |
133 // ignore leading whitespace | |
134 for (ptr = line; *ptr && isspace(*ptr); ptr++) | |
135 /* do nothing */ ; | |
136 | |
137 // ignore blank lines | |
138 if (!*ptr) | |
139 continue; | |
140 | |
141 for (ptr = line; *ptr && !isspace(*ptr); ptr++) | |
142 /* do nothing */ ; | |
143 | |
144 // now ptr points to the char past the first word | |
145 // NUL it out | |
146 if (*ptr) | |
147 *ptr++ = '\0'; | |
148 | |
149 // skip spaces after the first word | |
150 for ( ; *ptr && isspace(*ptr); ptr++) | |
151 /* do nothing */ ; | |
152 | |
153 if (!strcmp(line, "pad")) | |
154 { | |
155 // padding | |
156 // parse the hex number and stow it | |
157 linkscript.padsize = strtol(ptr, NULL, 16); | |
158 if (linkscript.padsize < 0) | |
159 linkscript.padsize = 0; | |
160 } | |
161 else if (!strcmp(line, "section")) | |
162 { | |
163 // section | |
164 // parse out the section name and flags | |
165 for (ptr2 = ptr; *ptr2 && !isspace(*ptr2); ptr2++) | |
166 /* do nothing */ ; | |
167 | |
168 if (*ptr2) | |
169 *ptr2++ = '\0'; | |
170 | |
171 while (*ptr2 && isspace(*ptr2)) | |
172 ptr2++; | |
173 | |
174 // ptr now points to the section name and flags and ptr2 | |
175 // to the first non-space character following | |
176 | |
177 // then look for "load <addr>" clause | |
178 if (*ptr2) | |
179 { | |
180 if (!strncmp(ptr2, "load", 4)) | |
181 { | |
182 ptr2 += 4; | |
183 while (*ptr2 && isspace(*ptr2)) | |
184 ptr2++; | |
185 | |
186 } | |
187 else | |
188 { | |
189 fprintf(stderr, "%s: bad script\n", scriptfile); | |
190 exit(1); | |
191 } | |
192 } | |
193 | |
194 // now ptr2 points to the load address if there is one | |
195 // or NUL if not | |
196 linkscript.lines = lw_realloc(linkscript.lines, sizeof(struct scriptline_s) * (linkscript.nlines + 1)); | |
197 | |
198 linkscript.lines[linkscript.nlines].noflags = 0; | |
199 linkscript.lines[linkscript.nlines].yesflags = 0; | |
200 if (*ptr2) | |
201 linkscript.lines[linkscript.nlines].loadat = strtol(ptr2, NULL, 16); | |
202 else | |
203 linkscript.lines[linkscript.nlines].loadat = -1; | |
204 for (ptr2 = ptr; *ptr2 && *ptr2 != ','; ptr2++) | |
205 /* do nothing */ ; | |
206 if (*ptr2) | |
207 { | |
208 *ptr2++ = '\0'; | |
209 if (!strcmp(ptr2, "!bss")) | |
210 { | |
211 linkscript.lines[linkscript.nlines].noflags = SECTION_BSS; | |
212 } | |
213 else if (!strcmp(ptr2, "bss")) | |
214 { | |
215 linkscript.lines[linkscript.nlines].yesflags = SECTION_BSS; | |
216 } | |
217 else | |
218 { | |
219 fprintf(stderr, "%s: bad script\n", scriptfile); | |
220 exit(1); | |
221 } | |
222 } | |
223 linkscript.lines[linkscript.nlines].sectname = lw_strdup(ptr); | |
224 linkscript.nlines++; | |
225 } | |
226 else | |
227 { | |
228 fprintf(stderr, "%s: bad script\n", scriptfile); | |
229 exit(1); | |
230 } | |
231 lw_free(line); | |
232 } | |
233 | |
234 if (scriptfile) | |
235 lw_free(script); | |
236 } |