Annotation of /trunk/mkinitrd-magellan/klibc/usr/dash/mkinit.c
Parent Directory | Revision Log
Revision 815 -
(hide annotations)
(download)
Fri Apr 24 18:32:46 2009 UTC (15 years ago) by niro
File MIME type: text/plain
File size: 10416 byte(s)
Fri Apr 24 18:32:46 2009 UTC (15 years ago) by niro
File MIME type: text/plain
File size: 10416 byte(s)
-updated to klibc-1.5.15
1 | niro | 532 | /*- |
2 | * Copyright (c) 1991, 1993 | ||
3 | * The Regents of the University of California. All rights reserved. | ||
4 | * Copyright (c) 1997-2005 | ||
5 | * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. | ||
6 | * | ||
7 | * This code is derived from software contributed to Berkeley by | ||
8 | * Kenneth Almquist. | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * 1. Redistributions of source code must retain the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer. | ||
15 | * 2. Redistributions in binary form must reproduce the above copyright | ||
16 | * notice, this list of conditions and the following disclaimer in the | ||
17 | * documentation and/or other materials provided with the distribution. | ||
18 | * 3. Neither the name of the University nor the names of its contributors | ||
19 | * may be used to endorse or promote products derived from this software | ||
20 | * without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
32 | * SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | /* | ||
36 | * This program scans all the source files for code to handle various | ||
37 | * special events and combines this code into one file. This (allegedly) | ||
38 | * improves the structure of the program since there is no need for | ||
39 | * anyone outside of a module to know that that module performs special | ||
40 | * operations on particular events. | ||
41 | * | ||
42 | * Usage: mkinit sourcefile... | ||
43 | */ | ||
44 | |||
45 | |||
46 | #include <sys/types.h> | ||
47 | #include <stdio.h> | ||
48 | #include <stdlib.h> | ||
49 | #include <string.h> | ||
50 | #include <fcntl.h> | ||
51 | #include <unistd.h> | ||
52 | |||
53 | |||
54 | /* | ||
55 | * OUTFILE is the name of the output file. Output is initially written | ||
56 | * to the file OUTTEMP, which is then moved to OUTFILE. | ||
57 | */ | ||
58 | |||
59 | #define OUTFILE "init.c" | ||
60 | #define OUTTEMP "init.c.new" | ||
61 | |||
62 | |||
63 | /* | ||
64 | * A text structure is basicly just a string that grows as more characters | ||
65 | * are added onto the end of it. It is implemented as a linked list of | ||
66 | * blocks of characters. The routines addstr and addchar append a string | ||
67 | * or a single character, respectively, to a text structure. Writetext | ||
68 | * writes the contents of a text structure to a file. | ||
69 | */ | ||
70 | |||
71 | #define BLOCKSIZE 512 | ||
72 | |||
73 | struct text { | ||
74 | char *nextc; | ||
75 | int nleft; | ||
76 | struct block *start; | ||
77 | struct block *last; | ||
78 | }; | ||
79 | |||
80 | struct block { | ||
81 | struct block *next; | ||
82 | char text[BLOCKSIZE]; | ||
83 | }; | ||
84 | |||
85 | |||
86 | /* | ||
87 | * There is one event structure for each event that mkinit handles. | ||
88 | */ | ||
89 | |||
90 | struct event { | ||
91 | char *name; /* name of event (e.g. INIT) */ | ||
92 | char *routine; /* name of routine called on event */ | ||
93 | char *comment; /* comment describing routine */ | ||
94 | struct text code; /* code for handling event */ | ||
95 | }; | ||
96 | |||
97 | |||
98 | char writer[] = "\ | ||
99 | /*\n\ | ||
100 | * This file was generated by the mkinit program.\n\ | ||
101 | */\n\ | ||
102 | \n"; | ||
103 | |||
104 | char init[] = "\ | ||
105 | /*\n\ | ||
106 | * Initialization code.\n\ | ||
107 | */\n"; | ||
108 | |||
109 | char reset[] = "\ | ||
110 | /*\n\ | ||
111 | * This routine is called when an error or an interrupt occurs in an\n\ | ||
112 | * interactive shell and control is returned to the main command loop.\n\ | ||
113 | */\n"; | ||
114 | |||
115 | |||
116 | struct event event[] = { | ||
117 | {"INIT", "init", init}, | ||
118 | {"RESET", "reset", reset}, | ||
119 | {NULL, NULL} | ||
120 | }; | ||
121 | |||
122 | |||
123 | char *curfile; /* current file */ | ||
124 | int linno; /* current line */ | ||
125 | char *header_files[200]; /* list of header files */ | ||
126 | struct text defines; /* #define statements */ | ||
127 | struct text decls; /* declarations */ | ||
128 | int amiddecls; /* for formatting */ | ||
129 | |||
130 | |||
131 | void readfile(char *); | ||
132 | int match(char *, char *); | ||
133 | int gooddefine(char *); | ||
134 | void doevent(struct event *, FILE *, char *); | ||
135 | void doinclude(char *); | ||
136 | void dodecl(char *, FILE *); | ||
137 | void output(void); | ||
138 | void addstr(char *, struct text *); | ||
139 | void addchar(int, struct text *); | ||
140 | void writetext(struct text *, FILE *); | ||
141 | FILE *ckfopen(char *, char *); | ||
142 | void *ckmalloc(int); | ||
143 | char *savestr(char *); | ||
144 | static void error(char *); | ||
145 | int main(int, char **); | ||
146 | |||
147 | #define equal(s1, s2) (strcmp(s1, s2) == 0) | ||
148 | |||
149 | int | ||
150 | main(int argc, char **argv) | ||
151 | { | ||
152 | char **ap; | ||
153 | |||
154 | header_files[0] = "\"shell.h\""; | ||
155 | header_files[1] = "\"mystring.h\""; | ||
156 | header_files[2] = "\"init.h\""; | ||
157 | for (ap = argv + 1 ; *ap ; ap++) | ||
158 | readfile(*ap); | ||
159 | output(); | ||
160 | rename(OUTTEMP, OUTFILE); | ||
161 | exit(0); | ||
162 | /* NOTREACHED */ | ||
163 | } | ||
164 | |||
165 | |||
166 | /* | ||
167 | * Parse an input file. | ||
168 | */ | ||
169 | |||
170 | void | ||
171 | readfile(char *fname) | ||
172 | { | ||
173 | FILE *fp; | ||
174 | char line[1024]; | ||
175 | struct event *ep; | ||
176 | |||
177 | fp = ckfopen(fname, "r"); | ||
178 | curfile = fname; | ||
179 | linno = 0; | ||
180 | amiddecls = 0; | ||
181 | while (fgets(line, sizeof line, fp) != NULL) { | ||
182 | linno++; | ||
183 | for (ep = event ; ep->name ; ep++) { | ||
184 | if (line[0] == ep->name[0] && match(ep->name, line)) { | ||
185 | doevent(ep, fp, fname); | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | if (line[0] == 'I' && match("INCLUDE", line)) | ||
190 | doinclude(line); | ||
191 | if (line[0] == 'M' && match("MKINIT", line)) | ||
192 | dodecl(line, fp); | ||
193 | if (line[0] == '#' && gooddefine(line)) { | ||
194 | char *cp; | ||
195 | char line2[1024]; | ||
196 | static const char undef[] = "#undef "; | ||
197 | |||
198 | strcpy(line2, line); | ||
199 | memcpy(line2, undef, sizeof(undef) - 1); | ||
200 | cp = line2 + sizeof(undef) - 1; | ||
201 | while(*cp && (*cp == ' ' || *cp == '\t')) | ||
202 | cp++; | ||
203 | while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n') | ||
204 | cp++; | ||
205 | *cp++ = '\n'; *cp = '\0'; | ||
206 | addstr(line2, &defines); | ||
207 | addstr(line, &defines); | ||
208 | } | ||
209 | } | ||
210 | fclose(fp); | ||
211 | } | ||
212 | |||
213 | |||
214 | int | ||
215 | match(char *name, char *line) | ||
216 | { | ||
217 | char *p, *q; | ||
218 | |||
219 | p = name, q = line; | ||
220 | while (*p) { | ||
221 | if (*p++ != *q++) | ||
222 | return 0; | ||
223 | } | ||
224 | if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n') | ||
225 | return 0; | ||
226 | return 1; | ||
227 | } | ||
228 | |||
229 | |||
230 | int | ||
231 | gooddefine(char *line) | ||
232 | { | ||
233 | char *p; | ||
234 | |||
235 | if (! match("#define", line)) | ||
236 | return 0; /* not a define */ | ||
237 | p = line + 7; | ||
238 | while (*p == ' ' || *p == '\t') | ||
239 | p++; | ||
240 | while (*p != ' ' && *p != '\t') { | ||
241 | if (*p == '(') | ||
242 | return 0; /* macro definition */ | ||
243 | p++; | ||
244 | } | ||
245 | while (*p != '\n' && *p != '\0') | ||
246 | p++; | ||
247 | if (p[-1] == '\\') | ||
248 | return 0; /* multi-line definition */ | ||
249 | return 1; | ||
250 | } | ||
251 | |||
252 | |||
253 | void | ||
254 | doevent(struct event *ep, FILE *fp, char *fname) | ||
255 | { | ||
256 | char line[1024]; | ||
257 | int indent; | ||
258 | char *p; | ||
259 | |||
260 | sprintf(line, "\n /* from %s: */\n", fname); | ||
261 | addstr(line, &ep->code); | ||
262 | addstr(" {\n", &ep->code); | ||
263 | for (;;) { | ||
264 | linno++; | ||
265 | if (fgets(line, sizeof line, fp) == NULL) | ||
266 | error("Unexpected EOF"); | ||
267 | if (equal(line, "}\n")) | ||
268 | break; | ||
269 | indent = 6; | ||
270 | for (p = line ; *p == '\t' ; p++) | ||
271 | indent += 8; | ||
272 | for ( ; *p == ' ' ; p++) | ||
273 | indent++; | ||
274 | if (*p == '\n' || *p == '#') | ||
275 | indent = 0; | ||
276 | while (indent >= 8) { | ||
277 | addchar('\t', &ep->code); | ||
278 | indent -= 8; | ||
279 | } | ||
280 | while (indent > 0) { | ||
281 | addchar(' ', &ep->code); | ||
282 | indent--; | ||
283 | } | ||
284 | addstr(p, &ep->code); | ||
285 | } | ||
286 | addstr(" }\n", &ep->code); | ||
287 | } | ||
288 | |||
289 | |||
290 | void | ||
291 | doinclude(char *line) | ||
292 | { | ||
293 | char *p; | ||
294 | char *name; | ||
295 | char **pp; | ||
296 | |||
297 | for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++); | ||
298 | if (*p == '\0') | ||
299 | error("Expecting '\"' or '<'"); | ||
300 | name = p; | ||
301 | while (*p != ' ' && *p != '\t' && *p != '\n') | ||
302 | p++; | ||
303 | if (p[-1] != '"' && p[-1] != '>') | ||
304 | error("Missing terminator"); | ||
305 | *p = '\0'; | ||
306 | |||
307 | /* name now contains the name of the include file */ | ||
308 | for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++); | ||
309 | if (*pp == NULL) | ||
310 | *pp = savestr(name); | ||
311 | } | ||
312 | |||
313 | |||
314 | void | ||
315 | dodecl(char *line1, FILE *fp) | ||
316 | { | ||
317 | char line[1024]; | ||
318 | char *p, *q; | ||
319 | |||
320 | if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */ | ||
321 | addchar('\n', &decls); | ||
322 | do { | ||
323 | linno++; | ||
324 | if (fgets(line, sizeof line, fp) == NULL) | ||
325 | error("Unterminated structure declaration"); | ||
326 | addstr(line, &decls); | ||
327 | } while (line[0] != '}'); | ||
328 | amiddecls = 0; | ||
329 | } else { | ||
330 | if (! amiddecls) | ||
331 | addchar('\n', &decls); | ||
332 | q = NULL; | ||
333 | for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++) | ||
334 | continue; | ||
335 | if (*p == '=') { /* eliminate initialization */ | ||
336 | for (q = p ; *q && *q != ';' ; q++); | ||
337 | if (*q == '\0') | ||
338 | q = NULL; | ||
339 | else { | ||
340 | while (p[-1] == ' ') | ||
341 | p--; | ||
342 | *p = '\0'; | ||
343 | } | ||
344 | } | ||
345 | addstr("extern", &decls); | ||
346 | addstr(line1 + 6, &decls); | ||
347 | if (q != NULL) | ||
348 | addstr(q, &decls); | ||
349 | amiddecls = 1; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | |||
354 | |||
355 | /* | ||
356 | * Write the output to the file OUTTEMP. | ||
357 | */ | ||
358 | |||
359 | void | ||
360 | output(void) | ||
361 | { | ||
362 | FILE *fp; | ||
363 | char **pp; | ||
364 | struct event *ep; | ||
365 | |||
366 | fp = ckfopen(OUTTEMP, "w"); | ||
367 | fputs(writer, fp); | ||
368 | for (pp = header_files ; *pp ; pp++) | ||
369 | fprintf(fp, "#include %s\n", *pp); | ||
370 | fputs("\n\n\n", fp); | ||
371 | writetext(&defines, fp); | ||
372 | fputs("\n\n", fp); | ||
373 | writetext(&decls, fp); | ||
374 | for (ep = event ; ep->name ; ep++) { | ||
375 | fputs("\n\n\n", fp); | ||
376 | fputs(ep->comment, fp); | ||
377 | fprintf(fp, "\nvoid\n%s() {\n", ep->routine); | ||
378 | writetext(&ep->code, fp); | ||
379 | fprintf(fp, "}\n"); | ||
380 | } | ||
381 | fclose(fp); | ||
382 | } | ||
383 | |||
384 | |||
385 | /* | ||
386 | * A text structure is simply a block of text that is kept in memory. | ||
387 | * Addstr appends a string to the text struct, and addchar appends a single | ||
388 | * character. | ||
389 | */ | ||
390 | |||
391 | void | ||
392 | addstr(char *s, struct text *text) | ||
393 | { | ||
394 | while (*s) { | ||
395 | if (--text->nleft < 0) | ||
396 | addchar(*s++, text); | ||
397 | else | ||
398 | *text->nextc++ = *s++; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | |||
403 | void | ||
404 | addchar(int c, struct text *text) | ||
405 | { | ||
406 | struct block *bp; | ||
407 | |||
408 | if (--text->nleft < 0) { | ||
409 | bp = ckmalloc(sizeof *bp); | ||
410 | if (text->start == NULL) | ||
411 | text->start = bp; | ||
412 | else | ||
413 | text->last->next = bp; | ||
414 | text->last = bp; | ||
415 | text->nextc = bp->text; | ||
416 | text->nleft = BLOCKSIZE - 1; | ||
417 | } | ||
418 | *text->nextc++ = c; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * Write the contents of a text structure to a file. | ||
423 | */ | ||
424 | void | ||
425 | writetext(struct text *text, FILE *fp) | ||
426 | { | ||
427 | struct block *bp; | ||
428 | |||
429 | if (text->start != NULL) { | ||
430 | niro | 815 | for (bp = text->start ; bp != text->last ; bp = bp->next) { |
431 | if ((fwrite(bp->text, sizeof (char), BLOCKSIZE, fp)) != BLOCKSIZE) | ||
432 | error("Can't write data\n"); | ||
433 | } | ||
434 | if ((fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp)) != (BLOCKSIZE - text->nleft)) | ||
435 | error("Can't write data\n"); | ||
436 | niro | 532 | } |
437 | } | ||
438 | |||
439 | FILE * | ||
440 | ckfopen(char *file, char *mode) | ||
441 | { | ||
442 | FILE *fp; | ||
443 | |||
444 | if ((fp = fopen(file, mode)) == NULL) { | ||
445 | fprintf(stderr, "Can't open %s\n", file); | ||
446 | exit(2); | ||
447 | } | ||
448 | return fp; | ||
449 | } | ||
450 | |||
451 | void * | ||
452 | ckmalloc(int nbytes) | ||
453 | { | ||
454 | char *p; | ||
455 | |||
456 | if ((p = malloc(nbytes)) == NULL) | ||
457 | error("Out of space"); | ||
458 | return p; | ||
459 | } | ||
460 | |||
461 | char * | ||
462 | savestr(char *s) | ||
463 | { | ||
464 | char *p; | ||
465 | |||
466 | p = ckmalloc(strlen(s) + 1); | ||
467 | strcpy(p, s); | ||
468 | return p; | ||
469 | } | ||
470 | |||
471 | static void | ||
472 | error(char *msg) | ||
473 | { | ||
474 | if (curfile != NULL) | ||
475 | fprintf(stderr, "%s:%d: ", curfile, linno); | ||
476 | fprintf(stderr, "%s\n", msg); | ||
477 | exit(2); | ||
478 | /* NOTREACHED */ | ||
479 | } |