source: mainline/uspace/app/ash/tools/mkinit.c@ 8ccd2ea

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8ccd2ea was c28a023, checked in by Josef Cejka <malyzelenyhnus@…>, 17 years ago

Initial commit of ash shell.
It cannot be compiled yet.

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