Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: didepend.c | |
5 | * | |
6 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
7 | * | |
8 | * - Do no alter or remove copyright notices | |
9 | * | |
10 | * - Redistribution and use of this software in source and binary forms, with | |
11 | * or without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistribution of source code must retain the above copyright notice, | |
15 | * this list of conditions and the following disclaimer. | |
16 | * | |
17 | * - Redistribution in binary form must reproduce the above copyright notice, | |
18 | * this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * | |
21 | * Neither the name of Sun Microsystems, Inc. or the names of contributors | |
22 | * may be used to endorse or promote products derived from this software | |
23 | * without specific prior written permission. | |
24 | * | |
25 | * This software is provided "AS IS," without a warranty of any kind. | |
26 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
27 | * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
28 | * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
29 | * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
30 | * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
31 | * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
32 | * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
33 | * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
34 | * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
35 | * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
36 | * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
37 | * | |
38 | * You acknowledge that this software is not designed, licensed or | |
39 | * intended for use in the design, construction, operation or maintenance of | |
40 | * any nuclear facility. | |
41 | * | |
42 | * ========== Copyright Header End ============================================ | |
43 | */ | |
44 | /* | |
45 | * id: @(#)didepend.c 1.12 04/04/22 | |
46 | * purpose: | |
47 | * copyright: Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved | |
48 | * Use is subject to license terms. | |
49 | */ | |
50 | ||
51 | #include <sys/types.h> | |
52 | #include <sys/stat.h> | |
53 | #include <fcntl.h> | |
54 | #include <string.h> | |
55 | #include <stdio.h> | |
56 | ||
57 | #include "defines.h" | |
58 | ||
59 | #define SOURCE_FLAG 0x01 | |
60 | #define TARGET_FLAG 0x02 | |
61 | #define DEPEND_FLAG 0x04 | |
62 | #define CODE_FLAG 0x08 | |
63 | #define CODE_START 0x10 | |
64 | #define CODE_END 0x20 | |
65 | #define COMPAT_MODE 0x40 | |
66 | ||
67 | #define MAXLINE 512 | |
68 | ||
69 | FILE *ifd; | |
70 | char *buildcmd = NULL; | |
71 | char *progname = NULL; | |
72 | char *filename = NULL; | |
73 | char *codefile = NULL; | |
74 | char *srcfile = NULL; | |
75 | char buffer[ MAXLINE ]; | |
76 | int flags = 0; | |
77 | int line_num = 0; | |
78 | int argcount; | |
79 | int pedantic = 0; | |
80 | int defdepth = 0; | |
81 | int showsyms = 0; | |
82 | int verbose = 0; | |
83 | ||
84 | void | |
85 | usage(void) | |
86 | { | |
87 | fprintf(stderr, "%s: [flag] sourcefile\n", progname); | |
88 | fprintf(stderr, " -D <symbol> : define <symbol>\n"); | |
89 | fprintf(stderr, " -U <symbol> : undefine <symbol>\n"); | |
90 | fprintf(stderr, " -S : show symbols used\n"); | |
91 | fprintf(stderr, " -s : print sources\n"); | |
92 | fprintf(stderr, " -t : print targets\n"); | |
93 | fprintf(stderr, " -d : print dependancies\n"); | |
94 | fprintf(stderr, " -c : print code\n"); | |
95 | fprintf(stderr, " -p : pedantic mode\n"); | |
96 | exit(1); | |
97 | } | |
98 | ||
99 | typedef void * retval; | |
100 | ||
101 | #define CAST(x) (retval) (x) | |
102 | ||
103 | #define CMD_NULL_ARGS 0x00 | |
104 | #define CMD_OPT_ARGS 0x10 | |
105 | #define CMD_COMPAT 0x20 | |
106 | #define CMD_COMPAT_ONLY 0x40 | |
107 | #define CMD_IFDEF 0x80 | |
108 | #define CMD_MASK 0xf0 | |
109 | ||
110 | typedef struct CMD | |
111 | { | |
112 | char *name; | |
113 | retval (*fn)(char *arg0, char *line); | |
114 | int flags; | |
115 | } cmd; | |
116 | ||
117 | retval enable_cmds(char *line, char *arg0); | |
118 | retval disable_cmds(char *line, char *arg0); | |
119 | retval get_source_line(char *line, char *arg0); | |
120 | retval set_build_cmd(char *arg0, char *line); | |
121 | retval grab_depend_line(char *arg0, char *line); | |
122 | retval grab_target_line(char *arg0, char *line); | |
123 | retval grab_external_line(char *arg0, char *line); | |
124 | retval grab_source(char *arg0, char *line); | |
125 | retval comment_line(char *arg0, char *line); | |
126 | retval unexpected_token(char *arg0, char *line); | |
127 | retval get_execute_token(char *arg0, char *line); | |
128 | retval grab_next_file(char *arg0, char *line); | |
129 | retval set_code_file(char *arg0, char *line); | |
130 | retval set_build_flags(char *arg0, char *line); | |
131 | retval do_message(char *arg0, char *line); | |
132 | retval do_define(char *arg0, char *line); | |
133 | retval do_undef(char *arg0, char *line); | |
134 | retval do_ifdef(char *arg0, char *line); | |
135 | retval do_ifndef(char *arg0, char *line); | |
136 | retval do_else(char *arg0, char *line); | |
137 | retval do_endif(char *arg0, char *line); | |
138 | ||
139 | #define COMPAT_NO_ARGS CMD_COMPAT|CMD_NULL_ARGS | |
140 | #define COMPAT_OPT_ARGS CMD_COMPAT|CMD_OPT_ARGS | |
141 | ||
142 | cmd cmds[] = { | |
143 | { "version1", disable_cmds, COMPAT_NO_ARGS }, | |
144 | { "version2", enable_cmds, COMPAT_NO_ARGS }, | |
145 | { "build", set_build_cmd, CMD_OPT_ARGS | 1 }, | |
146 | { "depend", grab_depend_line, 1 }, | |
147 | { "target", grab_target_line, 2 }, | |
148 | { "external", grab_external_line, 1 }, | |
149 | { "source{", grab_source, CMD_OPT_ARGS }, | |
150 | { "}source", unexpected_token, CMD_NULL_ARGS }, | |
151 | { "#", comment_line, COMPAT_OPT_ARGS }, | |
152 | { "-", get_source_line, CMD_COMPAT_ONLY }, | |
153 | { "include", grab_next_file, 1 }, | |
154 | { "codefile", set_code_file, 1 }, | |
155 | { "buildoptions", set_build_flags, CMD_OPT_ARGS | 1 }, | |
156 | { "message", do_message, CMD_OPT_ARGS | 1 }, | |
157 | { "#define", do_define, 1 }, | |
158 | { "#undef", do_undef, 1 }, | |
159 | { "#ifdef", do_ifdef, CMD_IFDEF | 1 }, | |
160 | { "#ifndef", do_ifndef, CMD_IFDEF | 1 }, | |
161 | { "#else", do_else, CMD_IFDEF | CMD_NULL_ARGS }, | |
162 | { "#endif", do_endif, CMD_IFDEF | CMD_NULL_ARGS }, | |
163 | { NULL, NULL, 0 } | |
164 | }; | |
165 | ||
166 | void | |
167 | malloc_failed(void *ptr) | |
168 | { | |
169 | if (ptr == NULL) { | |
170 | fprintf(stderr, "%s:%d: Malloc failed\n", filename, line_num); | |
171 | exit(1); | |
172 | } | |
173 | } | |
174 | ||
175 | char * | |
176 | get_arg(char *line, int which, int *rpos) | |
177 | { | |
178 | static char arg[MAXLINE]; | |
179 | char *tokens = " \t"; | |
180 | char *start; | |
181 | int strip; | |
182 | int len, end, pos, prev; | |
183 | ||
184 | if ((line == NULL) || (*line == 0)) { | |
185 | return (NULL); | |
186 | } | |
187 | ||
188 | end = strlen(line); | |
189 | prev = pos = 0; | |
190 | start = line; | |
191 | while ((which-- >= 0) && (pos < end)) { | |
192 | strip = strspn(start, tokens); | |
193 | start += strip; | |
194 | pos += strip; | |
195 | prev = pos; | |
196 | len = strcspn(start, tokens); | |
197 | pos += len; | |
198 | if ((pos >= end) && (which >= 0)) { | |
199 | if (rpos) *rpos = prev; | |
200 | return (NULL); | |
201 | } | |
202 | if (len) { | |
203 | strncpy(arg, start, len); | |
204 | arg[len] = 0; | |
205 | } else { | |
206 | strcpy(arg, start); | |
207 | } | |
208 | start += len; | |
209 | } | |
210 | if (rpos) *rpos = prev; | |
211 | return (arg); | |
212 | } | |
213 | ||
214 | int | |
215 | count_args(char *line) | |
216 | { | |
217 | int argc; | |
218 | char *lastarg; | |
219 | ||
220 | if (line == NULL) { | |
221 | return (0); | |
222 | } | |
223 | ||
224 | argc = 0; | |
225 | lastarg = line; | |
226 | while (lastarg) { | |
227 | lastarg = get_arg(line, argc+1, NULL); | |
228 | if (lastarg) argc++; | |
229 | } | |
230 | return (argc); | |
231 | } | |
232 | ||
233 | void | |
234 | automatic_message(char comment) | |
235 | { | |
236 | printf("%c\n", comment); | |
237 | printf("%c Warning this is a machine generated file\n", comment); | |
238 | printf("%c Changes made here will go away\n", comment); | |
239 | printf("%c\n", comment); | |
240 | } | |
241 | ||
242 | /* This is gross, but exists for Version1 compatability. */ | |
243 | char *fthsrc = | |
244 | "id: %" "Z%%" "M% %" "I% %" "E%\n" | |
245 | "purpose: %" "Y%\n" | |
246 | "copyright: Copyright 1989-1997 Sun Microsystems, Inc. All Rights Reserved\n" | |
247 | "\n" | |
248 | "\" /packages/SUNW,builtin-drivers\" find-device\n" | |
249 | "\n" | |
250 | ": do-fcode ( str$ -- )\n" | |
251 | " find-drop-in if\n" | |
252 | " 2dup 2>r execute-buffer\n" | |
253 | " 2r> free-drop-in\n" | |
254 | " then\n" | |
255 | ";\n\n"; | |
256 | ||
257 | char * | |
258 | get_line(char *line, int from) | |
259 | { | |
260 | char *argp; | |
261 | int pos; | |
262 | ||
263 | argp = get_arg(line, from, &pos); | |
264 | #if 0 | |
265 | printf("rem_line: '%s'\n", (argp ? argp : "")); | |
266 | #endif | |
267 | if (argp == NULL) { | |
268 | return (""); | |
269 | } | |
270 | return (line + pos); | |
271 | } | |
272 | ||
273 | retval | |
274 | get_more_source(char *cmd, char *line) | |
275 | { | |
276 | int len; | |
277 | char *backslash; | |
278 | ||
279 | printf("get_more_source('%s','%s')\n", | |
280 | (cmd ? cmd : ""), | |
281 | (line ? line : "")); | |
282 | len = strlen(line); | |
283 | if (len > 1) { | |
284 | backslash = line+len-1; | |
285 | if (*backslash == '\\') { | |
286 | *backslash = 0; | |
287 | if (cmd == NULL) | |
288 | printf("%s\n", get_line(line, 2)); | |
289 | else | |
290 | printf("%s\n", line); | |
291 | return (CAST(get_more_source)); | |
292 | } | |
293 | } | |
294 | return (CAST(get_execute_token)); | |
295 | } | |
296 | ||
297 | ||
298 | retval | |
299 | get_source_line(char *cmd, char *line) | |
300 | { | |
301 | char *arg0, *argp, *arg1, *argn; | |
302 | static int once = 0; | |
303 | int tail; | |
304 | ||
305 | #if 0 | |
306 | printf("get_source_line('%s','%s')\n", | |
307 | (cmd ? cmd : "NULL"), | |
308 | (line ? line : "NULL")); | |
309 | #endif | |
310 | arg0 = arg1 = argn = NULL; | |
311 | if (cmd == NULL) { | |
312 | argp = get_arg(line, 0, NULL); | |
313 | if (argp) arg0 = strdup(get_arg(line, 0, NULL)); | |
314 | malloc_failed(arg0); | |
315 | } else { | |
316 | arg0 = strdup(cmd); | |
317 | } | |
318 | ||
319 | argp = get_arg(line, 1, NULL); | |
320 | if (argp) arg1 = strdup(argp); | |
321 | malloc_failed(arg1); | |
322 | ||
323 | argp = get_line(line, 2); | |
324 | if (flags & CODE_FLAG) { | |
325 | if (!once) { | |
326 | printf("%s", fthsrc); | |
327 | once++; | |
328 | } | |
329 | get_more_source(cmd, line); | |
330 | } | |
331 | if (cmd == NULL) { | |
332 | if (flags & SOURCE_FLAG) { | |
333 | printf("%s ", arg0); | |
334 | } | |
335 | if (flags & TARGET_FLAG) { | |
336 | printf("%s ", arg1); | |
337 | } | |
338 | if (flags & DEPEND_FLAG) { | |
339 | printf("%s: %s\n\t%s %s %s\n\n", | |
340 | arg0, arg1, | |
341 | buildcmd, arg0, arg1); | |
342 | } | |
343 | } | |
344 | if (arg0) free(arg0); | |
345 | if (arg1) free(arg1); | |
346 | return (CAST(get_more_source(cmd, line))); | |
347 | } | |
348 | ||
349 | retval | |
350 | enable_cmds(char *arg0, char *line) | |
351 | { | |
352 | flags &= ~COMPAT_MODE; | |
353 | return (CAST(get_execute_token)); | |
354 | } | |
355 | ||
356 | retval | |
357 | disable_cmds(char *arg0, char *line) | |
358 | { | |
359 | flags |= COMPAT_MODE; | |
360 | return (CAST(get_execute_token)); | |
361 | } | |
362 | ||
363 | retval | |
364 | set_build_cmd(char *arg0, char *line) | |
365 | { | |
366 | char *sptr; | |
367 | ||
368 | if (buildcmd) free(buildcmd); | |
369 | sptr = get_line(line, 1); | |
370 | if ((sptr == NULL) || ((sptr != NULL) && (strlen(sptr) == 0))) { | |
371 | fprintf(stderr, "%s:%d: Error, Missing argument\n", | |
372 | filename, line_num); | |
373 | exit(1); | |
374 | } | |
375 | buildcmd = strdup(sptr); | |
376 | malloc_failed(buildcmd); | |
377 | return (CAST(get_execute_token)); | |
378 | } | |
379 | ||
380 | retval | |
381 | set_code_file(char *arg0, char *line) | |
382 | { | |
383 | char *sptr; | |
384 | ||
385 | if (codefile) free(codefile); | |
386 | sptr = get_line(line, 1); | |
387 | if ((sptr == NULL) || ((sptr != NULL) && (strlen(sptr) == 0))) { | |
388 | fprintf(stderr, "%s:%d: Error, Missing argument\n", | |
389 | filename, line_num); | |
390 | exit(1); | |
391 | } | |
392 | codefile = strdup(sptr); | |
393 | malloc_failed(codefile); | |
394 | return (CAST(get_execute_token)); | |
395 | } | |
396 | ||
397 | retval | |
398 | grab_depend_line(char *arg0, char *line) | |
399 | { | |
400 | static int once = 0; | |
401 | ||
402 | if (flags & DEPEND_FLAG) { | |
403 | if (!once++) automatic_message('#'); | |
404 | printf("\ninclude %s\n", get_arg(line, 1, NULL)); | |
405 | } | |
406 | return (CAST(get_execute_token)); | |
407 | } | |
408 | ||
409 | retval | |
410 | grab_target_line(char *arg0, char *line) | |
411 | { | |
412 | char *cptr, *dptr, *source, *target, *diname; | |
413 | int tflags; | |
414 | ||
415 | cptr = get_arg(line, 1, NULL); | |
416 | source = strdup(cptr); | |
417 | malloc_failed(source); | |
418 | dptr = strrchr(cptr, '/'); | |
419 | if (dptr) cptr = dptr+1; | |
420 | target = strdup(cptr); | |
421 | malloc_failed(target); | |
422 | diname = get_arg(line, 2, NULL); | |
423 | cptr = strrchr(target, '.'); | |
424 | if (cptr) *cptr = 0; | |
425 | ||
426 | if (flags & TARGET_FLAG) printf("%s.di ", target); | |
427 | if (flags & SOURCE_FLAG) printf("%s ", source); | |
428 | if (flags & DEPEND_FLAG) { | |
429 | printf("\n%s.di: %s %s\n\t%s %s %s\n", | |
430 | target, srcfile, source, | |
431 | buildcmd, source, diname); | |
432 | } | |
433 | free(target); | |
434 | free(source); | |
435 | return (CAST(get_execute_token)); | |
436 | } | |
437 | ||
438 | retval | |
439 | grab_external_line(char *arg0, char *line) | |
440 | { | |
441 | if (flags & TARGET_FLAG) printf("%s ", get_arg(line, 1, NULL)); | |
442 | return (CAST(get_execute_token)); | |
443 | } | |
444 | ||
445 | retval | |
446 | wait_source_end(char *arg0, char *line) | |
447 | { | |
448 | int end, argc; | |
449 | char *last_arg; | |
450 | ||
451 | printf("wait_source_end('%s','%s')\n", arg0, line); | |
452 | ||
453 | end = (strcmp(arg0, "}source") == 0); | |
454 | if (flags & DEPEND_FLAG) { | |
455 | if (!end) printf("%s\n", line); | |
456 | } | |
457 | if (!end) { | |
458 | return (CAST(wait_source_end)); | |
459 | } | |
460 | return (CAST(get_execute_token)); | |
461 | } | |
462 | ||
463 | retval | |
464 | grab_source(char *arg0, char *line) | |
465 | { | |
466 | static int start_code = 0; | |
467 | static int once = 0; | |
468 | int end, start; | |
469 | int codebase, codeend, codelen; | |
470 | retval (*fn)(char *, char *); | |
471 | char *args; | |
472 | char *lptr = strdup(line); | |
473 | ||
474 | malloc_failed(lptr); | |
475 | ||
476 | fn = grab_source; | |
477 | start = (strcmp(arg0, "source{") == 0); | |
478 | if ((start) && (start_code++)) { | |
479 | fprintf(stderr, "%s:%d: Warning, unbalanced start{ tokens\n", | |
480 | filename, line_num); | |
481 | if (pedantic) exit(1); | |
482 | } | |
483 | if (argcount) | |
484 | (void) get_arg(line, 1, &codebase); | |
485 | else | |
486 | codebase = strlen(arg0); | |
487 | args = get_arg(lptr, argcount, &codeend); | |
488 | end = (strcmp(args, "}source") == 0); | |
489 | ||
490 | if (!start) codebase = 0; | |
491 | if (!end) codeend = strlen(line); | |
492 | ||
493 | codelen = (codeend-codebase); | |
494 | strncpy(lptr, line + codebase, codelen); | |
495 | lptr[codelen] = 0; | |
496 | ||
497 | if (flags & CODE_FLAG) { | |
498 | if (start && !once++) automatic_message('\\'); | |
499 | printf("%s\n", lptr); | |
500 | } | |
501 | ||
502 | if (end) { | |
503 | start_code--; | |
504 | fn = get_execute_token; | |
505 | } | |
506 | free(lptr); | |
507 | return (CAST(fn)); | |
508 | } | |
509 | ||
510 | retval | |
511 | set_build_flags(char *arg0, char *line) | |
512 | { | |
513 | if (flags & DEPEND_FLAG) { | |
514 | printf("\n%s", get_line(line, 1)); | |
515 | } | |
516 | return (CAST(get_execute_token)); | |
517 | } | |
518 | ||
519 | retval | |
520 | comment_line(char *arg0, char *line) | |
521 | { | |
522 | return (CAST(get_execute_token)); | |
523 | } | |
524 | ||
525 | retval | |
526 | do_message(char *arg0, char *line) | |
527 | { | |
528 | if (flags & CODE_FLAG) { | |
529 | fprintf(stderr, "%s:%d: %s\n", | |
530 | filename, line_num, get_line(line, 1)); | |
531 | } | |
532 | return (CAST(get_execute_token)); | |
533 | } | |
534 | ||
535 | retval | |
536 | do_define(char *arg0, char *line) | |
537 | { | |
538 | define_symbol(get_arg(line, 1, NULL), FORTH_DEFINE); | |
539 | return (CAST(get_execute_token)); | |
540 | } | |
541 | ||
542 | retval | |
543 | do_undef(char *arg0, char *line) | |
544 | { | |
545 | define_symbol(get_arg(line, 1, NULL), FORTH_UNDEF); | |
546 | return (CAST(get_execute_token)); | |
547 | } | |
548 | ||
549 | #define DEF_ELSE 1 | |
550 | #define DEF_ENDIF 2 | |
551 | #define DEF_SKIP 4 | |
552 | #define MAX_DEF_DEPTH 5 | |
553 | ||
554 | #define defskip (def_state[defdepth] & DEF_SKIP) | |
555 | ||
556 | static int def_state[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | |
557 | ||
558 | void | |
559 | def_state_check(int state, int flag, char *msg) | |
560 | { | |
561 | if ((state & flag) == 0) { | |
562 | fprintf(stderr, "%s:%d: Parse Error, %s\n", | |
563 | filename, line_num, msg); | |
564 | exit(1); | |
565 | } | |
566 | if (defdepth > MAX_DEF_DEPTH) { | |
567 | fprintf(stderr, "%s:%d: too many Nested IFDEF's\n", | |
568 | filename, line_num); | |
569 | exit(1); | |
570 | } | |
571 | } | |
572 | ||
573 | void | |
574 | do_common_ifdef(char *arg0, char *line, int do_true) | |
575 | { | |
576 | int state = (DEF_ELSE | DEF_ENDIF); | |
577 | int def; | |
578 | ||
579 | def_state_check(1, 1, ""); | |
580 | state |= def_state[defdepth++] & DEF_SKIP; | |
581 | def = symbol_defined(get_arg(line, 1, NULL)); | |
582 | if ((do_true && !def) || (!do_true && def)) { | |
583 | state |= DEF_SKIP; | |
584 | } | |
585 | def_state[defdepth] = state; | |
586 | } | |
587 | ||
588 | retval | |
589 | do_ifdef(char *arg0, char *line) | |
590 | { | |
591 | do_common_ifdef(arg0, line, 1); | |
592 | return (CAST(get_execute_token)); | |
593 | } | |
594 | ||
595 | retval | |
596 | do_ifndef(char *arg0, char *line) | |
597 | { | |
598 | do_common_ifdef(arg0, line, 0); | |
599 | return (CAST(get_execute_token)); | |
600 | } | |
601 | ||
602 | retval | |
603 | do_else(char *arg0, char *line) | |
604 | { | |
605 | def_state_check(def_state[defdepth], DEF_ELSE, "Dangling #else"); | |
606 | def_state[defdepth] &= ~DEF_ELSE; | |
607 | def_state[defdepth] ^= DEF_SKIP; | |
608 | def_state[defdepth] |= def_state[defdepth-1] & DEF_SKIP; | |
609 | return (CAST(get_execute_token)); | |
610 | } | |
611 | ||
612 | retval | |
613 | do_endif(char *arg0, char *line) | |
614 | { | |
615 | def_state_check(def_state[defdepth], DEF_ENDIF, "Dangling #endif"); | |
616 | def_state[defdepth--] &= ~DEF_ENDIF; | |
617 | return (CAST(get_execute_token)); | |
618 | } | |
619 | ||
620 | retval | |
621 | unexpected_token(char *arg0, char *line) | |
622 | { | |
623 | fprintf(stderr, "%s:%d: bad token '%s'\n", filename, line_num, arg0); | |
624 | exit(1); | |
625 | return (NULL); | |
626 | } | |
627 | ||
628 | retval | |
629 | get_execute_token(char *token, char *line) | |
630 | { | |
631 | retval (*fn)(char *p, char *); | |
632 | cmd *cptr = cmds; | |
633 | ||
634 | fn = unexpected_token; | |
635 | while (cptr->name != NULL) { | |
636 | int nargs; | |
637 | ||
638 | if (strcmp(cptr->name, token) != 0) { | |
639 | cptr++; | |
640 | continue; | |
641 | } | |
642 | ||
643 | if (((flags & COMPAT_MODE) && !(cptr->flags & CMD_COMPAT)) || | |
644 | (!(flags & COMPAT_MODE) && (cptr->flags & CMD_COMPAT_ONLY))) | |
645 | unexpected_token(token, line); | |
646 | ||
647 | nargs = cptr->flags & ~CMD_MASK; | |
648 | if (verbose) { | |
649 | printf("[%d,%d] CMD: '%s' args = %d, argc = %d\n", | |
650 | defdepth, defskip, token, nargs, argcount); | |
651 | } | |
652 | ||
653 | if ((argcount > nargs) && (!(cptr->flags & CMD_OPT_ARGS))) { | |
654 | fprintf(stderr, | |
655 | "%s:%d: Warning, extra arguments for '%s'\n", | |
656 | filename, line_num, token); | |
657 | if (pedantic) exit(1); | |
658 | } | |
659 | ||
660 | if (argcount < nargs) { | |
661 | fprintf(stderr, | |
662 | "%s:%d: Missing arguments for '%s'\n", | |
663 | filename, line_num, token); | |
664 | exit(1); | |
665 | } | |
666 | fn = cptr->fn; | |
667 | break; | |
668 | } | |
669 | if ((flags & COMPAT_MODE) && (fn == unexpected_token)) { | |
670 | return (CAST(get_source_line(NULL, line))); | |
671 | } | |
672 | if (!(cptr->flags & CMD_IFDEF) && defskip) { | |
673 | fn = comment_line; | |
674 | } | |
675 | return (CAST((*fn)(token, line))); | |
676 | } | |
677 | ||
678 | void | |
679 | process_file(char *name, int recurse) | |
680 | { | |
681 | char comment = 0; | |
682 | char *savename; | |
683 | FILE *infile; | |
684 | int linenum; | |
685 | int done = 0; | |
686 | retval (*process)(char *line, char *arg); | |
687 | ||
688 | /* | |
689 | * This is a gross hack! I should have made this entire thing parameter | |
690 | * driven, instead I chose to use globals :( | |
691 | * So I need to save and restore them for this cruft to work. | |
692 | */ | |
693 | if (recurse) { | |
694 | if (flags & DEPEND_FLAG) printf("\n%s: %s\n", codefile, name); | |
695 | linenum = line_num; | |
696 | infile = ifd; | |
697 | savename = filename; | |
698 | if (flags & CODE_FLAG) { | |
699 | comment = '\\'; | |
700 | } else if (flags & DEPEND_FLAG) { | |
701 | comment = '#'; | |
702 | } | |
703 | if (comment) printf("\n%c Included from %s\n", comment, name); | |
704 | } | |
705 | filename = strdup(name); | |
706 | malloc_failed(filename); | |
707 | ifd = fopen(filename, "r"); | |
708 | if (ifd == NULL) { | |
709 | fprintf(stderr, "%s: unable to open: %s for reading", | |
710 | progname, filename); | |
711 | exit(1); | |
712 | } | |
713 | ||
714 | process = get_execute_token; | |
715 | line_num = 0; | |
716 | while (!done) { | |
717 | char *line, *cptr; | |
718 | char cmd[MAXLINE]; | |
719 | ||
720 | line_num++; | |
721 | line = fgets(buffer, MAXLINE, ifd); | |
722 | cmd[0] = 0; | |
723 | ||
724 | if (line) { | |
725 | cptr = strchr(line, '\n'); | |
726 | if (cptr) *cptr = 0; | |
727 | argcount = count_args(line); | |
728 | cptr = get_arg(line, 0, NULL); | |
729 | if (cptr) strcpy(cmd, cptr); | |
730 | } | |
731 | done = (line == NULL) || feof(ifd); | |
732 | ||
733 | if (!done) { | |
734 | if (*cmd != 0) | |
735 | process = (retval (*)()) process(cmd, line); | |
736 | } | |
737 | } | |
738 | fclose(ifd); | |
739 | free(filename); | |
740 | if (recurse) { | |
741 | line_num = linenum; | |
742 | ifd = infile; | |
743 | filename = savename; | |
744 | if (comment) printf("\n%c back to %s\n", comment, filename); | |
745 | } | |
746 | } | |
747 | ||
748 | retval | |
749 | grab_next_file(char *arg0, char *line) | |
750 | { | |
751 | char *cptr, eptr; | |
752 | ||
753 | cptr = get_arg(line, 1, NULL); | |
754 | ||
755 | if (flags & DEPEND_FLAG) { | |
756 | printf("\n%s: %s\n", codefile, cptr); | |
757 | } | |
758 | ||
759 | process_file(cptr, 1); | |
760 | ||
761 | return (CAST(get_execute_token)); | |
762 | } | |
763 | ||
764 | main(int argc, char **argv) | |
765 | { | |
766 | extern char *optarg; | |
767 | extern int optind; | |
768 | int errflg = 0; | |
769 | int c; | |
770 | ||
771 | progname = argv[0]; | |
772 | while ((c = getopt(argc, argv, "D:U:SVstdcp")) != EOF) | |
773 | switch (c) { | |
774 | case 'D': | |
775 | define_symbol(optarg, CMD_DEFINE); | |
776 | break; | |
777 | case 'U': | |
778 | define_symbol(optarg, CMD_UNDEF); | |
779 | break; | |
780 | case 'S': | |
781 | showsyms = 1; | |
782 | break; | |
783 | case 'V': | |
784 | verbose = 1; | |
785 | break; | |
786 | case 's': | |
787 | if (!flags) flags = SOURCE_FLAG; else usage(); | |
788 | break; | |
789 | ||
790 | case 't': | |
791 | if (!flags) flags = TARGET_FLAG; else usage(); | |
792 | break; | |
793 | ||
794 | case 'd': | |
795 | if (!flags) flags = DEPEND_FLAG; else usage(); | |
796 | break; | |
797 | ||
798 | case 'c': | |
799 | if (!flags) flags = CODE_FLAG; else usage(); | |
800 | break; | |
801 | ||
802 | case 'p': | |
803 | pedantic++; | |
804 | break; | |
805 | ||
806 | default: | |
807 | usage(); | |
808 | } | |
809 | ||
810 | if (!flags) usage(); | |
811 | flags |= COMPAT_MODE; | |
812 | ||
813 | progname = argv[0]; | |
814 | (void) set_build_cmd(NULL, "build\t${MAKEDI}"); | |
815 | (void) set_code_file(NULL, "codefile\tbuiltin.fth"); | |
816 | srcfile = argv[optind]; | |
817 | process_file(srcfile, 0); | |
818 | finish_symbols(showsyms); | |
819 | exit(0); | |
820 | } |