parag@hpsdeb.sde.hp.com (Parag Patel) (05/19/91)
Submitted-by: Parag Patel <parag@hpsdeb.sde.hp.com> Posting-number: Volume 19, Issue 93 Archive-name: wacco/part06 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is part 06 of wacco # ============= gen.C ============== if test -f 'gen.C' -a X"$1" != X"-c"; then echo 'x - skipping gen.C (File already exists)' else echo 'x - extracting gen.C (Text)' sed 's/^X//' << 'SHAR_EOF' > 'gen.C' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. static const char rcs_id[] = "$Header: gen.C,v 1.29 91/02/22 16:08:02 hmgr Exp $"; X #include "defs.h" #include "toks.h" #include <stdarg.h> X X static FILE *fp = NULL; static long curr_lineno = 1; static const char *currfile = NULL; static const char *inputfile = NULL; X static void putf(char *fmt, ...) { X va_list ap; X char buf[1024]; X X va_start(ap, fmt); X vsprintf(buf, fmt, ap); X va_end(ap); X int nl = 0; X for (char *s = buf; *s != '\0'; s++) X if (*s == '\n') X nl++; X curr_lineno += nl; X fputs(buf, fp); } X inline static void put(int ch) { X putc(ch, fp); X if (ch == '\n') X curr_lineno++; } X X static boolean saveret = FALSE; static char *mkretcode(symbol *s) { X s = NULL; X return saveret ? "_rc = " : "(void)"; } X static const char *mkname(symbol *sym) { X if (*sym->name != '"') X return sym->name; X if (*sym->name == '\'' && sym->type == TERMINAL) X return sym->name; X return strbldf("_S%d/*%s*/", sym->id, sym->name); } X static const char *mkerrname(symbol *sym) { X if (sym->type == NONTERMINAL && sym->realname != NULL) X return sym->realname; X return mkname(sym); } X X static void printset(const char *name, Bitset &set) { X Bitsetiter si(set); X symbol *s; X int id; X char *pre = ""; X X putf("static %s[] = { ", name); X while ((id = si()) >= 0) X { X if (id == EMPTY) X putf("%s_EMPTY", pre); X // continue; X else if (id == END) X putf("%sEOI", pre); X else X { X s = getsymbol(id); X putf("%s%s", pre, mkname(s)); X } X pre = ", "; X } X putf("%s-1 };\n", pre); } X static void printcase(char *pre, Bitset &set) { X Bitsetiter si(set); X symbol *s; X int id; X X while ((id = si()) >= 0) X { X if (id == EMPTY) X continue; X X putf("%scase ", pre); X if (id == END) X putf("EOI"); X else X { X s = getsymbol(id); X putf("%s", mkname(s)); X } X putf(":\n"); X } } X inline static boolean dotype(symbol *sym) { X if ((sym->usedret & RET_VALUE) || sym->rettype != NULL) X return TRUE; X else X return FALSE; } X static const char *mktype(symbol *sym, char *pre = "", char *post = NULL) { X if (!dotype(sym)) X return ""; X char *name; X if (sym->rettype == NULL) X name = "int"; X else X { X name = sym->rettype; X if (sym->mkstruct) X { X if (sym->realname != NULL && sym->realname != sym->name X && sym->rettype == findsymbol(sym->realname)->rettype) X return strbldf("%s_T%s%s", pre, sym->realname, post); X return strbldf("%s_T%s%s", pre, sym->name, post); X } X } X return strbldf("%s%s%s", pre, name, post); } X static const char *mkvoidtype(symbol *sym, char *pre = "", char *post = NULL) { X const char *type = mktype(sym, pre, post); X if (*type == '\0') X type = "void"; X return type; } X static void mkstruct(symbol *sym) { X if (!dotype(sym) || !sym->mkstruct) X return; X char *name = sym->name; X if (sym->realname != NULL && sym->realname != sym->name) X { X symbol *real = findsymbol(sym->realname); X if (real->rettype == sym->rettype) X { X if (dotype(real)) X return; X name = sym->realname; X } X } X putf("\nstruct _T%s\n{\n", name); X putf("\t%s;\n};\n", sym->rettype); } X static void mkcode(char *pre, symbol *code) { X if (code == NULL || code->code == NULL) X return; X X if (genlineinfo) X putf("#line %d \"%s\"\n", code->line, inputfile); X else X putf("/* #line %d */\n", code->line); X putf("%s%s;\n", pre, code->code); X if (genlineinfo) X putf("#line %d \"%s\"\n", curr_lineno + 1, currfile); } X static const char *mkvarname(symnode *start, symnode *node) { X if (node->alias != NULL) X return node->alias; X X int count = 0; X boolean addnum = FALSE; X char *name = node->sym->name; X X if (node->sym->realname != NULL && node->sym->name != node->sym->realname) X { X name = "_"; X for (symnode *n = start; n != node; n = n->next) X if (n->sym->type == NONTERMINAL && n->sym->realname != NULL X && n->sym->name != n->sym->realname) X count++; X for (n = n->next; n != NULL; n = n->next) X if (n->sym->type == NONTERMINAL && n->sym->realname != NULL X && n->sym->name != n->sym->realname) X addnum = TRUE; X } X else X { X for (symnode *n = start; n != node; n = n->next) X if (n->sym == node->sym) X count++; X for (n = n->next; n != NULL; n = n->next) X if (n->sym == node->sym) X addnum = TRUE; X } X if (addnum || count > 0) X return strbldf("%s%d", name, count + 1); X return name; } X X static void genstmt(char *pre, symnode *node) { X symbol *s; X symnode *n; X X for (n = node; n != NULL; n = n->next) X { X if (n->sym->type != NONTERMINAL || n->sym->id == EMPTY X || !dotype(n->sym)) X continue; X putf("%s%s _rv%s;\n", pre, mktype(n->sym), mkvarname(node, n)); X } X X for (n = node; n != NULL; n = n->next) X { X s = n->sym; X if (s->type == CODE) X { X if (dumpcode) X mkcode(pre, s); X continue; X } X if (s->id == EMPTY) X continue; X X if (s->type == TERMINAL) X putf("%s%sscantoken(%s, _link, _resync%d);\n", X pre, mkretcode(s), mkname(s), n->resync->id); X else if (optimize && s->usecount == 1 && !s->export) X { X symbol *sym = s; X symnode *nn = n; X Bitset set(numsymbols()); X X putf("%s{\n", pre); X if (dotype(s)) X putf("%s = _rv%s;\n", mktype(sym, pre, " &_rr"), X mkvarname(node, nn)); X else X putf("%s\n", mktype(sym, pre, " _rr;")); X putf("%sresynclink &_lnk = _link;\n", pre); X putf("%sresynclink _link(_lnk, _resync%d);\n\n", X pre, nn->resync->id); X X if (sym->resync != NULL) X putf("%s (void)scantoken(-1, _link, _resync%d);\n\n", X pre, sym->resync->id); X X if (sym->node != NULL && sym->node->or == NULL) X { X genstmt("\t\t\t", sym->node); X putf("\n%s}\n\n", pre); X // putf("\n%sreturn RETOK;\n}\n\n", pre); X continue; X } X X boolean donedefault = FALSE; X putf("%sswitch (w_nexttoken())\n\t{\n", pre); X for (symnode *n = sym->node; n != NULL; n = n->or) X { X set.clear(); X for (symnode *s = n; s != NULL; s = s->next) X { X if (s->sym->type == CODE) X continue; X set |= *s->sym->first; X if (!s->sym->first->isin(EMPTY)) X break; X } X X if (set.size() == 0 || (set.size() == 1 && set.isin(EMPTY))) X { X donedefault = TRUE; X putf("%s\tdefault:\n", pre); X genstmt("\t\t", n); X if (!sym->first->isin(EMPTY)) X putf("%s\t\tw_scanerr(\"illegal %s\");\n", X pre, mkerrname(sym)); X } X else X { X printcase("\t", set); X putf("\t\t{\n"); X genstmt("\t\t\t", n); X putf("\t\t}\n"); X } X putf("\t\tbreak;\n"); X } X X if (!donedefault && !sym->first->isin(EMPTY)) X { X putf("%s\tdefault:\n", pre); X putf("%s\t\tw_scanerr(\"illegal %s\");\n", X pre, mkerrname(sym)); X } X putf("%s}", pre); X putf(" }\n"); X } X else if (dotype(s)) X putf("%s%s_f%s(_link, _resync%d, _rv%s);\n", X pre, mkretcode(s), mkname(s), X n->resync->id, mkvarname(node, n)); X else X putf("%s%s_f%s(_link, _resync%d);\n", X pre, mkretcode(s), mkname(s), n->resync->id); X // putf(" }\n"); X } } X X static void genheader(void) { X symbol *sym; X int i; X X putf("#ifndef _T_O_K_E_N_S_\n#define _T_O_K_E_N_S_\n\n"); X X putf("#ifndef NULL\n#include <stdio.h>\n#endif\n\n"); X putf("#define RETOK 1\n"); X putf("#define RETERR 0\n\n"); X X putf("enum tokenids\n{\n"); X putf("\tEOI = 0,\n"); X putf("\t_EMPTY = 256, /* nothing uses this yet */\n"); X boolean doid = TRUE; X for (i = START; i < numsymbols(); i++) X { X sym = getsymbol(i); X if (sym->type != TERMINAL || *sym->name == '\'') X continue; X if (doid) X putf("\t%s = 257,\n", mkname(sym)); X else X putf("\t%s,\n", mkname(sym)); X doid = FALSE; X } X putf("};\n\n"); X X if (gotlexstr) X { X putf("#ifdef __cplusplus\n"); X putf("extern \"C\" {\n"); X putf("extern int yylex(void);\n"); X putf("}\n"); X putf("#else\n"); X putf("extern int yylex();\n"); X putf("#endif\n\n"); X X putf("#ifdef FLEX_SCANNER\n"); X putf("# undef YY_INPUT\n"); X putf("# define YY_INPUT(buf,result,max_size) \\\n"); X putf(" result = (buf[0] = w_input()) == EOI ? YY_NULL : 1;\n"); X putf("#else\n"); X putf("# undef input\n"); X putf("# define input w_input\n"); X putf("# undef unput\n"); X putf("# define unput w_unput\n"); X putf("#endif\n\n"); X X } X X putf("extern int w_numerrors;\n"); X putf("#ifdef __cplusplus\n"); X putf("extern \"C\" {\n"); X putf("extern int w_scanerr(const char *, ...);\n"); X putf("extern void w_flusherrs(void);\n"); X putf("extern void w_closefile(void);\n"); X putf("extern int w_openfile(char *);\n"); X putf("extern FILE *w_getfile(void);\n"); X putf("extern void w_setfile(FILE *);\n"); X putf("extern int w_currcol(void);\n"); X putf("extern int w_currline(void);\n"); X putf("extern char *w_getcurrline(void);\n"); X putf("extern int w_input(void);\n"); X putf("extern int w_unput(int);\n"); X putf("extern void w_output(int);\n"); X putf("extern int w_gettoken(void);\n"); X putf("extern int w_nexttoken(void);\n"); X putf("extern void w_skiptoken(void);\n"); X putf("extern char *w_tokenname(int);\n"); X putf("}\n"); X putf("#else\n"); X putf("extern int w_scanerr();\n"); X putf("extern void w_flusherrs();\n"); X putf("extern void w_closefile();\n"); X putf("extern int w_openfile();\n"); X putf("extern FILE *w_getfile();\n"); X putf("extern void w_setfile();\n"); X putf("extern int w_currcol();\n"); X putf("extern int w_currline();\n"); X putf("extern char *w_getcurrline();\n"); X putf("extern int w_input();\n"); X putf("extern int w_unput();\n"); X putf("extern void w_output();\n"); X putf("extern int w_gettoken();\n"); X putf("extern int w_nexttoken();\n"); X putf("extern void w_skiptoken();\n"); X putf("extern char *w_tokenname();\n"); X putf("#endif\n\n"); X X if (exportedname) X { X for (i = 0; i < numnonterms(); i++) X { X sym = getnonterm(i); X if (sym->type != NONTERMINAL || !sym->export) X continue; X mkstruct(sym); X putf("#ifdef __cplusplus\n"); X putf("extern \"C\" { int %s(%s); }\n", mkname(sym), X mkvoidtype(sym, "", " &")); X putf("#else\n"); X putf("extern int %s();\n", mkname(sym)); X putf("#endif\n"); X } X } X else X { X mkstruct(startsymbol); X putf("#ifdef __cplusplus\n"); X putf("extern \"C\" { int %s(%s); }\n", mkname(startsymbol), X mkvoidtype(startsymbol, "", " &")); X putf("#else\n"); X putf("extern int %s();\n", mkname(startsymbol)); X putf("#endif\n"); X } X X putf("\n\n#endif /* _T_O_K_E_N_S_ */\n"); } X X static void genscanner(char *header) { X symbol *sym; X int i, c; X boolean nl = TRUE; X X // scan past the definition section X while ((c = w_input()) != END) X { X if (nl && c == '%') X { X int t = w_input(); X if (t == '%') X break; X put(c); X c = t; X } X put(c); X nl = c == '\n'; X } X X // dump out our header stuff here X putf("%%{\n"); X putf("#include \"%s\"\n", header); X putf("%%}\n"); X X putf("%%%%\n"); X X // print the lexical values from the grammer X for (i = START; i < numsymbols(); i++) X { X symbol *sym = getsymbol(i); X if (sym->type != TERMINAL || sym->lexdef || sym->lexstr == NULL) X continue; X if (casesensitive || sym->name[0] != '"') X putf("%s", sym->lexstr); X else X { X for (char *s = sym->lexstr + 1; X *s != '\0' && !(*s == '"' && *(s + 1) == '\0'); X s++) X if (isalpha(*s)) X putf("[%c%c]", X islower(*s) ? toupper(*s) : *s, X isupper(*s) ? tolower(*s) : *s); X else if (*s == '\\' && *(s+1) == '"') X ; X else X putf("\\%c", *s); X } X putf("\t{ return (int)%s; }\n", mkname(sym)); X sym->lexdef = TRUE; X } X X // now add the rules at the bottom of the source X if (c != END) X while ((c = w_input()) != END) X { X if (nl && c == '%') X { X int t = w_input(); X if (t == '%') X break; X put(c); X c = t; X } X else if (nl && c == '$') X { X char *name = getword(); X if (name == NULL) X quit("Unexpected end-of-w_input"); X sym = findsymbol(name); X X if (sym == NULL) X error("Symbol %s not in grammer", name); X if (sym->lexstr != NULL) X error("Symbol %s lexical string redefined in lex section", X name); X X while ((c = w_input()) == ' ' || c == '\t') X ; X if (c == '\n' || c == END) X putf("\n"); X else X { X for (; c != END && c != '\n'; c = w_input()) X put(c); X putf("\t{ return (int)%s; }", name); X } X sym->lexdef = TRUE; X } X put(c); X nl = c == '\n'; X } X X // check for missing tokens X for (i = START; i < numsymbols(); i++) X { X sym = getsymbol(i); X if (sym->type != TERMINAL || sym->lexdef) X continue; X if (sym->lexstr == NULL) X error("Lexical value for symbol %s is not defined", mkname(sym)); X } X X putf("%%%%\n"); X X // now copy the rest (user code) X if (c != END) X while ((c = w_input()) != END) X put(c); } X X static void dumpexport(symbol *sym) { X putf("int %s(%s)\n{\n", mkname(sym), X mkvoidtype(sym, "", " &ret")); X putf("\tresynclink _link;\n\t"); X printset("_follow", *sym->follow); X putf("\tint _rval;\n"); X putf("\tint _savnum = w_numerrors;\n\n"); X putf("\tw_numerrors = 0;\n"); X putf("\t_rval = _f%s(_link, _follow%s);\n", X mkname(sym), dotype(sym) ? ", ret" : ""); X putf("\tswitch (w_nexttoken())\n\t{\n"); X printcase("\t", *sym->follow); X putf("\t\tbreak;\n"); X putf("\tdefault:\n"); X putf("\t\t_rval = w_scanerr(\"expected end of %s\");\n", X mkname(sym)); X putf("\t}\n"); X putf("\tif (w_numerrors > 0) _rval = RETERR;\n"); X putf("\tw_numerrors += _savnum;\n"); X putf("\tw_scanerr(NULL);\n"); X putf("\treturn _rval;\n"); X putf("}\n\n"); } X X static void genparser(char *header) { X symbol *sym; X symnode *n; X int i; X X putf("#define YYTEXT_DECL unsigned char yytext[]\n\n"); X mkcode("", startcode); X putf("\n#include \"%s\"\n\n", header); X putf("extern YYTEXT_DECL;\n"); X putf("int w_numerrors = 0;\n\n"); X X putf("\nstruct resynclink\n{\n\tresynclink *prev;\n"); X putf("\tint *resync;\n"); X putf("\tresynclink() { prev = 0; resync = 0; }\n"); X putf("\tresynclink(resynclink &p, int *s)"); X putf(" { prev = &p; resync = s; }\n"); X putf("};\n"); X X for (i = 0; i < numnonterms(); i++) X { X sym = getnonterm(i); X if (sym->type != NONTERMINAL) X continue; X if (!sym->export) X mkstruct(sym); X if (optimize && sym->usecount == 1 && !sym->export) X continue; X putf("static _f%s(resynclink &, int *%s);\n", mkname(sym), X mktype(sym, ", ", " &")); X } X putf("\n"); X X putf("static char *_toknams[] =\n{\n"); X putf("\t\"[]\",\n"); X for (i = START; i < numsymbols(); i++) X { X sym = getsymbol(i); X if (sym->type != TERMINAL || *sym->name == '\'') X continue; X char *str = sym->lexstr; X X if (str == NULL) X putf("\t\"%s\",\n", mkname(sym)); X else if (isalpha(*str)) X putf("\t\"%s\",\n", str); X else if (*str == '"' && str[strlen(str) - 1] == '"') X putf("\t%s,\n", sym->lexstr); X else X putf("\t\"%s\",\n", mkname(sym)); X } X putf("};\n\n"); X X putf("char *w_tokenname(int tok)\n{\n"); X putf("\tstatic char buf[6];\n\n"); X putf("\tif (tok > 255)\n"); X putf("\t\treturn _toknams[tok - 256];\n"); X putf("\tif (tok == 0)\n"); X putf("\t\treturn \"EOI\";\n"); X putf("\tbuf[0] = '`'; buf[1] = tok; buf[2] = '\\\'';\n"); X putf("\treturn buf;\n"); X putf("}\n\n"); X X putf("static int tok = -1;\n\n"); X X putf("int w_nexttoken()\n"); X putf("{\n\tif (tok < 0)\n\t\ttok = w_gettoken();\n"); X putf("\treturn tok;\n}\n\n"); X X putf("void w_skiptoken()\n{\n\ttok = -1;\n}\n\n"); X X putf("static int scantoken(int expect, resynclink &lnk, int *resync)\n"); X putf("{\n\tresynclink rlink(lnk, resync);\n\tresynclink *link;\n\n"); X putf("\tif (tok < 0)\n\t\ttok = w_gettoken();\n"); X putf("\tif (expect >= 0 && tok != expect)\n"); X putf("\t\tw_scanerr(\"expected %%s\", w_tokenname(expect));\n"); X putf("\tint level = 1;\n"); X putf("\twhile (tok != expect)\n\t{\n"); X putf("\t\tint l = level;\n"); X putf("\t\tfor (link = &rlink; link != NULL && l-- > 0;"); X putf(" link = link->prev)\n"); X putf("\t\t\tfor (int i = 0; link->resync[i] >= 0; i++)\n"); X putf("\t\t\t\tif (tok == link->resync[i])\n"); X putf("\t\t\t\t\treturn -1;\n\n"); X putf("\t\tw_scanerr(NULL);\n"); X putf("\t\ttok = w_gettoken();\n"); X putf("\t\tif (tok == expect)\n\t\t\tbreak;\n\t\tlevel++;\n"); X putf("\t}\t\n\ttok = -1;\n\treturn expect;\n}\n\n"); X X if (exportedname) X for (i = 0; i < numnonterms(); i++) X { X sym = getnonterm(i); X if (sym->type != NONTERMINAL || !sym->export) X continue; X dumpexport(sym); X } X else X dumpexport(startsymbol); X putf("\n"); X X i = 1; X for (Setiter setiter(settab); setiter; setiter++) X { X Set &set = setiter(); X printset(strbldf("_resync%d", set.id = i++), *set.set); X } X putf("\n"); X X Bitset set(numsymbols()); X for (i = 0; i < numnonterms(); i++) X { X sym = getnonterm(i); X if (sym->type != NONTERMINAL) X { X if (dumpcode) X mkcode("", sym); X continue; X } X if (optimize && sym->usecount < 2 && !sym->export) X { X if (sym->usecount != 1) X error("Warning - non-terminal %s is never used", sym->name); X continue; X } X X putf("static _f%s(resynclink &_lnk, int *_resync%s)\n", X mkname(sym), mktype(sym, ", ", " &_rr")); X putf("{\n\tresynclink _link(_lnk, _resync);\n"); X if ((saveret = (sym->usedret & RET_CODE) ? TRUE : FALSE)) X putf("\tint _rc;\n"); X putf("\n"); X X if (sym->resync != NULL) X { X putf("\t{ "); X //printset("_skip", *sym->resync); X putf("\t (void)scantoken(-1, _link, _resync%d); }\n\n", X sym->resync->id); X } X X if (sym->node != NULL && sym->node->or == NULL) X { X genstmt("\t", sym->node); X putf("\n\treturn RETOK;\n}\n\n"); X continue; X } X X boolean donedefault = FALSE; X putf("\tswitch (w_nexttoken())\n\t{\n"); X for (n = sym->node; n != NULL; n = n->or) X { X set.clear(); X for (symnode *s = n; s != NULL; s = s->next) X { X if (s->sym->type == CODE) X continue; X set |= *s->sym->first; X if (!s->sym->first->isin(EMPTY)) X break; X } X X if (set.size() == 0 || (set.size() == 1 && set.isin(EMPTY))) X { X donedefault = TRUE; X putf("\tdefault:\n"); X genstmt("\t\t", n); X if (!sym->first->isin(EMPTY)) X putf("\t\treturn w_scanerr(\"illegal %s\");\n", X mkerrname(sym)); X } X else X { X printcase("\t", set); X putf("\t\t{\n"); X genstmt("\t\t\t", n); X putf("\t\t}\n"); X } X putf("\t\tbreak;\n"); X } X X if (!donedefault && !sym->first->isin(EMPTY)) X { X putf("\tdefault:\n"); X putf("\t\treturn w_scanerr(\"illegal %s\");\n", X mkerrname(sym)); X } X X putf("\t}\n\treturn RETOK;\n}\n\n"); X } } X X void gencode(char *infile) { X inputfile = infile; X X fp = makefile(headername); X currfile = headername; X curr_lineno = 1; X genheader(); X fclose(fp); X cmpandmv(headername); X X fp = makefile(parsername); X currfile = parsername; X curr_lineno = 1; X genparser(headername); X fclose(fp); X cmpandmv(parsername); X X if (!gotlexstr) X return; X X fp = makefile(scannername); X currfile = scannername; X curr_lineno = 1; X genscanner(headername); X fclose(fp); X cmpandmv(scannername); } SHAR_EOF chmod 0444 gen.C || echo 'restore of gen.C failed' Wc_c="`wc -c < 'gen.C'`" test 18803 -eq "$Wc_c" || echo 'gen.C: original size 18803, current size' "$Wc_c" fi # ============= io.C ============== if test -f 'io.C' -a X"$1" != X"-c"; then echo 'x - skipping io.C (File already exists)' else echo 'x - extracting io.C (Text)' sed 's/^X//' << 'SHAR_EOF' > 'io.C' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. static const char rcs_id[] = "$Header: io.C,v 1.13 91/02/22 16:08:20 hmgr Exp $"; X #include "defs.h" #include "toks.h" #include <stdarg.h> X X #define UNPUT 300 #define MAXERR 36 X X struct errstack { X int col; X boolean skip; X char *err; X errstack() { col = -1; skip = FALSE; err = NULL; } }; X /*********** struct resynclink { X resynclink *prev; X int *resync; X resynclink() { prev = 0; resync = 0; } X resynclink(resynclink &p, int *s) { prev = &p; resync = s; } }; ***********/ X X extern char yytext[]; extern int yylex(); X static char filename[100]; static FILE *fp = stdin; X static int line = -1; static int col = 0; static char linebuf[200] = { '\0' }; static int lineloc = 0; static int ubuf[UNPUT]; static int top = 0; X static int tokcol = 0; static errstack errstk[MAXERR]; static int numerrs = 0; X X void w_flusherrs() { X line++; X if (numerrs <= 0) X return; X X fprintf(stderr, "%d:\t%s", line, linebuf); X if (linebuf[strlen(linebuf) - 1] != '\n') X fprintf(stderr, "\n"); X fprintf(stderr, "\t"); X X int i; X int pcol = 0; X for (i = 0; i < numerrs; i++) X { X for (; pcol < errstk[i].col - 1; pcol++) X fprintf(stderr, linebuf[pcol] == '\t' ? "\t" : X (errstk[i].skip ? "*" : " ")); X X if (i > 0 && errstk[i].col == errstk[i - 1].col) X continue; X X if (linebuf[pcol++] == '\t') X fprintf(stderr, "\t"); X X fprintf(stderr, errstk[i].skip ? "*" : "^"); X } X fprintf(stderr, "\n"); X X int last = -1; X for (i = 0; i < numerrs; i++) X { X if (errstk[i].skip) X continue; X /* ** if (last >= 0 && errstk[i].col == errstk[last].col && X strncmp(errstk[i].err, errstk[last].err, 5) == 0) continue; X last = i; ** */ X X fprintf(stderr, "\t"); X for (int j = 0; j < errstk[i].col - 1; j++) X fprintf(stderr, linebuf[j] == '\t' ? "\t" : " "); X X if (linebuf[j] == '\t') X fprintf(stderr, "\t"); X fprintf(stderr, "%s\n", errstk[i].err); X } X X numerrs = 0; } X X extern int w_numerrors; extern "C" int w_vscanerr(const char *fmt, va_list ap); int w_vscanerr(const char *fmt, va_list ap) { X w_numerrors++; X X if (numerrs >= MAXERR) X { X w_flusherrs(); X line--; X } X X if (errstk[numerrs].err == NULL) X errstk[numerrs].err = strnew(150); X X if (fmt == NULL) X { X errstk[numerrs].skip = TRUE; X errstk[numerrs].col = col; X } X else X { X errstk[numerrs].skip = FALSE; X errstk[numerrs].col = tokcol; X vsprintf(errstk[numerrs].err, (char *)fmt, ap); X } X numerrs++; X return RETERR; } X int w_scanerr(const char *fmt, ...) { X if (fmt == NULL) X { X w_flusherrs(); X return RETERR; X } X X va_list ap; X va_start(ap, fmt); X w_vscanerr(fmt, ap); X va_end(ap); X return RETERR; } X X int w_input() { X int c; X X if (top > 0) X return ubuf[--top]; X c = linebuf[lineloc++]; X while (c == '\0') X { X w_flusherrs(); X lineloc = 0; X tokcol = col = 0; X *linebuf = '\0'; X if (fgets(linebuf, sizeof linebuf - 2, fp) == NULL) X return END; X c = linebuf[lineloc++]; X } X col++; X return c; } X X int w_unput(int c) { X if (top >= UNPUT) X { X fprintf(stderr, "Cannot w_unput any more characters"); X exit(11); X } X ubuf[top++] = c; X return 0; } X X void w_output(int c) { X putchar(c); } X X void w_closefile() { X if (fp == NULL) X return; X fclose(fp); } X X int w_openfile(char *fname) { X if (fp != NULL) X w_closefile(); X if ((fp = fopen(fname, "r")) == NULL) X return RETERR; X strncpy(filename, fname, sizeof filename - 1); X return RETOK; } X X FILE *w_getfile() { X return fp; } X void w_setfile(FILE *f) { X fp = f; X *filename = '\0'; } X int w_currcol() { X return col; } X int w_currline() { X return line + 1; } X char *w_getcurrline() { X return linebuf; } X X int w_gettoken() { X int ret = yylex(); X tokcol = col - strlen(yytext); X return ret; } SHAR_EOF chmod 0444 io.C || echo 'restore of io.C failed' Wc_c="`wc -c < 'io.C'`" test 3832 -eq "$Wc_c" || echo 'io.C: original size 3832, current size' "$Wc_c" fi # ============= version.C ============== if test -f 'version.C' -a X"$1" != X"-c"; then echo 'x - skipping version.C (File already exists)' else echo 'x - extracting version.C (Text)' sed 's/^X//' << 'SHAR_EOF' > 'version.C' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. X static char *const whatid = "@(#)wacco 1.1 (17 May 1991)"; SHAR_EOF chmod 0444 version.C || echo 'restore of version.C failed' Wc_c="`wc -c < 'version.C'`" test 120 -eq "$Wc_c" || echo 'version.C: original size 120, current size' "$Wc_c" fi exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.