int assemble(char *file) { char ofile[100], incfile[20], *p; int i, of; strcpy(ofile, file); if(p = strrchr(ofile, pathchar())) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(p = strrchr(outfile, '.')) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = strrchr(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } p = getenv("INCLUDE"); if(p) { setinclude(p); } else { if(systemtype(Plan9)) { sprint(incfile,"/%s/include", thestring); setinclude(strdup(incfile)); } } of = mycreat(outfile, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); pass = 1; nosched = 0; pinit(file); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); if(nerrors) { cclean(); return nerrors; } pass = 2; nosched = 0; outhist(); pinit(file); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); cclean(); return nerrors; }
int assemble(char *file) { char *ofile, *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) strcpy(ofile, file); p = utfrrune(ofile, pathchar()); if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(outfile){ p = utfrrune(outfile, '.'); if(p) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } else outfile = "/dev/null"; } of = create(outfile, OWRITE, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); pass = 1; pinit(file); Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); if(nerrors) { cclean(); return nerrors; } Bprint(&obuf, "\n!\n"); pass = 2; outhist(); pinit(file); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); cclean(); return nerrors; }
int preprocess() { ++lptr; lastch = ' '; NextToken(); /* get first word on line */ if( lastst != id ) { error(ERR_PREPROC); return getline(incldepth == 0); } if( strcmp(lastid,"include") == 0 ) return doinclude(); else if( strcmp(lastid,"define") == 0 ) return dodefine(); else if (strcmp(lastid,"ifdef")==0) return doifdef(); else if (strcmp(lastid,"ifndef")==0) return doifndef(); else if (strcmp(lastid,"endif")==0) return doendif(); else { error(ERR_PREPROC); return getline(incldepth == 0); } }
int parse() { token=getlex(); do { if (token <= 0) return 1; if (istoken('#')) { if (istoken(T_DEFINE)) dodefine(); else if (istoken(T_INCLUDE)) doinclude(); else error1("define oder include erwartet"); } else{ typeName(); if (token=='(') dofunc(); else doglob(); } } while(1); }
int do_sw_commands(char *cp) { while(*cp) { switch(*cp++) { case 'D': dodefine(cp); return 1; case 'I': EiC_insertpath(cp); return 1; case '\?': case 'h': case 'H': usage(); case 'c': case 'C': EiC_TIMER = 1; break; #ifndef NO_HTML case 'e': // connect stderr to stdout dup2(1,2); // setup stdout to behave like stderr if(setvbuf(stdout,NULL,_IONBF,0) != 0) EiC_error("failed to setup stdout\n"); // inform the browser puts("Content-type: text/plain\n\n"); break; #endif case 'v': case 'V': puts(Version); exit(1); case 'R': prompt = 1; case 'r': reStart = 1; break; case 's': case 'S': silent = 1; break; case 'f': ScriptMode = 1; break; case 'p': EiC_SHOWLINE = 1; break; case 'P': EiC_showIncludes = 1; break; case 't': case 'T': EiC_traceON = 1; break; case 'n': HistoryFile = 0; break; case 'N': StartUpH = 0; break; case 'A': EiC_Interact = 0; break; default: while(isspace(*cp)) cp++; if(*cp == '-') /* assume script mode */ while(isspace(*++cp)); else if(*cp) /* catch for lines ending with whitespace */ return 0; } } return 1; }
/** * process all input text * at this level, only static declarations, defines, includes, * and function definitions are legal. */ void parse(void) { while (!input_eof) { if (match("#")) { if (match("asm")) doasm(); else if (match("include")) doinclude(); else if (match("define")) dodefine(); else if (match("undef")) doundef(); } else if (amatch("extern", 6)) do_declarations(EXTERN, NULL_TAG, 0); else if (amatch("static", 6)) do_declarations(STATIC, NULL_TAG, 0); else if (do_declarations(PUBLIC, NULL_TAG, 0)) ; else { newfunc(); } blanks(); } }
void control(Tokenrow *trp) { Nlist *np; Token *tp; tp = trp->tp; if (tp->type!=NAME) { if (tp->type==NUMBER) goto kline; if (tp->type != NL) error(ERROR, "Unidentifiable control line"); return; /* else empty line */ } if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) { error(WARNING, "Unknown preprocessor control %t", tp); return; } if (skipping) { if ((np->flag&ISKW)==0) return; switch (np->val) { case KENDIF: if (--ifdepth<skipping) skipping = 0; --cursource->ifdepth; setempty(trp); return; case KIFDEF: case KIFNDEF: case KIF: if (++ifdepth >= NIF) error(FATAL, "#if too deeply nested"); ++cursource->ifdepth; return; case KELIF: case KELSE: if (ifdepth<=skipping) break; return; default: return; } } switch (np->val) { case KDEFINE: dodefine(trp); break; case KUNDEF: tp += 1; if (tp->type!=NAME || trp->lp - trp->bp != 4) { error(ERROR, "Syntax error in #undef"); break; } if ((np = lookup(tp, 0)) != NULL) np->flag &= ~ISDEFINED; break; case KPRAGMA: return; case KIFDEF: case KIFNDEF: case KIF: if (++ifdepth >= NIF) error(FATAL, "#if too deeply nested"); ++cursource->ifdepth; ifsatisfied[ifdepth] = 0; if (eval(trp, np->val)) ifsatisfied[ifdepth] = 1; else skipping = ifdepth; break; case KELIF: if (ifdepth==0) { error(ERROR, "#elif with no #if"); return; } if (ifsatisfied[ifdepth]==2) error(ERROR, "#elif after #else"); if (eval(trp, np->val)) { if (ifsatisfied[ifdepth]) skipping = ifdepth; else { skipping = 0; ifsatisfied[ifdepth] = 1; } } else skipping = ifdepth; break; case KELSE: if (ifdepth==0 || cursource->ifdepth==0) { error(ERROR, "#else with no #if"); return; } if (ifsatisfied[ifdepth]==2) error(ERROR, "#else after #else"); if (trp->lp - trp->bp != 3) error(ERROR, "Syntax error in #else"); skipping = ifsatisfied[ifdepth]? ifdepth: 0; ifsatisfied[ifdepth] = 2; break; case KENDIF: if (ifdepth==0 || cursource->ifdepth==0) { error(ERROR, "#endif with no #if"); return; } --ifdepth; --cursource->ifdepth; if (trp->lp - trp->bp != 3) error(WARNING, "Syntax error in #endif"); break; case KERROR: trp->tp = tp+1; error(WARNING, "#error directive: %r", trp); break; case KLINE: trp->tp = tp+1; expandrow(trp, "<line>"); tp = trp->bp+2; kline: if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){ error(ERROR, "Syntax error in #line"); return; } cursource->line = atol((char*)tp->t)-1; if (cursource->line<0 || cursource->line>=32768) error(WARNING, "#line specifies number out of range"); tp = tp+1; if (tp+1<trp->lp) cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0); return; case KDEFINED: error(ERROR, "Bad syntax for control line"); break; case KINCLUDE: doinclude(trp); trp->lp = trp->bp; return; case KEVAL: eval(trp, np->val); break; default: error(ERROR, "Preprocessor control `%t' not yet implemented", tp); break; } setempty(trp); return; }
int main(int argc, char *argv[]) { int c; int n; int rval; char *p; setlocale(LC_ALL, ""); traceout = stderr; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); initkwds(); initspaces(); STACKMAX = INITSTACKMAX; mstack = (stae *)xalloc(sizeof(stae) * STACKMAX); sstack = (char *)xalloc(STACKMAX); maxout = 0; outfile = NULL; resizedivs(MAXOUT); while ((c = getopt(argc, argv, "gst:d:D:U:o:I:")) != -1) switch(c) { case 'D': /* define something..*/ for (p = optarg; *p; p++) if (*p == '=') break; if (p == optarg) errx(1, "null variable cannot be defined"); if (*p) *p++ = EOS; dodefine(optarg, p); break; case 'I': addtoincludepath(optarg); break; case 'U': /* undefine... */ remhash(optarg, TOP); break; case 'g': mimic_gnu = 1; break; case 'd': set_trace_flags(optarg); break; case 's': synccpp = 1; break; case 't': mark_traced(optarg, 1); break; case 'o': trace_file(optarg); break; case '?': default: usage(); } argc -= optind; argv += optind; rval = 0; active = stdout; /* default active output */ bbase[0] = bufbase; if (!argc) { sp = -1; /* stack pointer initialized */ fp = 0; /* frame pointer initialized */ set_input(infile+0, stdin, "stdin"); /* default input (naturally) */ if ((inname[0] = strdup("-")) == NULL) err(1, NULL); inlineno[0] = 1; emitline(); macro(); } else for (; argc--; ++argv) { p = *argv; if (p[0] == '-' && p[1] == EOS) set_input(infile, stdin, "stdin"); else if (fopen_trypath(infile, p) == NULL) { warn("%s", p); rval = 1; continue; } sp = -1; fp = 0; if ((inname[0] = strdup(p)) == NULL) err(1, NULL); inlineno[0] = 1; emitline(); macro(); release_input(infile); } if (*m4wraps) { /* anything for rundown ?? */ ilevel = 0; /* in case m4wrap includes.. */ bufbase = bp = buf; /* use the entire buffer */ pbstr(m4wraps); /* user-defined wrapup act */ macro(); /* last will and testament */ } if (active != stdout) active = stdout; /* reset output just in case */ for (n = 1; n < maxout; n++) /* default wrap-up: undivert */ if (outfile[n] != NULL) getdiv(n); /* remove bitbucket if used */ if (outfile[0] != NULL) { (void) fclose(outfile[0]); } exit(rval); }
int main(int argc, char *argv[]) { int c; int n; char *p; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); init_macros(); initspaces(); STACKMAX = INITSTACKMAX; mstack = xreallocarray(NULL, STACKMAX, sizeof(stae), NULL); sstack = xalloc(STACKMAX, NULL); maxout = 0; outfile = NULL; resizedivs(MAXOUT); while ((c = getopt(argc, argv, "gst:d:D:U:o:I:P")) != -1) switch(c) { case 'D': /* define something..*/ for (p = optarg; *p; p++) if (*p == '=') break; if (*p) *p++ = EOS; dodefine(optarg, p); break; case 'I': addtoincludepath(optarg); break; case 'P': prefix_builtins = 1; break; case 'U': /* undefine... */ macro_popdef(optarg); break; case 'g': mimic_gnu = 1; break; case 'd': set_trace_flags(optarg); break; case 's': synch_lines = 1; break; case 't': mark_traced(optarg, 1); break; case 'o': trace_file(optarg); break; case '?': usage(); } argc -= optind; argv += optind; initkwds(); if (mimic_gnu) setup_builtin("format", FORMATTYPE); active = stdout; /* default active output */ bbase[0] = bufbase; if (!argc) { sp = -1; /* stack pointer initialized */ fp = 0; /* frame pointer initialized */ set_input(infile+0, stdin, "stdin"); /* default input (naturally) */ macro(); } else for (; argc--; ++argv) { p = *argv; if (p[0] == '-' && p[1] == EOS) set_input(infile, stdin, "stdin"); else if (fopen_trypath(infile, p) == NULL) err(1, "%s", p); sp = -1; fp = 0; macro(); release_input(infile); } if (wrapindex) { int i; ilevel = 0; /* in case m4wrap includes.. */ bufbase = bp = buf; /* use the entire buffer */ if (mimic_gnu) { while (wrapindex != 0) { for (i = 0; i < wrapindex; i++) pbstr(m4wraps[i]); wrapindex =0; macro(); } } else { for (i = 0; i < wrapindex; i++) { pbstr(m4wraps[i]); macro(); } } } if (active != stdout) active = stdout; /* reset output just in case */ for (n = 1; n < maxout; n++) /* default wrap-up: undivert */ if (outfile[n] != NULL) getdiv(n); /* remove bitbucket if used */ if (outfile[0] != NULL) { (void) fclose(outfile[0]); } return exit_code; }
int control(int counter) /* * Process #control lines. Simple commands are processed inline, * while complex commands have their own subroutines. * * The counter is used to force out a newline before #line, and * #pragma commands. This prevents these commands from ending up at * the end of the previous line if cpp is invoked with the -C option. */ { register int c; register char *tp; register int hash; char *ep; c = skipws(); if (c == '\n' || c == EOF_CHAR) return (counter + 1); if (!isdigit(c)) scanid(c); /* Get #word to token[] */ else { unget(); /* Hack -- allow #123 as a */ strcpy(token, "line"); /* synonym for #line 123 */ } hash = (token[1] == EOS) ? L_nogood : (token[0] + (token[2] << 1)); switch (hash) { case L_assert: tp = "assert"; break; case L_define: tp = "define"; break; case L_elif: tp = "elif"; break; case L_else: tp = "else"; break; case L_endif: tp = "endif"; break; case L_if: tp = "if"; break; case L_ifdef: tp = "ifdef"; break; case L_ifndef: tp = "ifndef"; break; case L_include: tp = "include"; break; case L_line: tp = "line"; break; case L_pragma: tp = "pragma"; break; case L_undef: tp = "undef"; break; case L_error: tp = "error"; break; #if OSL_DEBUG_LEVEL > 1 case L_debug: tp = "debug"; break; case L_nodebug: tp = "nodebug"; break; #endif default: hash = L_nogood; case L_nogood: tp = ""; break; } if (!streq(tp, token)) hash = L_nogood; /* * hash is set to a unique value corresponding to the * control keyword (or L_nogood if we think it's nonsense). */ if (infile->fp == NULL) cwarn("Control line \"%s\" within macro expansion", token); if (!compiling) { /* Not compiling now */ switch (hash) { case L_if: /* These can't turn */ case L_ifdef: /* compilation on, but */ case L_ifndef: /* we must nest #if's */ if (++ifptr >= &ifstack[BLK_NEST]) goto if_nest_err; *ifptr = 0; /* !WAS_COMPILING */ case L_line: /* Many */ /* * Are pragma's always processed? */ case L_pragma: /* options */ case L_include: /* are uninteresting */ case L_define: /* if we */ case L_undef: /* aren't */ case L_assert: /* compiling. */ case L_error: /* BP 5.3.92, #error */ dump_line: skipnl(); /* Ignore rest of line */ return (counter + 1); } } /* * Make sure that #line and #pragma are output on a fresh line. */ if (counter > 0 && (hash == L_line || hash == L_pragma)) { PUTCHAR('\n'); counter--; } switch (hash) { case L_line: /* * Parse the line to update the line number and "progname" * field and line number for the next input line. * Set wrongline to force it out later. */ c = skipws(); workp = work; /* Save name in work */ while (c != '\n' && c != EOF_CHAR) { save(c); c = get(); } unget(); save(EOS); /* * Split #line argument into <line-number> and <name> * We subtract 1 as we want the number of the next line. */ line = atoi(work) - 1; /* Reset line number */ for (tp = work; isdigit(*tp) || type[(int)*tp] == SPA; tp++) ; /* Skip over digits */ if (*tp != EOS) { /* Got a filename, so: */ if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) { tp++; /* Skip over left quote */ *ep = EOS; /* And ignore right one */ } if (infile->progname != NULL) /* Give up the old name */ free(infile->progname); /* if it's allocated. */ infile->progname = savestring(tp); } wrongline = TRUE; /* Force output later */ break; case L_include: doinclude(); break; case L_define: dodefine(); break; case L_undef: doundef(); break; case L_else: if (ifptr == &ifstack[0]) goto nest_err; else if ((*ifptr & ELSE_SEEN) != 0) goto else_seen_err; *ifptr |= ELSE_SEEN; if ((*ifptr & WAS_COMPILING) != 0) { if (compiling || (*ifptr & TRUE_SEEN) != 0) compiling = FALSE; else { compiling = TRUE; } } break; case L_elif: if (ifptr == &ifstack[0]) goto nest_err; else if ((*ifptr & ELSE_SEEN) != 0) { else_seen_err: cerror("#%s may not follow #else", token); goto dump_line; } if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) { compiling = FALSE; /* Done compiling stuff */ goto dump_line; /* Skip this clause */ } doif(L_if); break; case L_if: case L_ifdef: case L_ifndef: if (++ifptr >= &ifstack[BLK_NEST]) if_nest_err: cfatal("Too many nested #%s statements", token); *ifptr = WAS_COMPILING; doif(hash); break; case L_endif: if (ifptr == &ifstack[0]) { nest_err: cerror("#%s must be in an #if", token); goto dump_line; } if (!compiling && (*ifptr & WAS_COMPILING) != 0) wrongline = TRUE; compiling = ((*ifptr & WAS_COMPILING) != 0); --ifptr; break; case L_assert: if (eval() == 0) cerror("Preprocessor assertion failure", NULLST); break; case L_pragma: /* * #pragma is provided to pass "options" to later * passes of the compiler. cpp doesn't have any yet. */ fprintf( pCppOut, "#pragma "); while ((c = get()) != '\n' && c != EOF_CHAR) cput(c); unget(); break; #if OSL_DEBUG_LEVEL > 1 case L_debug: if (debug == 0) dumpdef("debug set on"); debug++; break; case L_nodebug: debug--; break; #endif case L_error: /* BP 5.3.92, #error */ { fprintf( pCppOut, "cpp: line %u, Error directive: ", line ); while ((c = get()) != '\n' && c != EOF_CHAR) cput(c); fprintf( pCppOut, "\n" ); exit( 1 ); break; } default: /* * Undefined #control keyword. * Note: the correct behavior may be to warn and * pass the line to a subsequent compiler pass. * This would allow #asm or similar extensions. */ cerror("Illegal # command \"%s\"", token); break; } if (hash != L_include) { #if OLD_PREPROCESSOR /* * Ignore the rest of the #control line so you can write * #if foo * #endif foo */ goto dump_line; /* Take common exit */ #else if (skipws() != '\n') { cwarn("Unexpected text in #control line ignored", NULLST); skipnl(); } #endif } return (counter + 1); }
int prep (void) /* Check for preprocessor commands */ { int b, c; char *ln; ln = line; while (*(++ln) == '#' || *ln == ' ') /* locate first directive character */ ; if ( ! *ln) /* NULL directive */ return (killine ()); /* fprintf(stderr,"prep - line=%s\n",ln); */ if (strcmp2 (ln, "if ") || strcmp2 (ln, "ifdef ") || strcmp2 (ln, "ifndef ")) { /* fprintf(stderr,"prep - calling doif(%s)\n",ln); */ doif (ln); return (killine ()); } if (strcmp2 (ln, "else")) { doelse (); return (killine ()); } if (strcmp2 (ln, "endif")) { doendif (); return (killine ()); } if (strcmp2 (ln, "elif ")) { doelif (ln); return (killine ()); } if (procsw) { if (strcmp2 (ln, "define ")) { c = getident (ln, 7) + 2; /* get end of identifier */ splittok (ln, c); /* tokenize rest of line */ dodefine (strlen (line), &ln[7] - line); /* store #define info */ /* fprintf(stderr,"PREP (after dodef): line=|%s|\n",line); */ tstdupdef (); /* Check for def duplication and fix */ return (killine ()); /* Discard #define line */ } if (strcmp2 (ln, "include ")) { doinclude (&ln[8]); /* open include file */ return (killine ()); /* Discard #include line */ } if (strcmp2 (ln, "undef ")) { /* fprintf(stderr,"prep - undef found %s\n",ln); */ doundef (&ln[6]); /* remove undef identifier from def table */ /* fprintf(stderr,"prep - doundef done\n"); */ return (killine ()); /* Discard #undef line */ } if (strcmp2 (ln, "error ")) { fprintf (stderr, "User error - %s\n", &ln[6]); /* print error */ return (killine ()); /* Discard #error line */ } if (strcmp2 (ln, "asm")) { for (;;) /* send all following lines through for assembler */ { getln (0); if (eflag) break; if (findstr (1, line, "#endasm")) break; if (cflag) puts ("#2"); else printf ("#pragma asm "); printf ("%s\n", line); } if (eflag && cflag) /* error only in Microware mode (no #endasm) */ doerr (18, 1); return (killine ()); } if (strcmp2 (ln, "pragma ")) { dopragma (ln + 7); return (killine ()); } if (strcmp2 (ln, "line ")) { doline (ln + 5); return (killine ()); } doerr (17, 1); /* Illegal preprocessor directive */ return (killine ()); } }
int main(int argc, char ** argv) { EiC_init_EiC(); /* the macro PLATFORM * is passed in by the * compiler */ dodefine("_EiC"); dodefine(&(xstr(PLATFORM)[1])); #ifdef PPCLIB prs("Starting EiC...\n"); setvbuf(stdout,NULL,_IONBF,0); EiC_add_builtinfunc("puts",eic_puts); EiC_add_builtinfunc("gets",eic_gets); EiC_add_builtinfunc("putch",eic_putch); EiC_add_builtinfunc("getch",eic_getch); EiC_add_builtinfunc("getchq",eic_getchq); EiC_add_builtinfunc("in",eic_in); EiC_add_builtinfunc("out",eic_out); EiC_add_builtinfunc("load",eic_load); EiC_add_builtinfunc("printf",eic_printf); EiC_add_builtinfunc("sprintf",eic_sprintf); EiC_add_builtinfunc("scanf",eic_scanf); EiC_add_builtinfunc("sscanf",eic_sscanf); EiC_add_builtinfunc("setvbuf",eic_setvbuf); /* string .h */ EiC_add_builtinfunc("memcpy",eic_memcpy); EiC_add_builtinfunc("memmove",eic_memmove); EiC_add_builtinfunc("strcpy",eic_strcpy); EiC_add_builtinfunc("strncpy",eic_strncpy); EiC_add_builtinfunc("strcat",eic_strcat); EiC_add_builtinfunc("strncat",eic_strncat); EiC_add_builtinfunc("memcmp",eic_memcmp); EiC_add_builtinfunc("strcmp",eic_strcmp); EiC_add_builtinfunc("strcoll",eic_strcoll); EiC_add_builtinfunc("strncmp",eic_strncmp); EiC_add_builtinfunc("strxfrm",eic_strxfrm); EiC_add_builtinfunc("memchr",eic_memchr); EiC_add_builtinfunc("strchr",eic_strchr); EiC_add_builtinfunc("strcspn",eic_strcspn); EiC_add_builtinfunc("strpbrk",eic_strpbrk); EiC_add_builtinfunc("strrchr",eic_strrchr); EiC_add_builtinfunc("strspn",eic_strspn); EiC_add_builtinfunc("strstr",eic_strstr); EiC_add_builtinfunc("strtok",eic_strtok); EiC_add_builtinfunc("memset",eic_memset); EiC_add_builtinfunc("strerror",eic_strerror); EiC_add_builtinfunc("strlen",eic_strlen); EiC_add_builtinfunc("strrev", eic_strrev); /* stdlib.h */ EiC_add_builtinfunc("_itoa", eic_itoa); EiC_add_builtinfunc("_ltoa", eic_ltoa); EiC_add_builtinfunc("fftoa", eic_fftoa); EiC_add_builtinfunc("malloc", eic_malloc); EiC_add_builtinfunc("calloc", eic_calloc); EiC_add_builtinfunc("realloc", eic_realloc); EiC_add_builtinfunc("free", eic_free); EiC_add_builtinfunc("strtod", eic_strtod); EiC_add_builtinfunc("strtol", eic_strtol); EiC_add_builtinfunc("strtoul", eic_strtoul); EiC_add_builtinfunc("rand", eic_rand); EiC_add_builtinfunc("srand", eic_srand); EiC_add_builtinfunc("atoi", eic_atoi); EiC_add_builtinfunc("atof", eic_atof); EiC_add_builtinfunc("atol", eic_atol); EiC_add_builtinfunc("abort",eic_exit); EiC_add_builtinfunc("eic_exit",eic_exit); EiC_add_builtinfunc("div",eic_div); EiC_add_builtinfunc("ldiv",eic_ldiv); EiC_add_builtinfunc("acos",eic_acos); EiC_add_builtinfunc("asin",eic_asin); EiC_add_builtinfunc("atan",eic_atan); EiC_add_builtinfunc("atan2",eic_atan2); EiC_add_builtinfunc("cos",eic_cos); EiC_add_builtinfunc("sin",eic_sin); EiC_add_builtinfunc("tan",eic_tan); EiC_add_builtinfunc("cosh",eic_cosh); EiC_add_builtinfunc("sinh",eic_sinh); EiC_add_builtinfunc("tanh",eic_tanh); EiC_add_builtinfunc("exp",eic_exp); EiC_add_builtinfunc("frexp",eic_frexp); EiC_add_builtinfunc("ldexp",eic_ldexp); EiC_add_builtinfunc("log",eic_log); EiC_add_builtinfunc("log10",eic_log10); EiC_add_builtinfunc("modf",eic_modf); EiC_add_builtinfunc("pow",eic_pow); EiC_add_builtinfunc("sqrt",eic_sqrt); EiC_add_builtinfunc("ceil",eic_ceil); EiC_add_builtinfunc("fabs",eic_fabs); EiC_add_builtinfunc("floor",eic_floor); EiC_add_builtinfunc("fmod",eic_fmod); startstr=loadstring; /* load defines */ /* strcat(startstr,"typedef struct {void *p, *sp, *ep;} ptr_t;\n"); strcat(startstr,"typedef struct { ptr_t _ptr; int _cnt; ptr_t _base;\\\n"); strcat(startstr,"unsigned short _flag; short _fd; unsigned long _pid;\\\n"); strcat(startstr,"unsigned _bsize; ptr_t _tmpnam; char _sbuf[4];\\\n"); strcat(startstr,"unsigned _entry; }FILE;\n"); strcat(startstr,"int fgetc(FILE * fp);\n"); strcat(startstr,"int fputc(int c, FILE * fp);\n"); strcat(startstr,"char * fgets(char *s, int n, FILE *fp);\n"); strcat(startstr,"int fputs(const char *s, FILE *fp);\n"); */ #endif EiC_startEiC(argc, argv); return 0; }
/** * control - 处理预处理控制指令(头文件包含指令,行控制指令,条件编译指令) * @trp: 一行源程序的Token * 返回值:无 */ void control(Tokenrow *trp) { Nlist *np; Token *tp; tp = trp->tp; /* 获得Tokenrow中的当前Token(指向预处理控制指令关键字) */ if (tp->type!=NAME) { /* 如果当前Token不是标识符 */ if (tp->type==NUMBER) /* 如果当前Token是数字 */ goto kline; /* 跳转,处理行控制指令 */ if (tp->type != NL) /* 如果该Token既不是标识符,也不是数字 */ error(ERROR, "Unidentifiable control line"); /* 则,打印信息`无法识别的控制指令行' */ return; /* 该行处理完毕,函数返回(该行为空行,无控制信息,else empty line) */ } /* 如果当前Token是标识符但标识符不在标识符hash表中 或 标识符在hash表中但不是关键字且不能略过(TODO:啥是略过?) */ if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) { error(WARNING, "Unknown preprocessor control %t", tp); /* 打印信息,无法识别的预处理控制指令 */ return; /* 该行处理完毕 */ } if (skipping) { /* TODO: 啥是skipping? */ if ((np->flag&ISKW)==0) /* 如果np不是关键字 */ return; /* 函数返回 */ switch (np->val) { case KENDIF: if (--ifdepth<skipping) skipping = 0; --cursource->ifdepth; setempty(trp); return; case KIFDEF: case KIFNDEF: case KIF: if (++ifdepth >= NIF) error(FATAL, "#if too deeply nested"); ++cursource->ifdepth; return; case KELIF: case KELSE: if (ifdepth<=skipping) break; return; default: return; } } switch (np->val) { case KDEFINE: /* #define,定义宏 */ dodefine(trp); /* 定义宏 */ break; case KUNDEF: /* #undef */ tp += 1; /* tp指向宏名 */ if (tp->type!=NAME || trp->lp - trp->bp != 4) { /* 如果tp不是标识符类型 或者 lp-bp!=4 (lp和bp之间有4个Token) */ error(ERROR, "Syntax error in #undef"); /* 打印错误信息 */ break; } if ((np = lookup(tp, 0)) != NULL) /* 如果在hash表中找到了tp所指向的宏名 */ np->flag &= ~ISDEFINED; /* 清零ISDEFINED标志位 */ break; case KPRAGMA: /* #pragma */ return; case KIFDEF: /* #ifdef */ case KIFNDEF: /* #ifndef */ case KIF: /* #if */ if (++ifdepth >= NIF) /* 全局条件编译语句的嵌套深度值加1 */ error(FATAL, "#if too deeply nested"); /* 如果嵌套深度值大于NIF,则打印错误信息 `#if中嵌入太深' */ ++cursource->ifdepth; /* 当前输入源的条件编译语句的嵌套深度值加1 */ ifsatisfied[ifdepth] = 0; /* 设定条件编译语句的嵌套深度值对应的if语句还未被满足 */ if (eval(trp, np->val)) ifsatisfied[ifdepth] = 1; else skipping = ifdepth; break; case KELIF: /* #elif */ if (ifdepth==0) { error(ERROR, "#elif with no #if"); return; } if (ifsatisfied[ifdepth]==2) error(ERROR, "#elif after #else"); if (eval(trp, np->val)) { if (ifsatisfied[ifdepth]) skipping = ifdepth; else { skipping = 0; ifsatisfied[ifdepth] = 1; } } else skipping = ifdepth; break; case KELSE: /* #else */ if (ifdepth==0 || cursource->ifdepth==0) { error(ERROR, "#else with no #if"); return; } if (ifsatisfied[ifdepth]==2) error(ERROR, "#else after #else"); if (trp->lp - trp->bp != 3) error(ERROR, "Syntax error in #else"); skipping = ifsatisfied[ifdepth]? ifdepth: 0; ifsatisfied[ifdepth] = 2; break; case KENDIF: /* #endif */ if (ifdepth==0 || cursource->ifdepth==0) { error(ERROR, "#endif with no #if"); return; } --ifdepth; --cursource->ifdepth; if (trp->lp - trp->bp != 3) error(WARNING, "Syntax error in #endif"); break; case KERROR: /* #error */ trp->tp = tp+1; error(WARNING, "#error directive: %r", trp); break; case KLINE: /* #line */ trp->tp = tp+1; expandrow(trp, "<line>"); tp = trp->bp+2; kline: /* 行控制信息处理(line control)*/ if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')) { /* 如果行控制语法有误 */ /* 上面的if判断中共有5种语法错误检查: * 1. 如果只有`# 123\n' * 2. 如果当前token不是数字类型 * 3. 如果有类似`# 123 "file.c" 2 3'的行,那么这种行不被lcc的预处理程序支持。TODO:lcc不支持行控制中的flag语法. * 4. 如果在`# linenum filename'中,filename不是字符串 * 5. 如果filename是宽字符字符串 */ error(ERROR, "Syntax error in #line"); /* 打印错误信息 */ return; /* 该函数返回 */ } cursource->line = atol((char*)tp->t)-1; /* 更新当前输入源的行号信息 */ if (cursource->line<0 || cursource->line>=32768) /* 如果转化后的行号小于0或者行号大于32768 */ error(WARNING, "#line specifies number out of range"); /* 打印错误信息 */ tp = tp+1; /* 指针移动到filename位置 */ if (tp+1<trp->lp) /* 如果filename存在(因为filename后通常紧跟一个换行符token) */ cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0); /* 保存输入源的文件名 */ return; /* 该行处理完毕,函数返回 */ case KDEFINED: /* #defined */ error(ERROR, "Bad syntax for control line"); /* 打印语法错误提示 */ break; case KINCLUDE: /* #include */ doinclude(trp); trp->lp = trp->bp; return; case KEVAL: /* #eval */ eval(trp, np->val); break; default: /* # other */ error(ERROR, "Preprocessor control `%t' not yet implemented", tp); /* 未实现的预处理控制指令 */ break; } setempty(trp); /* 置空Tokenrow */ return; }
ReturnCode control( struct Global *global, int *counter ) /* Pending newline counter */ { /* * Process #control lines. Simple commands are processed inline, * while complex commands have their own subroutines. * * The counter is used to force out a newline before #line, and * #pragma commands. This prevents these commands from ending up at * the end of the previous line if cpp is invoked with the -C option. */ int c; char *tp; int hash; char *ep; ReturnCode ret; c = skipws( global ); if( c == '\n' || c == EOF_CHAR ) { (*counter)++; return(FPP_OK); } if( !isdigit(c) ) scanid( global, c ); /* Get #word to tokenbuf */ else { unget( global ); /* Hack -- allow #123 as a */ strcpy( global->tokenbuf, "line" ); /* synonym for #line 123 */ } hash = (global->tokenbuf[1] == EOS) ? L_nogood : (global->tokenbuf[0] + (global->tokenbuf[2] << 1)); switch( hash ) { case L_assert: tp = "assert"; break; case L_define: tp = "define"; break; case L_elif: tp = "elif"; break; case L_else: tp = "else"; break; case L_endif: tp = "endif"; break; case L_error: tp = "error"; break; case L_if: tp = "if"; break; case L_ifdef: tp = "ifdef"; break; case L_ifndef: tp = "ifndef"; break; case L_include: tp = "include"; break; case L_line: tp = "line"; break; case L_pragma: tp = "pragma"; break; case L_undef: tp = "undef"; break; default: hash = L_nogood; case L_nogood: tp = ""; break; } if( !streq( tp, global->tokenbuf ) ) hash = L_nogood; /* * hash is set to a unique value corresponding to the * control keyword (or L_nogood if we think it's nonsense). */ if( global->infile->fp == NULL ) cwarn( global, WARN_CONTROL_LINE_IN_MACRO, global->tokenbuf ); if( !compiling ) { /* Not compiling now */ switch( hash ) { case L_if: /* These can't turn */ case L_ifdef: /* compilation on, but */ case L_ifndef: /* we must nest #if's */ if( ++global->ifptr >= &global->ifstack[BLK_NEST] ) { cfatal( global, FATAL_TOO_MANY_NESTINGS, global->tokenbuf ); return( FPP_TOO_MANY_NESTED_STATEMENTS ); } *global->ifptr = 0; /* !WAS_COMPILING */ case L_line: /* Many */ /* * Are pragma's always processed? */ case L_pragma: /* options */ case L_include: /* are uninteresting */ case L_define: /* if we */ case L_undef: /* aren't */ case L_assert: /* compiling. */ case L_error: dump_line( global, counter ); /* Ignore rest of line */ return(FPP_OK); } } /* * Make sure that #line and #pragma are output on a fresh line. */ if( *counter > 0 && (hash == L_line || hash == L_pragma) ) { Putchar( global, '\n' ); (*counter)--; } switch( hash ) { case L_line: /* * Parse the line to update the line number and "progname" * field and line number for the next input line. * Set wrongline to force it out later. */ c = skipws( global ); global->workp = global->work; /* Save name in work */ while( c != '\n' && c != EOF_CHAR ) { if( (ret = save( global, c )) ) return(ret); c = get( global ); } unget( global ); if( (ret = save( global, EOS )) ) return(ret); /* * Split #line argument into <line-number> and <name> * We subtract 1 as we want the number of the next line. */ global->line = atoi(global->work) - 1; /* Reset line number */ for( tp = global->work; isdigit(*tp) || type[(unsigned)*tp] == SPA; tp++) ; /* Skip over digits */ if( *tp != EOS ) { /* Got a filename, so: */ if( *tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL ) { tp++; /* Skip over left quote */ *ep = EOS; /* And ignore right one */ } if( global->infile->progname != NULL ) /* Give up the old name if it's allocated. */ free( global->infile->progname ); global->infile->progname = savestring( global, tp ); } global->wrongline = TRUE; /* Force output later */ break; case L_include: ret = doinclude( global ); if( ret ) return(ret); break; case L_define: ret = dodefine( global ); if( ret ) return(ret); break; case L_undef: doundef( global ); break; case L_else: if( global->ifptr == &global->ifstack[0] ) { cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf ); dump_line( global, counter ); return( FPP_OK ); } else if( (*global->ifptr & ELSE_SEEN) != 0 ) { cerror( global, ERROR_STRING_MAY_NOT_FOLLOW_ELSE, global->tokenbuf ); dump_line( global, counter ); return( FPP_OK ); } *global->ifptr |= ELSE_SEEN; if( (*global->ifptr & WAS_COMPILING) != 0 ) { if( compiling || (*global->ifptr & TRUE_SEEN) != 0 ) compiling = FALSE; else { compiling = TRUE; } } break; case L_elif: if( global->ifptr == &global->ifstack[0] ) { cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf ); dump_line( global, counter ); return( FPP_OK ); } else if( (*global->ifptr & ELSE_SEEN) != 0 ) { cerror( global, ERROR_STRING_MAY_NOT_FOLLOW_ELSE, global->tokenbuf ); dump_line( global, counter ); return( FPP_OK ); } if( (*global->ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING ) { compiling = FALSE; /* Done compiling stuff */ dump_line( global, counter ); /* Skip this clause */ return( FPP_OK ); } ret = doif( global, L_if ); if( ret ) return(ret); break; case L_error: cerror(global, ERROR_ERROR); break; case L_if: case L_ifdef: case L_ifndef: if( ++global->ifptr < &global->ifstack[BLK_NEST] ) { *global->ifptr = WAS_COMPILING; ret = doif( global, hash ); if( ret ) return(ret); break; } cfatal( global, FATAL_TOO_MANY_NESTINGS, global->tokenbuf ); return( FPP_TOO_MANY_NESTED_STATEMENTS ); case L_endif: if( global->ifptr == &global->ifstack[0] ) { cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf ); dump_line( global, counter ); return(FPP_OK); } if( !compiling && (*global->ifptr & WAS_COMPILING) != 0 ) global->wrongline = TRUE; compiling = ((*global->ifptr & WAS_COMPILING) != 0); --global->ifptr; break; case L_assert: { int result; ret = eval( global, &result ); if(ret) return(ret); if( result == 0 ) cerror( global, ERROR_PREPROC_FAILURE ); } break; case L_pragma: /* * #pragma is provided to pass "options" to later * passes of the compiler. cpp doesn't have any yet. */ Putstring( global, "#pragma " ); while( (c = get( global ) ) != '\n' && c != EOF_CHAR ) Putchar( global, c ); unget( global ); Putchar( global, '\n' ); break; default: /* * Undefined #control keyword. * Note: the correct behavior may be to warn and * pass the line to a subsequent compiler pass. * This would allow #asm or similar extensions. */ if( global->warnillegalcpp ) cwarn( global, WARN_ILLEGAL_COMMAND, global->tokenbuf ); Putchar( global, '#' ); Putstring( global, global->tokenbuf ); Putchar( global, ' ' ); while( (c = get( global ) ) != '\n' && c != EOF_CHAR ) Putchar( global, c ); unget( global ); Putchar( global, '\n' ); break; } if( hash != L_include ) { #if OLD_PREPROCESSOR /* * Ignore the rest of the #control line so you can write * #if foo * #endif foo */ dump_line( global, counter ); /* Take common exit */ return( FPP_OK ); #else if (skipws(global) != '\n') { cwarn( global, WARN_UNEXPECTED_TEXT_IGNORED ); skipnl( global ); } #endif } (*counter)++; return( FPP_OK ); }
/* **************************************************************** * Analisa uma Linha de Controle * **************************************************************** */ void directive (void) { SYMTB *sp, **link_place; MAJOR maj; char *cp, c; /* * Convenção da STACK: * 'U': é indefinido, e nunca foi definido * 'N': é indefinido, mas já foi definido * 'D': é definido */ if ((maj = scan ()) == EOL) { skipline (); return; } if (maj != ID || !TYPE (sp, token.l_name, S_KEYWORD)) { err_msg ( ERRO, TOKMARK, "Esperava uma diretiva de préprocessamento" ); skipline (); return; } switch (sp->s_index) { case DEFINE: if (falselevel == 0) dodefine (); break; case UNDEF: if (falselevel == 0) doundef (); break; case INCLUDE: if (falselevel == 0) { doinclude (); return; } break; case IF: if (falselevel == 0) { if (expression ()) { *stackp++ = 'D'; putoutnl (); } else { *stackp++ = 'U'; falselevel++; } /* * A análise de expressões já processou * o fim de linha. Não devemos avançar mais. */ return; } else { *stackp++ = 'U'; falselevel++; } break; case IFDEF: if (scan () != ID) { err_msg (ERRO, TOKMARK, "Esperava um identificador"); *stackp++ = 'D'; break; } if (TYPE (sp, token.l_name, S_MACRO)) { *stackp++ = 'D'; if (falselevel == 0) putoutnl (); } else { *stackp++ = 'U'; falselevel++; } break; case IFNDEF: if (scan () != ID) { err_msg (ERRO, TOKMARK, "Esperava um identificador"); *stackp++ = 'D'; break; } if (!TYPE (sp, token.l_name, S_MACRO)) { *stackp++ = 'D'; if (falselevel == 0) putoutnl (); } else { *stackp++ = 'U'; falselevel++; } break; case ELIF: if (stackp <= stack) { err_msg ( ERRO, TOKMARK, "\"elif\" sem prévio \"if\" ou \"ifdef\"" ); break; } switch (stackp[-1]) { case 'U': if (falselevel == 1) { if (expression ()) { stackp[-1] = 'D'; falselevel--; /* == 0 */ putlineno (lineno); } else { /* Nada faz */ } return; } else { /* Nada faz */ } break; case 'N': /* Nada faz */ break; case 'D': stackp[-1] = 'N'; falselevel++; putoutnl (); break; default: err_msg ( ERRO, TOKMARK, "Estado inválido da STACK: '%c'", stackp[-1] ); } break; case ELSE: if (stackp <= stack) { err_msg ( ERRO, TOKMARK, "\"else\" sem prévio \"if\" ou \"ifdef\"" ); break; } switch (stackp[-1]) { case 'U': stackp[-1] = 'D'; if (--falselevel == 0) putlineno (lineno + 1); break; case 'N': /* Nada faz */ break; case 'D': stackp[-1] = 'U'; falselevel++; break; default: err_msg ( ERRO, TOKMARK, "Estado inválido da STACK: '%c'", stackp[-1] ); } break; case ENDIF: if (stackp <= stack) { err_msg ( ERRO, TOKMARK, "\"endif\" sem prévio \"if\" ou \"ifdef\"" ); break; } switch (*--stackp) { case 'U': case 'N': if (--falselevel == 0) putlineno (lineno + 1); break; case 'D': putoutnl (); break; default: err_msg ( ERRO, TOKMARK, "Estado inválido da STACK: '%c'", stackp[0] ); } break; case ERROR: if (falselevel == 0) { const char *msg; for (cp = (char *)nextp; CATEG (cp) == SEPAR; cp++) /* vazio */; msg = cp; while (*cp != '\n' && (*cp != '/' || cp[1] != '*')) cp++; c = *cp; *cp = '\0'; err_msg (ERRO, NOMARK, msg); *cp = c; nextp = msg; putoutnl (); } break; case PRAGMA: if (falselevel == 0) dopragma (); break; case LINE: if (falselevel == 0) { if (scan () != ICTE) { err_msg ( ERRO, TOKMARK, "Esperava uma constante" ); }; lineno = token.l_ival - 1; if (scan () == STR) { srcname = token.l_begin + 1; ((char *)token.l_end)[0] = '\0'; scan (); } return; } break; default: err_msg ( COMP, TOKMARK, "Erro no s_index para diretivas" ); } /* end switch (sp->s_index) */ skipline (); } /* end directive */
int assemble(char *file) { char *ofile, incfile[20], *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) strcpy(ofile, file); p = utfrrune(ofile, '/'); if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(outfile){ p = utfrrune(outfile, '.'); if(p) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = utfrune(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } else outfile = "/dev/null"; } p = getenv("INCLUDE"); if(p) { setinclude(p); } else { if(systemtype(Plan9)) { sprint(incfile,"/%s/include", thestring); setinclude(strdup(incfile)); } } of = create(outfile, OWRITE, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); pass = 1; pinit(file); Bprint(&obuf, "%s\n", thestring); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); if(nerrors) { cclean(); return nerrors; } Bprint(&obuf, "\n!\n"); pass = 2; outhist(); pinit(file); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); cclean(); return nerrors; }
/* * expand_builtin - evaluate built-in macros. */ void expand_builtin(const char *argv[], int argc, int td) { int c, n; int ac; static int sysval = 0; #ifdef DEBUG printf("argc = %d\n", argc); for (n = 0; n < argc; n++) printf("argv[%d] = %s\n", n, argv[n]); fflush(stdout); #endif /* * if argc == 3 and argv[2] is null, then we * have macro-or-builtin() type call. We adjust * argc to avoid further checking.. */ /* we keep the initial value for those built-ins that differentiate * between builtin() and builtin. */ ac = argc; if (argc == 3 && !*(argv[2]) && !mimic_gnu) argc--; switch (td & TYPEMASK) { case DEFITYPE: if (argc > 2) dodefine(argv[2], (argc > 3) ? argv[3] : null); break; case PUSDTYPE: if (argc > 2) dopushdef(argv[2], (argc > 3) ? argv[3] : null); break; case DUMPTYPE: dodump(argv, argc); break; case TRACEONTYPE: dotrace(argv, argc, 1); break; case TRACEOFFTYPE: dotrace(argv, argc, 0); break; case EXPRTYPE: /* * doexpr - evaluate arithmetic * expression */ { int base = 10; int maxdigits = 0; const char *errstr; if (argc > 3) { base = strtonum(argv[3], 2, 36, &errstr); if (errstr) { m4errx(1, "expr: base %s invalid.", argv[3]); } } if (argc > 4) { maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr); if (errstr) { m4errx(1, "expr: maxdigits %s invalid.", argv[4]); } } if (argc > 2) pbnumbase(expr(argv[2]), base, maxdigits); break; } case IFELTYPE: if (argc > 4) doifelse(argv, argc); break; case IFDFTYPE: /* * doifdef - select one of two * alternatives based on the existence of * another definition */ if (argc > 3) { if (lookup_macro_definition(argv[2]) != NULL) pbstr(argv[3]); else if (argc > 4) pbstr(argv[4]); } break; case LENGTYPE: /* * dolen - find the length of the * argument */ pbnum((argc > 2) ? strlen(argv[2]) : 0); break; case INCRTYPE: /* * doincr - increment the value of the * argument */ if (argc > 2) pbnum(atoi(argv[2]) + 1); break; case DECRTYPE: /* * dodecr - decrement the value of the * argument */ if (argc > 2) pbnum(atoi(argv[2]) - 1); break; case SYSCTYPE: /* * dosys - execute system command */ if (argc > 2) { fflush(stdout); sysval = system(argv[2]); } break; case SYSVTYPE: /* * dosysval - return value of the last * system call. * */ pbnum(sysval); break; case ESYSCMDTYPE: if (argc > 2) doesyscmd(argv[2]); break; case INCLTYPE: if (argc > 2) if (!doincl(argv[2])) { if (mimic_gnu) { warn("%s at line %lu: include(%s)", CURRENT_NAME, CURRENT_LINE, argv[2]); exit_code = 1; } else err(1, "%s at line %lu: include(%s)", CURRENT_NAME, CURRENT_LINE, argv[2]); } break; case SINCTYPE: if (argc > 2) (void) doincl(argv[2]); break; #ifdef EXTENDED case PASTTYPE: if (argc > 2) if (!dopaste(argv[2])) err(1, "%s at line %lu: paste(%s)", CURRENT_NAME, CURRENT_LINE, argv[2]); break; case SPASTYPE: if (argc > 2) (void) dopaste(argv[2]); break; case FORMATTYPE: doformat(argv, argc); break; #endif case CHNQTYPE: dochq(argv, ac); break; case CHNCTYPE: dochc(argv, argc); break; case SUBSTYPE: /* * dosub - select substring * */ if (argc > 3) dosub(argv, argc); break; case SHIFTYPE: /* * doshift - push back all arguments * except the first one (i.e. skip * argv[2]) */ if (argc > 3) { for (n = argc - 1; n > 3; n--) { pbstr(rquote); pbstr(argv[n]); pbstr(lquote); pushback(COMMA); } pbstr(rquote); pbstr(argv[3]); pbstr(lquote); } break; case DIVRTYPE: if (argc > 2 && (n = atoi(argv[2])) != 0) dodiv(n); else { active = stdout; oindex = 0; } break; case UNDVTYPE: doundiv(argv, argc); break; case DIVNTYPE: /* * dodivnum - return the number of * current output diversion */ pbnum(oindex); break; case UNDFTYPE: /* * doundefine - undefine a previously * defined macro(s) or m4 keyword(s). */ if (argc > 2) for (n = 2; n < argc; n++) macro_undefine(argv[n]); break; case POPDTYPE: /* * dopopdef - remove the topmost * definitions of macro(s) or m4 * keyword(s). */ if (argc > 2) for (n = 2; n < argc; n++) macro_popdef(argv[n]); break; case MKTMTYPE: /* * dotemp - create a temporary file */ if (argc > 2) { int fd; char *temp; temp = xstrdup(argv[2]); fd = mkstemp(temp); if (fd == -1) err(1, "%s at line %lu: couldn't make temp file %s", CURRENT_NAME, CURRENT_LINE, argv[2]); close(fd); pbstr(temp); free(temp); } break; case TRNLTYPE: /* * dotranslit - replace all characters in * the source string that appears in the * "from" string with the corresponding * characters in the "to" string. */ if (argc > 3) { char *temp; temp = xalloc(strlen(argv[2])+1, NULL); if (argc > 4) map(temp, argv[2], argv[3], argv[4]); else map(temp, argv[2], argv[3], null); pbstr(temp); free(temp); } else if (argc > 2) pbstr(argv[2]); break; case INDXTYPE: /* * doindex - find the index of the second * argument string in the first argument * string. -1 if not present. */ pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); break; case ERRPTYPE: /* * doerrp - print the arguments to stderr * file */ if (argc > 2) { for (n = 2; n < argc; n++) fprintf(stderr, "%s ", argv[n]); fprintf(stderr, "\n"); } break; case DNLNTYPE: /* * dodnl - eat-up-to and including * newline */ while ((c = gpbc()) != '\n' && c != EOF) ; break; case M4WRTYPE: /* * dom4wrap - set up for * wrap-up/wind-down activity */ if (argc > 2) dom4wrap(argv[2]); break; case EXITTYPE: /* * doexit - immediate exit from m4. */ killdiv(); exit((argc > 2) ? atoi(argv[2]) : 0); break; case DEFNTYPE: if (argc > 2) for (n = 2; n < argc; n++) dodefn(argv[n]); break; case INDIRTYPE: /* Indirect call */ if (argc > 2) doindir(argv, argc); break; case BUILTINTYPE: /* Builtins only */ if (argc > 2) dobuiltin(argv, argc); break; case PATSTYPE: if (argc > 2) dopatsubst(argv, argc); break; case REGEXPTYPE: if (argc > 2) doregexp(argv, argc); break; case LINETYPE: doprintlineno(infile+ilevel); break; case FILENAMETYPE: doprintfilename(infile+ilevel); break; case SELFTYPE: pbstr(rquote); pbstr(argv[1]); pbstr(lquote); break; default: m4errx(1, "eval: major botch."); break; } }
void main(int argc, char *argv[]) { char ofile[100], incfile[20], *p; int nout, nproc, status, i, c, of; thechar = '7'; /* of 9 */ thestring = "alpha"; memset(debug, 0, sizeof(debug)); cinit(); outfile = 0; include[ninclude++] = "."; ARGBEGIN { default: c = ARGC(); if(c >= 0 || c < sizeof(debug)) debug[c] = 1; break; case 'o': outfile = ARGF(); break; case 'D': p = ARGF(); if(p) Dlist[nDlist++] = p; break; case 'I': p = ARGF(); if(p) include[ninclude++] = p; break; } ARGEND if(*argv == 0) { print("usage: %ca [-options] file.s\n", thechar); errorexit(); } nproc = 3; if(p = getenv("NPROC")) nproc = atol(p); if(argc > 1) { c = 0; nout = 0; for(;;) { while(nout < nproc && argc > 0) { i = fork(); if(i < 0) { i = mywait(&status); if(i < 0) errorexit(); if(status) c++; nout--; continue; } if(i == 0) { print("%s:\n", *argv); goto child; } nout++; argc--; argv++; } i = mywait(&status); if(i < 0) { if(c) errorexit(); exits(0); } if(status) c++; nout--; } } child: strecpy(ofile, ofile+sizeof ofile, *argv); if(p = strrchr(ofile, '/')) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; if(p = strrchr(outfile, '.')) if(p[1] == 's' && p[2] == 0) p[0] = 0; p = strrchr(outfile, 0); p[0] = '.'; p[1] = thechar; p[2] = 0; } if(0) { strcpy(incfile, "/usr/%include"); p = strrchr(incfile, '%'); if(p) *p = thechar; } else { strcpy(incfile, "/"); strcat(incfile, thestring); strcat(incfile, "/include"); } include[ninclude++] = incfile; if(p = getenv("INCLUDE")) include[ninclude-1] = p; /* */ of = mycreat(outfile, 0664); if(of < 0) { yyerror("%ca: cannot create %s", thechar, outfile); errorexit(); } Binit(&obuf, of, OWRITE); pass = 1; pinit(*argv); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); if(nerrors) { cclean(); errorexit(); } pass = 2; outhist(); pinit(*argv); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); yyparse(); cclean(); if(nerrors) errorexit(); exits(0); }