Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/dash/mkinit.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 815 - (show 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)
-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 }