13e12c5d1SDavid du Colombier /* 23e12c5d1SDavid du Colombier Copyright (c) 1989 AT&T 33e12c5d1SDavid du Colombier All Rights Reserved 43e12c5d1SDavid du Colombier 53e12c5d1SDavid du Colombier THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. 63e12c5d1SDavid du Colombier 73e12c5d1SDavid du Colombier The copyright notice above does not evidence any 83e12c5d1SDavid du Colombier actual or intended publication of such source code. 93e12c5d1SDavid du Colombier */ 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier #define DEBUG 123e12c5d1SDavid du Colombier #include <stdio.h> 133e12c5d1SDavid du Colombier #include <string.h> 143e12c5d1SDavid du Colombier #include <ctype.h> 153e12c5d1SDavid du Colombier #include <errno.h> 163e12c5d1SDavid du Colombier #include <stdlib.h> 173e12c5d1SDavid du Colombier #include "awk.h" 183e12c5d1SDavid du Colombier #include "y.tab.h" 193e12c5d1SDavid du Colombier 203e12c5d1SDavid du Colombier #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p)) 213e12c5d1SDavid du Colombier #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p)) 223e12c5d1SDavid du Colombier 233e12c5d1SDavid du Colombier FILE *infile = NULL; 243e12c5d1SDavid du Colombier uchar *file = (uchar*) ""; 25*219b2ee8SDavid du Colombier int recsize = RECSIZE; 26*219b2ee8SDavid du Colombier uchar *recdata; 27*219b2ee8SDavid du Colombier uchar *record; 28*219b2ee8SDavid du Colombier uchar *fields; 29*219b2ee8SDavid du Colombier Cell *fldtab; 303e12c5d1SDavid du Colombier 313e12c5d1SDavid du Colombier #define MAXFLD 200 32*219b2ee8SDavid du Colombier int nfields = MAXFLD; /* can be set from commandline in main */ 33*219b2ee8SDavid du Colombier 343e12c5d1SDavid du Colombier int donefld; /* 1 = implies rec broken into fields */ 353e12c5d1SDavid du Colombier int donerec; /* 1 = record is valid (no flds have changed) */ 363e12c5d1SDavid du Colombier 373e12c5d1SDavid du Colombier int maxfld = 0; /* last used field */ 383e12c5d1SDavid du Colombier int argno = 1; /* current input argument number */ 393e12c5d1SDavid du Colombier extern Awkfloat *ARGC; 403e12c5d1SDavid du Colombier 41*219b2ee8SDavid du Colombier void recinit(unsigned int n) 42*219b2ee8SDavid du Colombier { 43*219b2ee8SDavid du Colombier static Cell dollar0 = { 44*219b2ee8SDavid du Colombier OCELL, CFLD, (uchar*) "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE }; 45*219b2ee8SDavid du Colombier static Cell dollar1 = { 46*219b2ee8SDavid du Colombier OCELL, CFLD, NULL, (uchar*) "", 0.0, FLD|STR|DONTFREE }; 47*219b2ee8SDavid du Colombier int i; 48*219b2ee8SDavid du Colombier 49*219b2ee8SDavid du Colombier record = recdata = (uchar *) malloc(n); 50*219b2ee8SDavid du Colombier fields = (uchar *) malloc(n); 51*219b2ee8SDavid du Colombier fldtab = (Cell *) malloc(nfields * sizeof(Cell)); 52*219b2ee8SDavid du Colombier if (recdata == NULL || fields == NULL || fldtab == NULL) 53*219b2ee8SDavid du Colombier ERROR "out of space for $0 and fields" FATAL; 54*219b2ee8SDavid du Colombier fldtab[0] = dollar0; 55*219b2ee8SDavid du Colombier fldtab[0].sval = recdata; 56*219b2ee8SDavid du Colombier for (i = 1; i < nfields; i++) 57*219b2ee8SDavid du Colombier fldtab[i] = dollar1; 58*219b2ee8SDavid du Colombier } 59*219b2ee8SDavid du Colombier 603e12c5d1SDavid du Colombier void initgetrec(void) 613e12c5d1SDavid du Colombier { 623e12c5d1SDavid du Colombier int i; 633e12c5d1SDavid du Colombier uchar *p; 643e12c5d1SDavid du Colombier 653e12c5d1SDavid du Colombier for (i = 1; i < *ARGC; i++) { 66*219b2ee8SDavid du Colombier if (!isclvar(p = getargv(i))) { /* find 1st real filename */ 67*219b2ee8SDavid du Colombier setsval(lookup("FILENAME", symtab), getargv(i)); 683e12c5d1SDavid du Colombier return; 69*219b2ee8SDavid du Colombier } 703e12c5d1SDavid du Colombier setclvar(p); /* a commandline assignment before filename */ 713e12c5d1SDavid du Colombier argno++; 723e12c5d1SDavid du Colombier } 733e12c5d1SDavid du Colombier infile = stdin; /* no filenames, so use stdin */ 743e12c5d1SDavid du Colombier } 753e12c5d1SDavid du Colombier 76*219b2ee8SDavid du Colombier getrec(uchar *buf) /* get next input record from whatever source */ 77*219b2ee8SDavid du Colombier { /* note: tests whether buf == record */ 783e12c5d1SDavid du Colombier int c; 793e12c5d1SDavid du Colombier static int firsttime = 1; 803e12c5d1SDavid du Colombier 813e12c5d1SDavid du Colombier if (firsttime) { 823e12c5d1SDavid du Colombier firsttime = 0; 833e12c5d1SDavid du Colombier initgetrec(); 843e12c5d1SDavid du Colombier } 853e12c5d1SDavid du Colombier dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", 863e12c5d1SDavid du Colombier *RS, *FS, *ARGC, *FILENAME) ); 873e12c5d1SDavid du Colombier donefld = 0; 883e12c5d1SDavid du Colombier donerec = 1; 893e12c5d1SDavid du Colombier buf[0] = 0; 903e12c5d1SDavid du Colombier while (argno < *ARGC || infile == stdin) { 913e12c5d1SDavid du Colombier dprintf( ("argno=%d, file=|%s|\n", argno, file) ); 923e12c5d1SDavid du Colombier if (infile == NULL) { /* have to open a new file */ 933e12c5d1SDavid du Colombier file = getargv(argno); 943e12c5d1SDavid du Colombier if (*file == '\0') { /* it's been zapped */ 953e12c5d1SDavid du Colombier argno++; 963e12c5d1SDavid du Colombier continue; 973e12c5d1SDavid du Colombier } 983e12c5d1SDavid du Colombier if (isclvar(file)) { /* a var=value arg */ 993e12c5d1SDavid du Colombier setclvar(file); 1003e12c5d1SDavid du Colombier argno++; 1013e12c5d1SDavid du Colombier continue; 1023e12c5d1SDavid du Colombier } 1033e12c5d1SDavid du Colombier *FILENAME = file; 1043e12c5d1SDavid du Colombier dprintf( ("opening file %s\n", file) ); 1053e12c5d1SDavid du Colombier if (*file == '-' && *(file+1) == '\0') 1063e12c5d1SDavid du Colombier infile = stdin; 1073e12c5d1SDavid du Colombier else if ((infile = fopen((char *)file, "r")) == NULL) 1083e12c5d1SDavid du Colombier ERROR "can't open file %s", file FATAL; 1093e12c5d1SDavid du Colombier setfval(fnrloc, 0.0); 1103e12c5d1SDavid du Colombier } 111*219b2ee8SDavid du Colombier c = readrec(buf, recsize, infile); 1123e12c5d1SDavid du Colombier if (c != 0 || buf[0] != '\0') { /* normal record */ 1133e12c5d1SDavid du Colombier if (buf == record) { 1143e12c5d1SDavid du Colombier if (!(recloc->tval & DONTFREE)) 1153e12c5d1SDavid du Colombier xfree(recloc->sval); 1163e12c5d1SDavid du Colombier recloc->sval = record; 1173e12c5d1SDavid du Colombier recloc->tval = REC | STR | DONTFREE; 1183e12c5d1SDavid du Colombier if (isnumber(recloc->sval)) { 1193e12c5d1SDavid du Colombier recloc->fval = atof(recloc->sval); 1203e12c5d1SDavid du Colombier recloc->tval |= NUM; 1213e12c5d1SDavid du Colombier } 1223e12c5d1SDavid du Colombier } 1233e12c5d1SDavid du Colombier setfval(nrloc, nrloc->fval+1); 1243e12c5d1SDavid du Colombier setfval(fnrloc, fnrloc->fval+1); 1253e12c5d1SDavid du Colombier return 1; 1263e12c5d1SDavid du Colombier } 1273e12c5d1SDavid du Colombier /* EOF arrived on this file; set up next */ 1283e12c5d1SDavid du Colombier if (infile != stdin) 1293e12c5d1SDavid du Colombier fclose(infile); 1303e12c5d1SDavid du Colombier infile = NULL; 1313e12c5d1SDavid du Colombier argno++; 1323e12c5d1SDavid du Colombier } 1333e12c5d1SDavid du Colombier return 0; /* true end of file */ 1343e12c5d1SDavid du Colombier } 1353e12c5d1SDavid du Colombier 1363e12c5d1SDavid du Colombier readrec(uchar *buf, int bufsize, FILE *inf) /* read one record into buf */ 1373e12c5d1SDavid du Colombier { 1383e12c5d1SDavid du Colombier register int sep, c; 1393e12c5d1SDavid du Colombier register uchar *rr; 1403e12c5d1SDavid du Colombier register int nrr; 1413e12c5d1SDavid du Colombier 1423e12c5d1SDavid du Colombier if ((sep = **RS) == 0) { 1433e12c5d1SDavid du Colombier sep = '\n'; 1443e12c5d1SDavid du Colombier while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */ 1453e12c5d1SDavid du Colombier ; 1463e12c5d1SDavid du Colombier if (c != EOF) 1473e12c5d1SDavid du Colombier ungetc(c, inf); 1483e12c5d1SDavid du Colombier } 1493e12c5d1SDavid du Colombier for (rr = buf, nrr = bufsize; ; ) { 1503e12c5d1SDavid du Colombier for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c) 1513e12c5d1SDavid du Colombier if (--nrr < 0) 152*219b2ee8SDavid du Colombier ERROR "input record `%.30s...' too long; try -mr n", buf FATAL; 1533e12c5d1SDavid du Colombier if (**RS == sep || c == EOF) 1543e12c5d1SDavid du Colombier break; 1553e12c5d1SDavid du Colombier if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ 1563e12c5d1SDavid du Colombier break; 1573e12c5d1SDavid du Colombier *rr++ = '\n'; 1583e12c5d1SDavid du Colombier *rr++ = c; 1593e12c5d1SDavid du Colombier } 1603e12c5d1SDavid du Colombier if (rr > buf + bufsize) 161*219b2ee8SDavid du Colombier ERROR "input record `%.30s...' too long; try -mr n", buf FATAL; 1623e12c5d1SDavid du Colombier *rr = 0; 1633e12c5d1SDavid du Colombier dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) ); 1643e12c5d1SDavid du Colombier return c == EOF && rr == buf ? 0 : 1; 1653e12c5d1SDavid du Colombier } 1663e12c5d1SDavid du Colombier 1673e12c5d1SDavid du Colombier uchar *getargv(int n) /* get ARGV[n] */ 1683e12c5d1SDavid du Colombier { 1693e12c5d1SDavid du Colombier Cell *x; 1703e12c5d1SDavid du Colombier uchar *s, temp[10]; 1713e12c5d1SDavid du Colombier extern Array *ARGVtab; 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier sprintf((char *)temp, "%d", n); 1743e12c5d1SDavid du Colombier x = setsymtab(temp, "", 0.0, STR, ARGVtab); 1753e12c5d1SDavid du Colombier s = getsval(x); 1763e12c5d1SDavid du Colombier dprintf( ("getargv(%d) returns |%s|\n", n, s) ); 1773e12c5d1SDavid du Colombier return s; 1783e12c5d1SDavid du Colombier } 1793e12c5d1SDavid du Colombier 1803e12c5d1SDavid du Colombier void setclvar(uchar *s) /* set var=value from s */ 1813e12c5d1SDavid du Colombier { 1823e12c5d1SDavid du Colombier uchar *p; 1833e12c5d1SDavid du Colombier Cell *q; 1843e12c5d1SDavid du Colombier 1853e12c5d1SDavid du Colombier for (p=s; *p != '='; p++) 1863e12c5d1SDavid du Colombier ; 1873e12c5d1SDavid du Colombier *p++ = 0; 1883e12c5d1SDavid du Colombier p = qstring(p, '\0'); 1893e12c5d1SDavid du Colombier q = setsymtab(s, p, 0.0, STR, symtab); 1903e12c5d1SDavid du Colombier setsval(q, p); 1913e12c5d1SDavid du Colombier if (isnumber(q->sval)) { 1923e12c5d1SDavid du Colombier q->fval = atof(q->sval); 1933e12c5d1SDavid du Colombier q->tval |= NUM; 1943e12c5d1SDavid du Colombier } 1953e12c5d1SDavid du Colombier dprintf( ("command line set %s to |%s|\n", s, p) ); 1963e12c5d1SDavid du Colombier } 1973e12c5d1SDavid du Colombier 1983e12c5d1SDavid du Colombier 199*219b2ee8SDavid du Colombier void fldbld(void) /* create fields from current record */ 2003e12c5d1SDavid du Colombier { 2013e12c5d1SDavid du Colombier register uchar *r, *fr, sep; 2023e12c5d1SDavid du Colombier Cell *p; 2033e12c5d1SDavid du Colombier int i; 2043e12c5d1SDavid du Colombier 2053e12c5d1SDavid du Colombier if (donefld) 2063e12c5d1SDavid du Colombier return; 2073e12c5d1SDavid du Colombier if (!(recloc->tval & STR)) 2083e12c5d1SDavid du Colombier getsval(recloc); 209*219b2ee8SDavid du Colombier r = recloc->sval; 2103e12c5d1SDavid du Colombier fr = fields; 2113e12c5d1SDavid du Colombier i = 0; /* number of fields accumulated here */ 2123e12c5d1SDavid du Colombier if (strlen(*FS) > 1) { /* it's a regular expression */ 2133e12c5d1SDavid du Colombier i = refldbld(r, *FS); 214*219b2ee8SDavid du Colombier } else if ((sep = **FS) == ' ') { /* default whitespace */ 2153e12c5d1SDavid du Colombier for (i = 0; ; ) { 2163e12c5d1SDavid du Colombier while (*r == ' ' || *r == '\t' || *r == '\n') 2173e12c5d1SDavid du Colombier r++; 2183e12c5d1SDavid du Colombier if (*r == 0) 2193e12c5d1SDavid du Colombier break; 2203e12c5d1SDavid du Colombier i++; 221*219b2ee8SDavid du Colombier if (i >= nfields) 2223e12c5d1SDavid du Colombier break; 2233e12c5d1SDavid du Colombier if (!(fldtab[i].tval & DONTFREE)) 2243e12c5d1SDavid du Colombier xfree(fldtab[i].sval); 2253e12c5d1SDavid du Colombier fldtab[i].sval = fr; 2263e12c5d1SDavid du Colombier fldtab[i].tval = FLD | STR | DONTFREE; 2273e12c5d1SDavid du Colombier do 2283e12c5d1SDavid du Colombier *fr++ = *r++; 2293e12c5d1SDavid du Colombier while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); 2303e12c5d1SDavid du Colombier *fr++ = 0; 2313e12c5d1SDavid du Colombier } 2323e12c5d1SDavid du Colombier *fr = 0; 2333e12c5d1SDavid du Colombier } else if (*r != 0) { /* if 0, it's a null field */ 2343e12c5d1SDavid du Colombier for (;;) { 2353e12c5d1SDavid du Colombier i++; 236*219b2ee8SDavid du Colombier if (i >= nfields) 2373e12c5d1SDavid du Colombier break; 2383e12c5d1SDavid du Colombier if (!(fldtab[i].tval & DONTFREE)) 2393e12c5d1SDavid du Colombier xfree(fldtab[i].sval); 2403e12c5d1SDavid du Colombier fldtab[i].sval = fr; 2413e12c5d1SDavid du Colombier fldtab[i].tval = FLD | STR | DONTFREE; 242*219b2ee8SDavid du Colombier while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */ 2433e12c5d1SDavid du Colombier *fr++ = *r++; 2443e12c5d1SDavid du Colombier *fr++ = 0; 2453e12c5d1SDavid du Colombier if (*r++ == 0) 2463e12c5d1SDavid du Colombier break; 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier *fr = 0; 2493e12c5d1SDavid du Colombier } 250*219b2ee8SDavid du Colombier if (i >= nfields) 251*219b2ee8SDavid du Colombier ERROR "record `%.30s...' has too many fields; try -mf n", record FATAL; 2523e12c5d1SDavid du Colombier /* clean out junk from previous record */ 2533e12c5d1SDavid du Colombier cleanfld(i, maxfld); 2543e12c5d1SDavid du Colombier maxfld = i; 2553e12c5d1SDavid du Colombier donefld = 1; 2563e12c5d1SDavid du Colombier for (p = fldtab+1; p <= fldtab+maxfld; p++) { 2573e12c5d1SDavid du Colombier if(isnumber(p->sval)) { 2583e12c5d1SDavid du Colombier p->fval = atof(p->sval); 2593e12c5d1SDavid du Colombier p->tval |= NUM; 2603e12c5d1SDavid du Colombier } 2613e12c5d1SDavid du Colombier } 2623e12c5d1SDavid du Colombier setfval(nfloc, (Awkfloat) maxfld); 2633e12c5d1SDavid du Colombier if (dbg) 2643e12c5d1SDavid du Colombier for (p = fldtab; p <= fldtab+maxfld; p++) 2653e12c5d1SDavid du Colombier printf("field %d: |%s|\n", p-fldtab, p->sval); 2663e12c5d1SDavid du Colombier } 2673e12c5d1SDavid du Colombier 2683e12c5d1SDavid du Colombier void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */ 2693e12c5d1SDavid du Colombier { 2703e12c5d1SDavid du Colombier static uchar *nullstat = (uchar *) ""; 2713e12c5d1SDavid du Colombier register Cell *p, *q; 2723e12c5d1SDavid du Colombier 2733e12c5d1SDavid du Colombier for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) { 2743e12c5d1SDavid du Colombier if (!(p->tval & DONTFREE)) 2753e12c5d1SDavid du Colombier xfree(p->sval); 2763e12c5d1SDavid du Colombier p->tval = FLD | STR | DONTFREE; 2773e12c5d1SDavid du Colombier p->sval = nullstat; 2783e12c5d1SDavid du Colombier } 2793e12c5d1SDavid du Colombier } 2803e12c5d1SDavid du Colombier 2813e12c5d1SDavid du Colombier void newfld(int n) /* add field n (after end) */ 2823e12c5d1SDavid du Colombier { 283*219b2ee8SDavid du Colombier if (n >= nfields) 284*219b2ee8SDavid du Colombier ERROR "creating too many fields (%d); try -mf n", n, record FATAL; 2853e12c5d1SDavid du Colombier cleanfld(maxfld, n); 2863e12c5d1SDavid du Colombier maxfld = n; 2873e12c5d1SDavid du Colombier setfval(nfloc, (Awkfloat) n); 2883e12c5d1SDavid du Colombier } 2893e12c5d1SDavid du Colombier 2903e12c5d1SDavid du Colombier refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */ 2913e12c5d1SDavid du Colombier { 2923e12c5d1SDavid du Colombier uchar *fr; 2933e12c5d1SDavid du Colombier void *p; 2943e12c5d1SDavid du Colombier int i; 2953e12c5d1SDavid du Colombier 2963e12c5d1SDavid du Colombier fr = fields; 2973e12c5d1SDavid du Colombier *fr = '\0'; 2983e12c5d1SDavid du Colombier if (*rec == '\0') 2993e12c5d1SDavid du Colombier return 0; 3003e12c5d1SDavid du Colombier p = compre(fs); 3013e12c5d1SDavid du Colombier dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) ); 302*219b2ee8SDavid du Colombier for (i = 1; i < nfields; i++) { 3033e12c5d1SDavid du Colombier if (!(fldtab[i].tval & DONTFREE)) 3043e12c5d1SDavid du Colombier xfree(fldtab[i].sval); 3053e12c5d1SDavid du Colombier fldtab[i].tval = FLD | STR | DONTFREE; 3063e12c5d1SDavid du Colombier fldtab[i].sval = fr; 3073e12c5d1SDavid du Colombier dprintf( ("refldbld: i=%d\n", i) ); 3083e12c5d1SDavid du Colombier if (nematch(p, rec, rec)) { 3093e12c5d1SDavid du Colombier dprintf( ("match %s (%d chars)\n", patbeg, patlen) ); 3103e12c5d1SDavid du Colombier strncpy(fr, rec, patbeg-rec); 3113e12c5d1SDavid du Colombier fr += patbeg - rec + 1; 3123e12c5d1SDavid du Colombier *(fr-1) = '\0'; 3133e12c5d1SDavid du Colombier rec = patbeg + patlen; 3143e12c5d1SDavid du Colombier } else { 3153e12c5d1SDavid du Colombier dprintf( ("no match %s\n", rec) ); 3163e12c5d1SDavid du Colombier strcpy(fr, rec); 3173e12c5d1SDavid du Colombier break; 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier } 3203e12c5d1SDavid du Colombier return i; 3213e12c5d1SDavid du Colombier } 3223e12c5d1SDavid du Colombier 323*219b2ee8SDavid du Colombier void recbld(void) /* create $0 from $1..$NF if necessary */ 3243e12c5d1SDavid du Colombier { 325*219b2ee8SDavid du Colombier register int i; 3263e12c5d1SDavid du Colombier register uchar *r, *p; 327*219b2ee8SDavid du Colombier static uchar *rec = 0; 3283e12c5d1SDavid du Colombier 3293e12c5d1SDavid du Colombier if (donerec == 1) 3303e12c5d1SDavid du Colombier return; 331*219b2ee8SDavid du Colombier if (rec == 0) { 332*219b2ee8SDavid du Colombier rec = (uchar *) malloc(recsize); 333*219b2ee8SDavid du Colombier if (rec == 0) 334*219b2ee8SDavid du Colombier ERROR "out of space building $0, record size %d", recsize FATAL; 335*219b2ee8SDavid du Colombier } 3363e12c5d1SDavid du Colombier r = rec; 3373e12c5d1SDavid du Colombier for (i = 1; i <= *NF; i++) { 3383e12c5d1SDavid du Colombier p = getsval(&fldtab[i]); 339*219b2ee8SDavid du Colombier while (r < rec+recsize-1 && (*r = *p++)) 3403e12c5d1SDavid du Colombier r++; 3413e12c5d1SDavid du Colombier if (i < *NF) 342*219b2ee8SDavid du Colombier for (p = *OFS; r < rec+recsize-1 && (*r = *p++); ) 3433e12c5d1SDavid du Colombier r++; 3443e12c5d1SDavid du Colombier } 345*219b2ee8SDavid du Colombier if (r > rec + recsize - 1) 346*219b2ee8SDavid du Colombier ERROR "built giant record `%.30s...'; try -mr n", record FATAL; 3473e12c5d1SDavid du Colombier *r = '\0'; 3483e12c5d1SDavid du Colombier dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) ); 3493e12c5d1SDavid du Colombier recloc->tval = REC | STR | DONTFREE; 3503e12c5d1SDavid du Colombier recloc->sval = record = rec; 3513e12c5d1SDavid du Colombier dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) ); 3523e12c5d1SDavid du Colombier dprintf( ("recbld = |%s|\n", record) ); 3533e12c5d1SDavid du Colombier donerec = 1; 3543e12c5d1SDavid du Colombier } 3553e12c5d1SDavid du Colombier 3563e12c5d1SDavid du Colombier Cell *fieldadr(int n) 3573e12c5d1SDavid du Colombier { 358*219b2ee8SDavid du Colombier if (n < 0 || n >= nfields) 359*219b2ee8SDavid du Colombier ERROR "trying to access field %d; try -mf n", n FATAL; 3603e12c5d1SDavid du Colombier return(&fldtab[n]); 3613e12c5d1SDavid du Colombier } 3623e12c5d1SDavid du Colombier 3633e12c5d1SDavid du Colombier int errorflag = 0; 3643e12c5d1SDavid du Colombier char errbuf[200]; 3653e12c5d1SDavid du Colombier 3663e12c5d1SDavid du Colombier void yyerror(uchar *s) 3673e12c5d1SDavid du Colombier { 3683e12c5d1SDavid du Colombier extern uchar *cmdname, *curfname; 3693e12c5d1SDavid du Colombier static int been_here = 0; 3703e12c5d1SDavid du Colombier 3713e12c5d1SDavid du Colombier if (been_here++ > 2) 3723e12c5d1SDavid du Colombier return; 3733e12c5d1SDavid du Colombier fprintf(stderr, "%s: %s", cmdname, s); 3743e12c5d1SDavid du Colombier fprintf(stderr, " at source line %d", lineno); 3753e12c5d1SDavid du Colombier if (curfname != NULL) 3763e12c5d1SDavid du Colombier fprintf(stderr, " in function %s", curfname); 3773e12c5d1SDavid du Colombier fprintf(stderr, "\n"); 3783e12c5d1SDavid du Colombier errorflag = 2; 3793e12c5d1SDavid du Colombier eprint(); 3803e12c5d1SDavid du Colombier } 3813e12c5d1SDavid du Colombier 3823e12c5d1SDavid du Colombier void fpecatch(int n) 3833e12c5d1SDavid du Colombier { 3843e12c5d1SDavid du Colombier ERROR "floating point exception %d", n FATAL; 3853e12c5d1SDavid du Colombier } 3863e12c5d1SDavid du Colombier 3873e12c5d1SDavid du Colombier extern int bracecnt, brackcnt, parencnt; 3883e12c5d1SDavid du Colombier 3893e12c5d1SDavid du Colombier void bracecheck(void) 3903e12c5d1SDavid du Colombier { 3913e12c5d1SDavid du Colombier int c; 3923e12c5d1SDavid du Colombier static int beenhere = 0; 3933e12c5d1SDavid du Colombier 3943e12c5d1SDavid du Colombier if (beenhere++) 3953e12c5d1SDavid du Colombier return; 3963e12c5d1SDavid du Colombier while ((c = input()) != EOF && c != '\0') 3973e12c5d1SDavid du Colombier bclass(c); 3983e12c5d1SDavid du Colombier bcheck2(bracecnt, '{', '}'); 3993e12c5d1SDavid du Colombier bcheck2(brackcnt, '[', ']'); 4003e12c5d1SDavid du Colombier bcheck2(parencnt, '(', ')'); 4013e12c5d1SDavid du Colombier } 4023e12c5d1SDavid du Colombier 4033e12c5d1SDavid du Colombier void bcheck2(int n, int c1, int c2) 4043e12c5d1SDavid du Colombier { 4053e12c5d1SDavid du Colombier if (n == 1) 4063e12c5d1SDavid du Colombier fprintf(stderr, "\tmissing %c\n", c2); 4073e12c5d1SDavid du Colombier else if (n > 1) 4083e12c5d1SDavid du Colombier fprintf(stderr, "\t%d missing %c's\n", n, c2); 4093e12c5d1SDavid du Colombier else if (n == -1) 4103e12c5d1SDavid du Colombier fprintf(stderr, "\textra %c\n", c2); 4113e12c5d1SDavid du Colombier else if (n < -1) 4123e12c5d1SDavid du Colombier fprintf(stderr, "\t%d extra %c's\n", -n, c2); 4133e12c5d1SDavid du Colombier } 4143e12c5d1SDavid du Colombier 4153e12c5d1SDavid du Colombier void error(int f, char *s) 4163e12c5d1SDavid du Colombier { 4173e12c5d1SDavid du Colombier extern Node *curnode; 4183e12c5d1SDavid du Colombier extern uchar *cmdname; 4193e12c5d1SDavid du Colombier 4203e12c5d1SDavid du Colombier fflush(stdout); 4213e12c5d1SDavid du Colombier fprintf(stderr, "%s: ", cmdname); 4223e12c5d1SDavid du Colombier fprintf(stderr, "%s", s); 4233e12c5d1SDavid du Colombier fprintf(stderr, "\n"); 4243e12c5d1SDavid du Colombier if (compile_time != 2 && NR && *NR > 0) { 425*219b2ee8SDavid du Colombier fprintf(stderr, " input record number %d", (int) (*FNR)); 4263e12c5d1SDavid du Colombier if (strcmp(*FILENAME, "-") != 0) 4273e12c5d1SDavid du Colombier fprintf(stderr, ", file %s", *FILENAME); 4283e12c5d1SDavid du Colombier fprintf(stderr, "\n"); 4293e12c5d1SDavid du Colombier } 4303e12c5d1SDavid du Colombier if (compile_time != 2 && curnode) 4313e12c5d1SDavid du Colombier fprintf(stderr, " source line number %d\n", curnode->lineno); 4323e12c5d1SDavid du Colombier else if (compile_time != 2 && lineno) 4333e12c5d1SDavid du Colombier fprintf(stderr, " source line number %d\n", lineno); 4343e12c5d1SDavid du Colombier eprint(); 4353e12c5d1SDavid du Colombier if (f) { 436*219b2ee8SDavid du Colombier if (dbg > 1) /* core dump if serious debugging on */ 4373e12c5d1SDavid du Colombier abort(); 4383e12c5d1SDavid du Colombier exit(2); 4393e12c5d1SDavid du Colombier } 4403e12c5d1SDavid du Colombier } 4413e12c5d1SDavid du Colombier 4423e12c5d1SDavid du Colombier void eprint(void) /* try to print context around error */ 4433e12c5d1SDavid du Colombier { 4443e12c5d1SDavid du Colombier uchar *p, *q; 4453e12c5d1SDavid du Colombier int c; 4463e12c5d1SDavid du Colombier static int been_here = 0; 447*219b2ee8SDavid du Colombier extern uchar ebuf[], *ep; 4483e12c5d1SDavid du Colombier 4493e12c5d1SDavid du Colombier if (compile_time == 2 || compile_time == 0 || been_here++ > 0) 4503e12c5d1SDavid du Colombier return; 4513e12c5d1SDavid du Colombier p = ep - 1; 4523e12c5d1SDavid du Colombier if (p > ebuf && *p == '\n') 4533e12c5d1SDavid du Colombier p--; 4543e12c5d1SDavid du Colombier for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--) 4553e12c5d1SDavid du Colombier ; 4563e12c5d1SDavid du Colombier while (*p == '\n') 4573e12c5d1SDavid du Colombier p++; 4583e12c5d1SDavid du Colombier fprintf(stderr, " context is\n\t"); 4593e12c5d1SDavid du Colombier for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) 4603e12c5d1SDavid du Colombier ; 4613e12c5d1SDavid du Colombier for ( ; p < q; p++) 4623e12c5d1SDavid du Colombier if (*p) 4633e12c5d1SDavid du Colombier putc(*p, stderr); 4643e12c5d1SDavid du Colombier fprintf(stderr, " >>> "); 4653e12c5d1SDavid du Colombier for ( ; p < ep; p++) 4663e12c5d1SDavid du Colombier if (*p) 4673e12c5d1SDavid du Colombier putc(*p, stderr); 4683e12c5d1SDavid du Colombier fprintf(stderr, " <<< "); 4693e12c5d1SDavid du Colombier if (*ep) 4703e12c5d1SDavid du Colombier while ((c = input()) != '\n' && c != '\0' && c != EOF) { 4713e12c5d1SDavid du Colombier putc(c, stderr); 4723e12c5d1SDavid du Colombier bclass(c); 4733e12c5d1SDavid du Colombier } 4743e12c5d1SDavid du Colombier putc('\n', stderr); 4753e12c5d1SDavid du Colombier ep = ebuf; 4763e12c5d1SDavid du Colombier } 4773e12c5d1SDavid du Colombier 4783e12c5d1SDavid du Colombier void bclass(int c) 4793e12c5d1SDavid du Colombier { 4803e12c5d1SDavid du Colombier switch (c) { 4813e12c5d1SDavid du Colombier case '{': bracecnt++; break; 4823e12c5d1SDavid du Colombier case '}': bracecnt--; break; 4833e12c5d1SDavid du Colombier case '[': brackcnt++; break; 4843e12c5d1SDavid du Colombier case ']': brackcnt--; break; 4853e12c5d1SDavid du Colombier case '(': parencnt++; break; 4863e12c5d1SDavid du Colombier case ')': parencnt--; break; 4873e12c5d1SDavid du Colombier } 4883e12c5d1SDavid du Colombier } 4893e12c5d1SDavid du Colombier 4903e12c5d1SDavid du Colombier double errcheck(double x, uchar *s) 4913e12c5d1SDavid du Colombier { 4923e12c5d1SDavid du Colombier extern int errno; 4933e12c5d1SDavid du Colombier 4943e12c5d1SDavid du Colombier if (errno == EDOM) { 4953e12c5d1SDavid du Colombier errno = 0; 4963e12c5d1SDavid du Colombier ERROR "%s argument out of domain", s WARNING; 4973e12c5d1SDavid du Colombier x = 1; 4983e12c5d1SDavid du Colombier } else if (errno == ERANGE) { 4993e12c5d1SDavid du Colombier errno = 0; 5003e12c5d1SDavid du Colombier ERROR "%s result out of range", s WARNING; 5013e12c5d1SDavid du Colombier x = 1; 5023e12c5d1SDavid du Colombier } 5033e12c5d1SDavid du Colombier return x; 5043e12c5d1SDavid du Colombier } 5053e12c5d1SDavid du Colombier 5063e12c5d1SDavid du Colombier isclvar(uchar *s) /* is s of form var=something ? */ 5073e12c5d1SDavid du Colombier { 5083e12c5d1SDavid du Colombier uchar *os = s; 5093e12c5d1SDavid du Colombier 5103e12c5d1SDavid du Colombier if (!isalpha(*s) && *s != '_') 5113e12c5d1SDavid du Colombier return 0; 5123e12c5d1SDavid du Colombier for ( ; *s; s++) 5133e12c5d1SDavid du Colombier if (!(isalnum(*s) || *s == '_')) 5143e12c5d1SDavid du Colombier break; 5153e12c5d1SDavid du Colombier return *s == '=' && s > os && *(s+1) != '='; 5163e12c5d1SDavid du Colombier } 5173e12c5d1SDavid du Colombier 518*219b2ee8SDavid du Colombier #define MAXEXPON 38 /* maximum exponent for fp number. should be IEEE */ 5193e12c5d1SDavid du Colombier 520*219b2ee8SDavid du Colombier isnumber(uchar *s) /* should be done by a library function */ 5213e12c5d1SDavid du Colombier { 5223e12c5d1SDavid du Colombier register int d1, d2; 5233e12c5d1SDavid du Colombier int point; 5243e12c5d1SDavid du Colombier uchar *es; 5253e12c5d1SDavid du Colombier 5263e12c5d1SDavid du Colombier d1 = d2 = point = 0; 5273e12c5d1SDavid du Colombier while (*s == ' ' || *s == '\t' || *s == '\n') 5283e12c5d1SDavid du Colombier s++; 5293e12c5d1SDavid du Colombier if (*s == '\0') 530*219b2ee8SDavid du Colombier return(0); /* empty stuff isn't a number */ 5313e12c5d1SDavid du Colombier if (*s == '+' || *s == '-') 5323e12c5d1SDavid du Colombier s++; 5333e12c5d1SDavid du Colombier if (!isdigit(*s) && *s != '.') 5343e12c5d1SDavid du Colombier return(0); 5353e12c5d1SDavid du Colombier if (isdigit(*s)) { 5363e12c5d1SDavid du Colombier do { 5373e12c5d1SDavid du Colombier d1++; 5383e12c5d1SDavid du Colombier s++; 5393e12c5d1SDavid du Colombier } while (isdigit(*s)); 5403e12c5d1SDavid du Colombier } 5413e12c5d1SDavid du Colombier if (*s == '.') { 5423e12c5d1SDavid du Colombier point++; 5433e12c5d1SDavid du Colombier s++; 5443e12c5d1SDavid du Colombier } 5453e12c5d1SDavid du Colombier if (isdigit(*s)) { 5463e12c5d1SDavid du Colombier d2++; 5473e12c5d1SDavid du Colombier do { 5483e12c5d1SDavid du Colombier s++; 5493e12c5d1SDavid du Colombier } while (isdigit(*s)); 5503e12c5d1SDavid du Colombier } 5513e12c5d1SDavid du Colombier if (!(d1 || point && d2)) 5523e12c5d1SDavid du Colombier return(0); 5533e12c5d1SDavid du Colombier if (*s == 'e' || *s == 'E') { 5543e12c5d1SDavid du Colombier s++; 5553e12c5d1SDavid du Colombier if (*s == '+' || *s == '-') 5563e12c5d1SDavid du Colombier s++; 5573e12c5d1SDavid du Colombier if (!isdigit(*s)) 5583e12c5d1SDavid du Colombier return(0); 5593e12c5d1SDavid du Colombier es = s; 5603e12c5d1SDavid du Colombier do { 5613e12c5d1SDavid du Colombier s++; 5623e12c5d1SDavid du Colombier } while (isdigit(*s)); 5633e12c5d1SDavid du Colombier if (s - es > 2) 5643e12c5d1SDavid du Colombier return(0); 5653e12c5d1SDavid du Colombier else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) 5663e12c5d1SDavid du Colombier return(0); 5673e12c5d1SDavid du Colombier } 5683e12c5d1SDavid du Colombier while (*s == ' ' || *s == '\t' || *s == '\n') 5693e12c5d1SDavid du Colombier s++; 5703e12c5d1SDavid du Colombier if (*s == '\0') 5713e12c5d1SDavid du Colombier return(1); 5723e12c5d1SDavid du Colombier else 5733e12c5d1SDavid du Colombier return(0); 5743e12c5d1SDavid du Colombier } 575