1*65390Sbostic /**************************************************************** 2*65390Sbostic Copyright (C) AT&T 1993 3*65390Sbostic All Rights Reserved 4*65390Sbostic 5*65390Sbostic Permission to use, copy, modify, and distribute this software and 6*65390Sbostic its documentation for any purpose and without fee is hereby 7*65390Sbostic granted, provided that the above copyright notice appear in all 8*65390Sbostic copies and that both that the copyright notice and this 9*65390Sbostic permission notice and warranty disclaimer appear in supporting 10*65390Sbostic documentation, and that the name of AT&T or any of its entities 11*65390Sbostic not be used in advertising or publicity pertaining to 12*65390Sbostic distribution of the software without specific, written prior 13*65390Sbostic permission. 14*65390Sbostic 15*65390Sbostic AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16*65390Sbostic INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 17*65390Sbostic IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 18*65390Sbostic SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19*65390Sbostic WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 20*65390Sbostic IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21*65390Sbostic ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 22*65390Sbostic THIS SOFTWARE. 23*65390Sbostic ****************************************************************/ 24*65390Sbostic 25*65390Sbostic #define DEBUG 26*65390Sbostic #include <stdio.h> 27*65390Sbostic #include <string.h> 28*65390Sbostic #include <ctype.h> 29*65390Sbostic #include <errno.h> 30*65390Sbostic #include <stdlib.h> 31*65390Sbostic #include "awk.h" 32*65390Sbostic #include "y.tab.h" 33*65390Sbostic 34*65390Sbostic #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p)) 35*65390Sbostic #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p)) 36*65390Sbostic 37*65390Sbostic FILE *infile = NULL; 38*65390Sbostic uchar *file = (uchar*) ""; 39*65390Sbostic int recsize = RECSIZE; 40*65390Sbostic uchar *recdata; 41*65390Sbostic uchar *record; 42*65390Sbostic uchar *fields; 43*65390Sbostic Cell *fldtab; 44*65390Sbostic 45*65390Sbostic #define MAXFLD 200 46*65390Sbostic int nfields = MAXFLD; /* can be set from commandline in main */ 47*65390Sbostic 48*65390Sbostic int donefld; /* 1 = implies rec broken into fields */ 49*65390Sbostic int donerec; /* 1 = record is valid (no flds have changed) */ 50*65390Sbostic 51*65390Sbostic int maxfld = 0; /* last used field */ 52*65390Sbostic int argno = 1; /* current input argument number */ 53*65390Sbostic extern Awkfloat *ARGC; 54*65390Sbostic 55*65390Sbostic void recinit(unsigned int n) 56*65390Sbostic { 57*65390Sbostic static Cell dollar0 = { 58*65390Sbostic OCELL, CFLD, (uchar*) "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE }; 59*65390Sbostic static Cell dollar1 = { 60*65390Sbostic OCELL, CFLD, NULL, (uchar*) "", 0.0, FLD|STR|DONTFREE }; 61*65390Sbostic int i; 62*65390Sbostic 63*65390Sbostic record = recdata = (uchar *) malloc(n); 64*65390Sbostic fields = (uchar *) malloc(n); 65*65390Sbostic fldtab = (Cell *) malloc(nfields * sizeof(Cell)); 66*65390Sbostic if (recdata == NULL || fields == NULL || fldtab == NULL) 67*65390Sbostic ERROR "out of space for $0 and fields" FATAL; 68*65390Sbostic fldtab[0] = dollar0; 69*65390Sbostic fldtab[0].sval = recdata; 70*65390Sbostic for (i = 1; i < nfields; i++) 71*65390Sbostic fldtab[i] = dollar1; 72*65390Sbostic } 73*65390Sbostic 74*65390Sbostic void initgetrec(void) 75*65390Sbostic { 76*65390Sbostic int i; 77*65390Sbostic uchar *p; 78*65390Sbostic 79*65390Sbostic for (i = 1; i < *ARGC; i++) { 80*65390Sbostic if (!isclvar(p = getargv(i))) { /* find 1st real filename */ 81*65390Sbostic setsval(lookup("FILENAME", symtab), getargv(i)); 82*65390Sbostic return; 83*65390Sbostic } 84*65390Sbostic setclvar(p); /* a commandline assignment before filename */ 85*65390Sbostic argno++; 86*65390Sbostic } 87*65390Sbostic infile = stdin; /* no filenames, so use stdin */ 88*65390Sbostic } 89*65390Sbostic 90*65390Sbostic getrec(uchar *buf) /* get next input record from whatever source */ 91*65390Sbostic { /* note: tests whether buf == record */ 92*65390Sbostic int c; 93*65390Sbostic static int firsttime = 1; 94*65390Sbostic 95*65390Sbostic if (firsttime) { 96*65390Sbostic firsttime = 0; 97*65390Sbostic initgetrec(); 98*65390Sbostic } 99*65390Sbostic dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", 100*65390Sbostic *RS, *FS, *ARGC, *FILENAME) ); 101*65390Sbostic donefld = 0; 102*65390Sbostic donerec = 1; 103*65390Sbostic buf[0] = 0; 104*65390Sbostic while (argno < *ARGC || infile == stdin) { 105*65390Sbostic dprintf( ("argno=%d, file=|%s|\n", argno, file) ); 106*65390Sbostic if (infile == NULL) { /* have to open a new file */ 107*65390Sbostic file = getargv(argno); 108*65390Sbostic if (*file == '\0') { /* it's been zapped */ 109*65390Sbostic argno++; 110*65390Sbostic continue; 111*65390Sbostic } 112*65390Sbostic if (isclvar(file)) { /* a var=value arg */ 113*65390Sbostic setclvar(file); 114*65390Sbostic argno++; 115*65390Sbostic continue; 116*65390Sbostic } 117*65390Sbostic *FILENAME = file; 118*65390Sbostic dprintf( ("opening file %s\n", file) ); 119*65390Sbostic if (*file == '-' && *(file+1) == '\0') 120*65390Sbostic infile = stdin; 121*65390Sbostic else if ((infile = fopen((char *)file, "r")) == NULL) 122*65390Sbostic ERROR "can't open file %s", file FATAL; 123*65390Sbostic setfval(fnrloc, 0.0); 124*65390Sbostic } 125*65390Sbostic c = readrec(buf, recsize, infile); 126*65390Sbostic if (c != 0 || buf[0] != '\0') { /* normal record */ 127*65390Sbostic if (buf == record) { 128*65390Sbostic if (!(recloc->tval & DONTFREE)) 129*65390Sbostic xfree(recloc->sval); 130*65390Sbostic recloc->sval = record; 131*65390Sbostic recloc->tval = REC | STR | DONTFREE; 132*65390Sbostic if (isnumber(recloc->sval)) { 133*65390Sbostic recloc->fval = atof(recloc->sval); 134*65390Sbostic recloc->tval |= NUM; 135*65390Sbostic } 136*65390Sbostic } 137*65390Sbostic setfval(nrloc, nrloc->fval+1); 138*65390Sbostic setfval(fnrloc, fnrloc->fval+1); 139*65390Sbostic return 1; 140*65390Sbostic } 141*65390Sbostic /* EOF arrived on this file; set up next */ 142*65390Sbostic if (infile != stdin) 143*65390Sbostic fclose(infile); 144*65390Sbostic infile = NULL; 145*65390Sbostic argno++; 146*65390Sbostic } 147*65390Sbostic return 0; /* true end of file */ 148*65390Sbostic } 149*65390Sbostic 150*65390Sbostic readrec(uchar *buf, int bufsize, FILE *inf) /* read one record into buf */ 151*65390Sbostic { 152*65390Sbostic register int sep, c; 153*65390Sbostic register uchar *rr; 154*65390Sbostic register int nrr; 155*65390Sbostic 156*65390Sbostic if ((sep = **RS) == 0) { 157*65390Sbostic sep = '\n'; 158*65390Sbostic while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */ 159*65390Sbostic ; 160*65390Sbostic if (c != EOF) 161*65390Sbostic ungetc(c, inf); 162*65390Sbostic } 163*65390Sbostic for (rr = buf, nrr = bufsize; ; ) { 164*65390Sbostic for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c) 165*65390Sbostic if (--nrr < 0) 166*65390Sbostic ERROR "input record `%.30s...' too long; try -mr n", buf FATAL; 167*65390Sbostic if (**RS == sep || c == EOF) 168*65390Sbostic break; 169*65390Sbostic if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ 170*65390Sbostic break; 171*65390Sbostic *rr++ = '\n'; 172*65390Sbostic *rr++ = c; 173*65390Sbostic } 174*65390Sbostic if (rr > buf + bufsize) 175*65390Sbostic ERROR "input record `%.30s...' too long; try -mr n", buf FATAL; 176*65390Sbostic *rr = 0; 177*65390Sbostic dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) ); 178*65390Sbostic return c == EOF && rr == buf ? 0 : 1; 179*65390Sbostic } 180*65390Sbostic 181*65390Sbostic uchar *getargv(int n) /* get ARGV[n] */ 182*65390Sbostic { 183*65390Sbostic Cell *x; 184*65390Sbostic uchar *s, temp[10]; 185*65390Sbostic extern Array *ARGVtab; 186*65390Sbostic 187*65390Sbostic sprintf((char *)temp, "%d", n); 188*65390Sbostic x = setsymtab(temp, "", 0.0, STR, ARGVtab); 189*65390Sbostic s = getsval(x); 190*65390Sbostic dprintf( ("getargv(%d) returns |%s|\n", n, s) ); 191*65390Sbostic return s; 192*65390Sbostic } 193*65390Sbostic 194*65390Sbostic void setclvar(uchar *s) /* set var=value from s */ 195*65390Sbostic { 196*65390Sbostic uchar *p; 197*65390Sbostic Cell *q; 198*65390Sbostic 199*65390Sbostic for (p=s; *p != '='; p++) 200*65390Sbostic ; 201*65390Sbostic *p++ = 0; 202*65390Sbostic p = qstring(p, '\0'); 203*65390Sbostic q = setsymtab(s, p, 0.0, STR, symtab); 204*65390Sbostic setsval(q, p); 205*65390Sbostic if (isnumber(q->sval)) { 206*65390Sbostic q->fval = atof(q->sval); 207*65390Sbostic q->tval |= NUM; 208*65390Sbostic } 209*65390Sbostic dprintf( ("command line set %s to |%s|\n", s, p) ); 210*65390Sbostic } 211*65390Sbostic 212*65390Sbostic 213*65390Sbostic void fldbld(void) /* create fields from current record */ 214*65390Sbostic { 215*65390Sbostic register uchar *r, *fr, sep; 216*65390Sbostic Cell *p; 217*65390Sbostic int i; 218*65390Sbostic 219*65390Sbostic if (donefld) 220*65390Sbostic return; 221*65390Sbostic if (!(recloc->tval & STR)) 222*65390Sbostic getsval(recloc); 223*65390Sbostic r = recloc->sval; 224*65390Sbostic fr = fields; 225*65390Sbostic i = 0; /* number of fields accumulated here */ 226*65390Sbostic if (strlen(*FS) > 1) { /* it's a regular expression */ 227*65390Sbostic i = refldbld(r, *FS); 228*65390Sbostic } else if ((sep = **FS) == ' ') { /* default whitespace */ 229*65390Sbostic for (i = 0; ; ) { 230*65390Sbostic while (*r == ' ' || *r == '\t' || *r == '\n') 231*65390Sbostic r++; 232*65390Sbostic if (*r == 0) 233*65390Sbostic break; 234*65390Sbostic i++; 235*65390Sbostic if (i >= nfields) 236*65390Sbostic break; 237*65390Sbostic if (!(fldtab[i].tval & DONTFREE)) 238*65390Sbostic xfree(fldtab[i].sval); 239*65390Sbostic fldtab[i].sval = fr; 240*65390Sbostic fldtab[i].tval = FLD | STR | DONTFREE; 241*65390Sbostic do 242*65390Sbostic *fr++ = *r++; 243*65390Sbostic while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); 244*65390Sbostic *fr++ = 0; 245*65390Sbostic } 246*65390Sbostic *fr = 0; 247*65390Sbostic } else if (*r != 0) { /* if 0, it's a null field */ 248*65390Sbostic for (;;) { 249*65390Sbostic i++; 250*65390Sbostic if (i >= nfields) 251*65390Sbostic break; 252*65390Sbostic if (!(fldtab[i].tval & DONTFREE)) 253*65390Sbostic xfree(fldtab[i].sval); 254*65390Sbostic fldtab[i].sval = fr; 255*65390Sbostic fldtab[i].tval = FLD | STR | DONTFREE; 256*65390Sbostic while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */ 257*65390Sbostic *fr++ = *r++; 258*65390Sbostic *fr++ = 0; 259*65390Sbostic if (*r++ == 0) 260*65390Sbostic break; 261*65390Sbostic } 262*65390Sbostic *fr = 0; 263*65390Sbostic } 264*65390Sbostic if (i >= nfields) 265*65390Sbostic ERROR "record `%.30s...' has too many fields; try -mf n", record FATAL; 266*65390Sbostic /* clean out junk from previous record */ 267*65390Sbostic cleanfld(i, maxfld); 268*65390Sbostic maxfld = i; 269*65390Sbostic donefld = 1; 270*65390Sbostic for (p = fldtab+1; p <= fldtab+maxfld; p++) { 271*65390Sbostic if(isnumber(p->sval)) { 272*65390Sbostic p->fval = atof(p->sval); 273*65390Sbostic p->tval |= NUM; 274*65390Sbostic } 275*65390Sbostic } 276*65390Sbostic setfval(nfloc, (Awkfloat) maxfld); 277*65390Sbostic if (dbg) 278*65390Sbostic for (p = fldtab; p <= fldtab+maxfld; p++) 279*65390Sbostic printf("field %d: |%s|\n", p-fldtab, p->sval); 280*65390Sbostic } 281*65390Sbostic 282*65390Sbostic void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */ 283*65390Sbostic { 284*65390Sbostic static uchar *nullstat = (uchar *) ""; 285*65390Sbostic register Cell *p, *q; 286*65390Sbostic 287*65390Sbostic for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) { 288*65390Sbostic if (!(p->tval & DONTFREE)) 289*65390Sbostic xfree(p->sval); 290*65390Sbostic p->tval = FLD | STR | DONTFREE; 291*65390Sbostic p->sval = nullstat; 292*65390Sbostic } 293*65390Sbostic } 294*65390Sbostic 295*65390Sbostic void newfld(int n) /* add field n (after end) */ 296*65390Sbostic { 297*65390Sbostic if (n >= nfields) 298*65390Sbostic ERROR "creating too many fields (%d); try -mf n", n, record FATAL; 299*65390Sbostic cleanfld(maxfld, n); 300*65390Sbostic maxfld = n; 301*65390Sbostic setfval(nfloc, (Awkfloat) n); 302*65390Sbostic } 303*65390Sbostic 304*65390Sbostic refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */ 305*65390Sbostic { 306*65390Sbostic uchar *fr; 307*65390Sbostic int i, tempstat; 308*65390Sbostic fa *pfa; 309*65390Sbostic 310*65390Sbostic fr = fields; 311*65390Sbostic *fr = '\0'; 312*65390Sbostic if (*rec == '\0') 313*65390Sbostic return 0; 314*65390Sbostic pfa = makedfa(fs, 1); 315*65390Sbostic dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) ); 316*65390Sbostic tempstat = pfa->initstat; 317*65390Sbostic for (i = 1; i < nfields; i++) { 318*65390Sbostic if (!(fldtab[i].tval & DONTFREE)) 319*65390Sbostic xfree(fldtab[i].sval); 320*65390Sbostic fldtab[i].tval = FLD | STR | DONTFREE; 321*65390Sbostic fldtab[i].sval = fr; 322*65390Sbostic dprintf( ("refldbld: i=%d\n", i) ); 323*65390Sbostic if (nematch(pfa, rec)) { 324*65390Sbostic pfa->initstat = 2; /* horrible coupling */ 325*65390Sbostic dprintf( ("match %s (%d chars)\n", patbeg, patlen) ); 326*65390Sbostic strncpy(fr, rec, patbeg-rec); 327*65390Sbostic fr += patbeg - rec + 1; 328*65390Sbostic *(fr-1) = '\0'; 329*65390Sbostic rec = patbeg + patlen; 330*65390Sbostic } else { 331*65390Sbostic dprintf( ("no match %s\n", rec) ); 332*65390Sbostic strcpy(fr, rec); 333*65390Sbostic pfa->initstat = tempstat; 334*65390Sbostic break; 335*65390Sbostic } 336*65390Sbostic } 337*65390Sbostic return i; 338*65390Sbostic } 339*65390Sbostic 340*65390Sbostic void recbld(void) /* create $0 from $1..$NF if necessary */ 341*65390Sbostic { 342*65390Sbostic register int i; 343*65390Sbostic register uchar *r, *p; 344*65390Sbostic static uchar *rec = 0; 345*65390Sbostic 346*65390Sbostic if (donerec == 1) 347*65390Sbostic return; 348*65390Sbostic if (rec == 0) { 349*65390Sbostic rec = (uchar *) malloc(recsize); 350*65390Sbostic if (rec == 0) 351*65390Sbostic ERROR "out of space building $0, record size %d", recsize FATAL; 352*65390Sbostic } 353*65390Sbostic r = rec; 354*65390Sbostic for (i = 1; i <= *NF; i++) { 355*65390Sbostic p = getsval(&fldtab[i]); 356*65390Sbostic while (r < rec+recsize-1 && (*r = *p++)) 357*65390Sbostic r++; 358*65390Sbostic if (i < *NF) 359*65390Sbostic for (p = *OFS; r < rec+recsize-1 && (*r = *p++); ) 360*65390Sbostic r++; 361*65390Sbostic } 362*65390Sbostic if (r > rec + recsize - 1) 363*65390Sbostic ERROR "built giant record `%.30s...'; try -mr n", record FATAL; 364*65390Sbostic *r = '\0'; 365*65390Sbostic dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) ); 366*65390Sbostic recloc->tval = REC | STR | DONTFREE; 367*65390Sbostic recloc->sval = record = rec; 368*65390Sbostic dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) ); 369*65390Sbostic dprintf( ("recbld = |%s|\n", record) ); 370*65390Sbostic donerec = 1; 371*65390Sbostic } 372*65390Sbostic 373*65390Sbostic Cell *fieldadr(int n) 374*65390Sbostic { 375*65390Sbostic if (n < 0 || n >= nfields) 376*65390Sbostic ERROR "trying to access field %d; try -mf n", n FATAL; 377*65390Sbostic return(&fldtab[n]); 378*65390Sbostic } 379*65390Sbostic 380*65390Sbostic int errorflag = 0; 381*65390Sbostic char errbuf[200]; 382*65390Sbostic 383*65390Sbostic void yyerror(uchar *s) 384*65390Sbostic { 385*65390Sbostic extern uchar *cmdname, *curfname; 386*65390Sbostic static int been_here = 0; 387*65390Sbostic 388*65390Sbostic if (been_here++ > 2) 389*65390Sbostic return; 390*65390Sbostic fprintf(stderr, "%s: %s", cmdname, s); 391*65390Sbostic fprintf(stderr, " at source line %d", lineno); 392*65390Sbostic if (curfname != NULL) 393*65390Sbostic fprintf(stderr, " in function %s", curfname); 394*65390Sbostic fprintf(stderr, "\n"); 395*65390Sbostic errorflag = 2; 396*65390Sbostic eprint(); 397*65390Sbostic } 398*65390Sbostic 399*65390Sbostic void fpecatch(int n) 400*65390Sbostic { 401*65390Sbostic ERROR "floating point exception %d", n FATAL; 402*65390Sbostic } 403*65390Sbostic 404*65390Sbostic extern int bracecnt, brackcnt, parencnt; 405*65390Sbostic 406*65390Sbostic void bracecheck(void) 407*65390Sbostic { 408*65390Sbostic int c; 409*65390Sbostic static int beenhere = 0; 410*65390Sbostic 411*65390Sbostic if (beenhere++) 412*65390Sbostic return; 413*65390Sbostic while ((c = input()) != EOF && c != '\0') 414*65390Sbostic bclass(c); 415*65390Sbostic bcheck2(bracecnt, '{', '}'); 416*65390Sbostic bcheck2(brackcnt, '[', ']'); 417*65390Sbostic bcheck2(parencnt, '(', ')'); 418*65390Sbostic } 419*65390Sbostic 420*65390Sbostic void bcheck2(int n, int c1, int c2) 421*65390Sbostic { 422*65390Sbostic if (n == 1) 423*65390Sbostic fprintf(stderr, "\tmissing %c\n", c2); 424*65390Sbostic else if (n > 1) 425*65390Sbostic fprintf(stderr, "\t%d missing %c's\n", n, c2); 426*65390Sbostic else if (n == -1) 427*65390Sbostic fprintf(stderr, "\textra %c\n", c2); 428*65390Sbostic else if (n < -1) 429*65390Sbostic fprintf(stderr, "\t%d extra %c's\n", -n, c2); 430*65390Sbostic } 431*65390Sbostic 432*65390Sbostic void error(int f, char *s) 433*65390Sbostic { 434*65390Sbostic extern Node *curnode; 435*65390Sbostic extern uchar *cmdname; 436*65390Sbostic 437*65390Sbostic fflush(stdout); 438*65390Sbostic fprintf(stderr, "%s: ", cmdname); 439*65390Sbostic fprintf(stderr, "%s", s); 440*65390Sbostic fprintf(stderr, "\n"); 441*65390Sbostic if (compile_time != 2 && NR && *NR > 0) { 442*65390Sbostic fprintf(stderr, " input record number %g", *FNR); 443*65390Sbostic if (strcmp(*FILENAME, "-") != 0) 444*65390Sbostic fprintf(stderr, ", file %s", *FILENAME); 445*65390Sbostic fprintf(stderr, "\n"); 446*65390Sbostic } 447*65390Sbostic if (compile_time != 2 && curnode) 448*65390Sbostic fprintf(stderr, " source line number %d\n", curnode->lineno); 449*65390Sbostic else if (compile_time != 2 && lineno) 450*65390Sbostic fprintf(stderr, " source line number %d\n", lineno); 451*65390Sbostic eprint(); 452*65390Sbostic if (f) { 453*65390Sbostic if (dbg > 1) /* core dump if serious debugging on */ 454*65390Sbostic abort(); 455*65390Sbostic exit(2); 456*65390Sbostic } 457*65390Sbostic } 458*65390Sbostic 459*65390Sbostic void eprint(void) /* try to print context around error */ 460*65390Sbostic { 461*65390Sbostic uchar *p, *q; 462*65390Sbostic int c; 463*65390Sbostic static int been_here = 0; 464*65390Sbostic extern uchar ebuf[], *ep; 465*65390Sbostic 466*65390Sbostic if (compile_time == 2 || compile_time == 0 || been_here++ > 0) 467*65390Sbostic return; 468*65390Sbostic p = ep - 1; 469*65390Sbostic if (p > ebuf && *p == '\n') 470*65390Sbostic p--; 471*65390Sbostic for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--) 472*65390Sbostic ; 473*65390Sbostic while (*p == '\n') 474*65390Sbostic p++; 475*65390Sbostic fprintf(stderr, " context is\n\t"); 476*65390Sbostic for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) 477*65390Sbostic ; 478*65390Sbostic for ( ; p < q; p++) 479*65390Sbostic if (*p) 480*65390Sbostic putc(*p, stderr); 481*65390Sbostic fprintf(stderr, " >>> "); 482*65390Sbostic for ( ; p < ep; p++) 483*65390Sbostic if (*p) 484*65390Sbostic putc(*p, stderr); 485*65390Sbostic fprintf(stderr, " <<< "); 486*65390Sbostic if (*ep) 487*65390Sbostic while ((c = input()) != '\n' && c != '\0' && c != EOF) { 488*65390Sbostic putc(c, stderr); 489*65390Sbostic bclass(c); 490*65390Sbostic } 491*65390Sbostic putc('\n', stderr); 492*65390Sbostic ep = ebuf; 493*65390Sbostic } 494*65390Sbostic 495*65390Sbostic void bclass(int c) 496*65390Sbostic { 497*65390Sbostic switch (c) { 498*65390Sbostic case '{': bracecnt++; break; 499*65390Sbostic case '}': bracecnt--; break; 500*65390Sbostic case '[': brackcnt++; break; 501*65390Sbostic case ']': brackcnt--; break; 502*65390Sbostic case '(': parencnt++; break; 503*65390Sbostic case ')': parencnt--; break; 504*65390Sbostic } 505*65390Sbostic } 506*65390Sbostic 507*65390Sbostic double errcheck(double x, uchar *s) 508*65390Sbostic { 509*65390Sbostic extern int errno; 510*65390Sbostic 511*65390Sbostic if (errno == EDOM) { 512*65390Sbostic errno = 0; 513*65390Sbostic ERROR "%s argument out of domain", s WARNING; 514*65390Sbostic x = 1; 515*65390Sbostic } else if (errno == ERANGE) { 516*65390Sbostic errno = 0; 517*65390Sbostic ERROR "%s result out of range", s WARNING; 518*65390Sbostic x = 1; 519*65390Sbostic } 520*65390Sbostic return x; 521*65390Sbostic } 522*65390Sbostic 523*65390Sbostic isclvar(uchar *s) /* is s of form var=something ? */ 524*65390Sbostic { 525*65390Sbostic uchar *os = s; 526*65390Sbostic 527*65390Sbostic if (!isalpha(*s) && *s != '_') 528*65390Sbostic return 0; 529*65390Sbostic for ( ; *s; s++) 530*65390Sbostic if (!(isalnum(*s) || *s == '_')) 531*65390Sbostic break; 532*65390Sbostic return *s == '=' && s > os && *(s+1) != '='; 533*65390Sbostic } 534*65390Sbostic 535*65390Sbostic #define MAXEXPON 38 /* maximum exponent for fp number. should be IEEE */ 536*65390Sbostic 537*65390Sbostic isnumber(uchar *s) /* probably should be done by a library function */ 538*65390Sbostic { 539*65390Sbostic register int d1, d2; 540*65390Sbostic int point; 541*65390Sbostic uchar *es; 542*65390Sbostic 543*65390Sbostic d1 = d2 = point = 0; 544*65390Sbostic while (*s == ' ' || *s == '\t' || *s == '\n') 545*65390Sbostic s++; 546*65390Sbostic if (*s == '\0') 547*65390Sbostic return(0); /* empty stuff isn't number */ 548*65390Sbostic if (*s == '+' || *s == '-') 549*65390Sbostic s++; 550*65390Sbostic if (!isdigit(*s) && *s != '.') 551*65390Sbostic return(0); 552*65390Sbostic if (isdigit(*s)) { 553*65390Sbostic do { 554*65390Sbostic d1++; 555*65390Sbostic s++; 556*65390Sbostic } while (isdigit(*s)); 557*65390Sbostic } 558*65390Sbostic if (*s == '.') { 559*65390Sbostic point++; 560*65390Sbostic s++; 561*65390Sbostic } 562*65390Sbostic if (isdigit(*s)) { 563*65390Sbostic d2++; 564*65390Sbostic do { 565*65390Sbostic s++; 566*65390Sbostic } while (isdigit(*s)); 567*65390Sbostic } 568*65390Sbostic if (!(d1 || point && d2)) 569*65390Sbostic return(0); 570*65390Sbostic if (*s == 'e' || *s == 'E') { 571*65390Sbostic s++; 572*65390Sbostic if (*s == '+' || *s == '-') 573*65390Sbostic s++; 574*65390Sbostic if (!isdigit(*s)) 575*65390Sbostic return(0); 576*65390Sbostic es = s; 577*65390Sbostic do { 578*65390Sbostic s++; 579*65390Sbostic } while (isdigit(*s)); 580*65390Sbostic if (s - es > 2) 581*65390Sbostic return(0); 582*65390Sbostic else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) 583*65390Sbostic return(0); 584*65390Sbostic } 585*65390Sbostic while (*s == ' ' || *s == '\t' || *s == '\n') 586*65390Sbostic s++; 587*65390Sbostic if (*s == '\0') 588*65390Sbostic return(1); 589*65390Sbostic else 590*65390Sbostic return(0); 591*65390Sbostic } 592