Contents of /trunk/mkinitrd-magellan/klibc/usr/dash/mkinit.c
Parent Directory | Revision Log
Revision 815 -
(show annotations)
(download)
Fri Apr 24 18:32:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 10416 byte(s)
Fri Apr 24 18:32:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 10416 byte(s)
-updated to klibc-1.5.15
1 | /*- |
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 | 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 | } |
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 | } |