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 }