1*7dd7cddfSDavid du Colombier /**************************************************************** 2*7dd7cddfSDavid du Colombier Copyright (C) Lucent Technologies 1997 33e12c5d1SDavid du Colombier All Rights Reserved 43e12c5d1SDavid du Colombier 5*7dd7cddfSDavid du Colombier Permission to use, copy, modify, and distribute this software and 6*7dd7cddfSDavid du Colombier its documentation for any purpose and without fee is hereby 7*7dd7cddfSDavid du Colombier granted, provided that the above copyright notice appear in all 8*7dd7cddfSDavid du Colombier copies and that both that the copyright notice and this 9*7dd7cddfSDavid du Colombier permission notice and warranty disclaimer appear in supporting 10*7dd7cddfSDavid du Colombier documentation, and that the name Lucent Technologies or any of 11*7dd7cddfSDavid du Colombier its entities not be used in advertising or publicity pertaining 12*7dd7cddfSDavid du Colombier to distribution of the software without specific, written prior 13*7dd7cddfSDavid du Colombier permission. 143e12c5d1SDavid du Colombier 15*7dd7cddfSDavid du Colombier LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16*7dd7cddfSDavid du Colombier INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 17*7dd7cddfSDavid du Colombier IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 18*7dd7cddfSDavid du Colombier SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19*7dd7cddfSDavid du Colombier WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 20*7dd7cddfSDavid du Colombier IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21*7dd7cddfSDavid du Colombier ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 22*7dd7cddfSDavid du Colombier THIS SOFTWARE. 23*7dd7cddfSDavid du Colombier ****************************************************************/ 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier #define DEBUG 263e12c5d1SDavid du Colombier #include <stdio.h> 273e12c5d1SDavid du Colombier #include <string.h> 283e12c5d1SDavid du Colombier #include <ctype.h> 293e12c5d1SDavid du Colombier #include <errno.h> 303e12c5d1SDavid du Colombier #include <stdlib.h> 31*7dd7cddfSDavid du Colombier #include <stdarg.h> 323e12c5d1SDavid du Colombier #include "awk.h" 333e12c5d1SDavid du Colombier #include "y.tab.h" 343e12c5d1SDavid du Colombier 353e12c5d1SDavid du Colombier FILE *infile = NULL; 36*7dd7cddfSDavid du Colombier char *file = ""; 37*7dd7cddfSDavid du Colombier char *record; 38219b2ee8SDavid du Colombier int recsize = RECSIZE; 39*7dd7cddfSDavid du Colombier char *fields; 40*7dd7cddfSDavid du Colombier int fieldssize = RECSIZE; 41*7dd7cddfSDavid du Colombier 42*7dd7cddfSDavid du Colombier Cell **fldtab; /* pointers to Cells */ 43*7dd7cddfSDavid du Colombier char inputFS[100] = " "; 443e12c5d1SDavid du Colombier 453e12c5d1SDavid du Colombier #define MAXFLD 200 46*7dd7cddfSDavid du Colombier int nfields = MAXFLD; /* last allocated slot for $i */ 47219b2ee8SDavid du Colombier 483e12c5d1SDavid du Colombier int donefld; /* 1 = implies rec broken into fields */ 493e12c5d1SDavid du Colombier int donerec; /* 1 = record is valid (no flds have changed) */ 503e12c5d1SDavid du Colombier 51*7dd7cddfSDavid du Colombier int lastfld = 0; /* last used field */ 523e12c5d1SDavid du Colombier int argno = 1; /* current input argument number */ 533e12c5d1SDavid du Colombier extern Awkfloat *ARGC; 543e12c5d1SDavid du Colombier 55*7dd7cddfSDavid du Colombier static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE }; 56*7dd7cddfSDavid du Colombier static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; 57*7dd7cddfSDavid du Colombier 58219b2ee8SDavid du Colombier void recinit(unsigned int n) 59219b2ee8SDavid du Colombier { 60*7dd7cddfSDavid du Colombier record = (char *) malloc(n); 61*7dd7cddfSDavid du Colombier fields = (char *) malloc(n); 62*7dd7cddfSDavid du Colombier fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *)); 63*7dd7cddfSDavid du Colombier if (record == NULL || fields == NULL || fldtab == NULL) 64*7dd7cddfSDavid du Colombier FATAL("out of space for $0 and fields"); 65*7dd7cddfSDavid du Colombier fldtab[0] = (Cell *) malloc(sizeof (Cell)); 66*7dd7cddfSDavid du Colombier *fldtab[0] = dollar0; 67*7dd7cddfSDavid du Colombier fldtab[0]->sval = record; 68*7dd7cddfSDavid du Colombier fldtab[0]->nval = tostring("0"); 69*7dd7cddfSDavid du Colombier makefields(1, nfields); 70*7dd7cddfSDavid du Colombier } 71*7dd7cddfSDavid du Colombier 72*7dd7cddfSDavid du Colombier void makefields(int n1, int n2) /* create $n1..$n2 inclusive */ 73*7dd7cddfSDavid du Colombier { 74*7dd7cddfSDavid du Colombier char temp[50]; 75219b2ee8SDavid du Colombier int i; 76219b2ee8SDavid du Colombier 77*7dd7cddfSDavid du Colombier for (i = n1; i <= n2; i++) { 78*7dd7cddfSDavid du Colombier fldtab[i] = (Cell *) malloc(sizeof (struct Cell)); 79*7dd7cddfSDavid du Colombier if (fldtab[i] == NULL) 80*7dd7cddfSDavid du Colombier FATAL("out of space in makefields %d", i); 81*7dd7cddfSDavid du Colombier *fldtab[i] = dollar1; 82*7dd7cddfSDavid du Colombier sprintf(temp, "%d", i); 83*7dd7cddfSDavid du Colombier fldtab[i]->nval = tostring(temp); 84*7dd7cddfSDavid du Colombier } 85219b2ee8SDavid du Colombier } 86219b2ee8SDavid du Colombier 873e12c5d1SDavid du Colombier void initgetrec(void) 883e12c5d1SDavid du Colombier { 893e12c5d1SDavid du Colombier int i; 90*7dd7cddfSDavid du Colombier char *p; 913e12c5d1SDavid du Colombier 923e12c5d1SDavid du Colombier for (i = 1; i < *ARGC; i++) { 93219b2ee8SDavid du Colombier if (!isclvar(p = getargv(i))) { /* find 1st real filename */ 94219b2ee8SDavid du Colombier setsval(lookup("FILENAME", symtab), getargv(i)); 953e12c5d1SDavid du Colombier return; 96219b2ee8SDavid du Colombier } 973e12c5d1SDavid du Colombier setclvar(p); /* a commandline assignment before filename */ 983e12c5d1SDavid du Colombier argno++; 993e12c5d1SDavid du Colombier } 1003e12c5d1SDavid du Colombier infile = stdin; /* no filenames, so use stdin */ 1013e12c5d1SDavid du Colombier } 1023e12c5d1SDavid du Colombier 103*7dd7cddfSDavid du Colombier int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */ 104*7dd7cddfSDavid du Colombier { /* note: cares whether buf == record */ 1053e12c5d1SDavid du Colombier int c; 1063e12c5d1SDavid du Colombier static int firsttime = 1; 107*7dd7cddfSDavid du Colombier char *buf = *pbuf; 108*7dd7cddfSDavid du Colombier int bufsize = *pbufsize; 1093e12c5d1SDavid du Colombier 1103e12c5d1SDavid du Colombier if (firsttime) { 1113e12c5d1SDavid du Colombier firsttime = 0; 1123e12c5d1SDavid du Colombier initgetrec(); 1133e12c5d1SDavid du Colombier } 1143e12c5d1SDavid du Colombier dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", 1153e12c5d1SDavid du Colombier *RS, *FS, *ARGC, *FILENAME) ); 116*7dd7cddfSDavid du Colombier if (isrecord) { 1173e12c5d1SDavid du Colombier donefld = 0; 1183e12c5d1SDavid du Colombier donerec = 1; 119*7dd7cddfSDavid du Colombier } 1203e12c5d1SDavid du Colombier buf[0] = 0; 1213e12c5d1SDavid du Colombier while (argno < *ARGC || infile == stdin) { 1223e12c5d1SDavid du Colombier dprintf( ("argno=%d, file=|%s|\n", argno, file) ); 1233e12c5d1SDavid du Colombier if (infile == NULL) { /* have to open a new file */ 1243e12c5d1SDavid du Colombier file = getargv(argno); 1253e12c5d1SDavid du Colombier if (*file == '\0') { /* it's been zapped */ 1263e12c5d1SDavid du Colombier argno++; 1273e12c5d1SDavid du Colombier continue; 1283e12c5d1SDavid du Colombier } 1293e12c5d1SDavid du Colombier if (isclvar(file)) { /* a var=value arg */ 1303e12c5d1SDavid du Colombier setclvar(file); 1313e12c5d1SDavid du Colombier argno++; 1323e12c5d1SDavid du Colombier continue; 1333e12c5d1SDavid du Colombier } 1343e12c5d1SDavid du Colombier *FILENAME = file; 1353e12c5d1SDavid du Colombier dprintf( ("opening file %s\n", file) ); 1363e12c5d1SDavid du Colombier if (*file == '-' && *(file+1) == '\0') 1373e12c5d1SDavid du Colombier infile = stdin; 138*7dd7cddfSDavid du Colombier else if ((infile = fopen(file, "r")) == NULL) 139*7dd7cddfSDavid du Colombier FATAL("can't open file %s", file); 1403e12c5d1SDavid du Colombier setfval(fnrloc, 0.0); 1413e12c5d1SDavid du Colombier } 142*7dd7cddfSDavid du Colombier c = readrec(&buf, &bufsize, infile); 1433e12c5d1SDavid du Colombier if (c != 0 || buf[0] != '\0') { /* normal record */ 144*7dd7cddfSDavid du Colombier if (isrecord) { 145*7dd7cddfSDavid du Colombier if (freeable(fldtab[0])) 146*7dd7cddfSDavid du Colombier xfree(fldtab[0]->sval); 147*7dd7cddfSDavid du Colombier fldtab[0]->sval = buf; /* buf == record */ 148*7dd7cddfSDavid du Colombier fldtab[0]->tval = REC | STR | DONTFREE; 149*7dd7cddfSDavid du Colombier if (is_number(fldtab[0]->sval)) { 150*7dd7cddfSDavid du Colombier fldtab[0]->fval = atof(fldtab[0]->sval); 151*7dd7cddfSDavid du Colombier fldtab[0]->tval |= NUM; 1523e12c5d1SDavid du Colombier } 1533e12c5d1SDavid du Colombier } 1543e12c5d1SDavid du Colombier setfval(nrloc, nrloc->fval+1); 1553e12c5d1SDavid du Colombier setfval(fnrloc, fnrloc->fval+1); 156*7dd7cddfSDavid du Colombier *pbuf = buf; 157*7dd7cddfSDavid du Colombier *pbufsize = bufsize; 1583e12c5d1SDavid du Colombier return 1; 1593e12c5d1SDavid du Colombier } 1603e12c5d1SDavid du Colombier /* EOF arrived on this file; set up next */ 1613e12c5d1SDavid du Colombier if (infile != stdin) 1623e12c5d1SDavid du Colombier fclose(infile); 1633e12c5d1SDavid du Colombier infile = NULL; 1643e12c5d1SDavid du Colombier argno++; 1653e12c5d1SDavid du Colombier } 166*7dd7cddfSDavid du Colombier *pbuf = buf; 167*7dd7cddfSDavid du Colombier *pbufsize = bufsize; 1683e12c5d1SDavid du Colombier return 0; /* true end of file */ 1693e12c5d1SDavid du Colombier } 1703e12c5d1SDavid du Colombier 171*7dd7cddfSDavid du Colombier void nextfile(void) 1723e12c5d1SDavid du Colombier { 173*7dd7cddfSDavid du Colombier if (infile != stdin) 174*7dd7cddfSDavid du Colombier fclose(infile); 175*7dd7cddfSDavid du Colombier infile = NULL; 176*7dd7cddfSDavid du Colombier argno++; 177*7dd7cddfSDavid du Colombier } 1783e12c5d1SDavid du Colombier 179*7dd7cddfSDavid du Colombier int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */ 180*7dd7cddfSDavid du Colombier { 181*7dd7cddfSDavid du Colombier int sep, c; 182*7dd7cddfSDavid du Colombier char *rr, *buf = *pbuf; 183*7dd7cddfSDavid du Colombier int bufsize = *pbufsize; 184*7dd7cddfSDavid du Colombier 185*7dd7cddfSDavid du Colombier if (strlen(*FS) >= sizeof(inputFS)) 186*7dd7cddfSDavid du Colombier FATAL("field separator %.10s... is too long", *FS); 187*7dd7cddfSDavid du Colombier strcpy(inputFS, *FS); /* for subsequent field splitting */ 1883e12c5d1SDavid du Colombier if ((sep = **RS) == 0) { 1893e12c5d1SDavid du Colombier sep = '\n'; 1903e12c5d1SDavid du Colombier while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */ 1913e12c5d1SDavid du Colombier ; 1923e12c5d1SDavid du Colombier if (c != EOF) 1933e12c5d1SDavid du Colombier ungetc(c, inf); 1943e12c5d1SDavid du Colombier } 195*7dd7cddfSDavid du Colombier for (rr = buf; ; ) { 196*7dd7cddfSDavid du Colombier for (; (c=getc(inf)) != sep && c != EOF; ) { 197*7dd7cddfSDavid du Colombier if (rr-buf+1 > bufsize) 198*7dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1")) 199*7dd7cddfSDavid du Colombier FATAL("input record `%.30s...' too long", buf); 200*7dd7cddfSDavid du Colombier *rr++ = c; 201*7dd7cddfSDavid du Colombier } 2023e12c5d1SDavid du Colombier if (**RS == sep || c == EOF) 2033e12c5d1SDavid du Colombier break; 2043e12c5d1SDavid du Colombier if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ 2053e12c5d1SDavid du Colombier break; 206*7dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2")) 207*7dd7cddfSDavid du Colombier FATAL("input record `%.30s...' too long", buf); 2083e12c5d1SDavid du Colombier *rr++ = '\n'; 2093e12c5d1SDavid du Colombier *rr++ = c; 2103e12c5d1SDavid du Colombier } 211*7dd7cddfSDavid du Colombier if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3")) 212*7dd7cddfSDavid du Colombier FATAL("input record `%.30s...' too long", buf); 2133e12c5d1SDavid du Colombier *rr = 0; 2143e12c5d1SDavid du Colombier dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) ); 215*7dd7cddfSDavid du Colombier *pbuf = buf; 216*7dd7cddfSDavid du Colombier *pbufsize = bufsize; 2173e12c5d1SDavid du Colombier return c == EOF && rr == buf ? 0 : 1; 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier 220*7dd7cddfSDavid du Colombier char *getargv(int n) /* get ARGV[n] */ 2213e12c5d1SDavid du Colombier { 2223e12c5d1SDavid du Colombier Cell *x; 223*7dd7cddfSDavid du Colombier char *s, temp[50]; 2243e12c5d1SDavid du Colombier extern Array *ARGVtab; 2253e12c5d1SDavid du Colombier 226*7dd7cddfSDavid du Colombier sprintf(temp, "%d", n); 2273e12c5d1SDavid du Colombier x = setsymtab(temp, "", 0.0, STR, ARGVtab); 2283e12c5d1SDavid du Colombier s = getsval(x); 2293e12c5d1SDavid du Colombier dprintf( ("getargv(%d) returns |%s|\n", n, s) ); 2303e12c5d1SDavid du Colombier return s; 2313e12c5d1SDavid du Colombier } 2323e12c5d1SDavid du Colombier 233*7dd7cddfSDavid du Colombier void setclvar(char *s) /* set var=value from s */ 2343e12c5d1SDavid du Colombier { 235*7dd7cddfSDavid du Colombier char *p; 2363e12c5d1SDavid du Colombier Cell *q; 2373e12c5d1SDavid du Colombier 2383e12c5d1SDavid du Colombier for (p=s; *p != '='; p++) 2393e12c5d1SDavid du Colombier ; 2403e12c5d1SDavid du Colombier *p++ = 0; 2413e12c5d1SDavid du Colombier p = qstring(p, '\0'); 2423e12c5d1SDavid du Colombier q = setsymtab(s, p, 0.0, STR, symtab); 2433e12c5d1SDavid du Colombier setsval(q, p); 244*7dd7cddfSDavid du Colombier if (is_number(q->sval)) { 2453e12c5d1SDavid du Colombier q->fval = atof(q->sval); 2463e12c5d1SDavid du Colombier q->tval |= NUM; 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier dprintf( ("command line set %s to |%s|\n", s, p) ); 2493e12c5d1SDavid du Colombier } 2503e12c5d1SDavid du Colombier 2513e12c5d1SDavid du Colombier 252219b2ee8SDavid du Colombier void fldbld(void) /* create fields from current record */ 2533e12c5d1SDavid du Colombier { 254*7dd7cddfSDavid du Colombier /* this relies on having fields[] the same length as $0 */ 255*7dd7cddfSDavid du Colombier /* the fields are all stored in this one array with \0's */ 256*7dd7cddfSDavid du Colombier char *r, *fr, sep; 2573e12c5d1SDavid du Colombier Cell *p; 258*7dd7cddfSDavid du Colombier int i, j, n; 2593e12c5d1SDavid du Colombier 2603e12c5d1SDavid du Colombier if (donefld) 2613e12c5d1SDavid du Colombier return; 262*7dd7cddfSDavid du Colombier if (!isstr(fldtab[0])) 263*7dd7cddfSDavid du Colombier getsval(fldtab[0]); 264*7dd7cddfSDavid du Colombier r = fldtab[0]->sval; 265*7dd7cddfSDavid du Colombier n = strlen(r); 266*7dd7cddfSDavid du Colombier if (n > fieldssize) { 267*7dd7cddfSDavid du Colombier xfree(fields); 268*7dd7cddfSDavid du Colombier if ((fields = (char *) malloc(n+1)) == NULL) 269*7dd7cddfSDavid du Colombier FATAL("out of space for fields in fldbld %d", n); 270*7dd7cddfSDavid du Colombier fieldssize = n; 271*7dd7cddfSDavid du Colombier } 2723e12c5d1SDavid du Colombier fr = fields; 2733e12c5d1SDavid du Colombier i = 0; /* number of fields accumulated here */ 274*7dd7cddfSDavid du Colombier if (strlen(inputFS) > 1) { /* it's a regular expression */ 275*7dd7cddfSDavid du Colombier i = refldbld(r, inputFS); 276*7dd7cddfSDavid du Colombier } else if ((sep = *inputFS) == ' ') { /* default whitespace */ 2773e12c5d1SDavid du Colombier for (i = 0; ; ) { 2783e12c5d1SDavid du Colombier while (*r == ' ' || *r == '\t' || *r == '\n') 2793e12c5d1SDavid du Colombier r++; 2803e12c5d1SDavid du Colombier if (*r == 0) 2813e12c5d1SDavid du Colombier break; 2823e12c5d1SDavid du Colombier i++; 283*7dd7cddfSDavid du Colombier if (i > nfields) 284*7dd7cddfSDavid du Colombier growfldtab(i); 285*7dd7cddfSDavid du Colombier if (freeable(fldtab[i])) 286*7dd7cddfSDavid du Colombier xfree(fldtab[i]->sval); 287*7dd7cddfSDavid du Colombier fldtab[i]->sval = fr; 288*7dd7cddfSDavid du Colombier fldtab[i]->tval = FLD | STR | DONTFREE; 2893e12c5d1SDavid du Colombier do 2903e12c5d1SDavid du Colombier *fr++ = *r++; 2913e12c5d1SDavid du Colombier while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); 2923e12c5d1SDavid du Colombier *fr++ = 0; 2933e12c5d1SDavid du Colombier } 2943e12c5d1SDavid du Colombier *fr = 0; 295*7dd7cddfSDavid du Colombier } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */ 296*7dd7cddfSDavid du Colombier for (i = 0; *r != 0; r++) { 297*7dd7cddfSDavid du Colombier char buf[2]; 298*7dd7cddfSDavid du Colombier i++; 299*7dd7cddfSDavid du Colombier if (i > nfields) 300*7dd7cddfSDavid du Colombier growfldtab(i); 301*7dd7cddfSDavid du Colombier if (freeable(fldtab[i])) 302*7dd7cddfSDavid du Colombier xfree(fldtab[i]->sval); 303*7dd7cddfSDavid du Colombier buf[0] = *r; 304*7dd7cddfSDavid du Colombier buf[1] = 0; 305*7dd7cddfSDavid du Colombier fldtab[i]->sval = tostring(buf); 306*7dd7cddfSDavid du Colombier fldtab[i]->tval = FLD | STR; 307*7dd7cddfSDavid du Colombier } 308*7dd7cddfSDavid du Colombier *fr = 0; 3093e12c5d1SDavid du Colombier } else if (*r != 0) { /* if 0, it's a null field */ 3103e12c5d1SDavid du Colombier for (;;) { 3113e12c5d1SDavid du Colombier i++; 312*7dd7cddfSDavid du Colombier if (i > nfields) 313*7dd7cddfSDavid du Colombier growfldtab(i); 314*7dd7cddfSDavid du Colombier if (freeable(fldtab[i])) 315*7dd7cddfSDavid du Colombier xfree(fldtab[i]->sval); 316*7dd7cddfSDavid du Colombier fldtab[i]->sval = fr; 317*7dd7cddfSDavid du Colombier fldtab[i]->tval = FLD | STR | DONTFREE; 318219b2ee8SDavid du Colombier while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */ 3193e12c5d1SDavid du Colombier *fr++ = *r++; 3203e12c5d1SDavid du Colombier *fr++ = 0; 3213e12c5d1SDavid du Colombier if (*r++ == 0) 3223e12c5d1SDavid du Colombier break; 3233e12c5d1SDavid du Colombier } 3243e12c5d1SDavid du Colombier *fr = 0; 3253e12c5d1SDavid du Colombier } 326*7dd7cddfSDavid du Colombier if (i > nfields) 327*7dd7cddfSDavid du Colombier FATAL("record `%.30s...' has too many fields; can't happen", r); 328*7dd7cddfSDavid du Colombier cleanfld(i+1, lastfld); /* clean out junk from previous record */ 329*7dd7cddfSDavid du Colombier lastfld = i; 3303e12c5d1SDavid du Colombier donefld = 1; 331*7dd7cddfSDavid du Colombier for (j = 1; j <= lastfld; j++) { 332*7dd7cddfSDavid du Colombier p = fldtab[j]; 333*7dd7cddfSDavid du Colombier if(is_number(p->sval)) { 3343e12c5d1SDavid du Colombier p->fval = atof(p->sval); 3353e12c5d1SDavid du Colombier p->tval |= NUM; 3363e12c5d1SDavid du Colombier } 3373e12c5d1SDavid du Colombier } 338*7dd7cddfSDavid du Colombier setfval(nfloc, (Awkfloat) lastfld); 339*7dd7cddfSDavid du Colombier if (dbg) { 340*7dd7cddfSDavid du Colombier for (j = 0; j <= lastfld; j++) { 341*7dd7cddfSDavid du Colombier p = fldtab[j]; 342*7dd7cddfSDavid du Colombier printf("field %d (%s): |%s|\n", j, p->nval, p->sval); 343*7dd7cddfSDavid du Colombier } 344*7dd7cddfSDavid du Colombier } 3453e12c5d1SDavid du Colombier } 3463e12c5d1SDavid du Colombier 3473e12c5d1SDavid du Colombier void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */ 348*7dd7cddfSDavid du Colombier { /* nvals remain intact */ 349*7dd7cddfSDavid du Colombier Cell *p; 350*7dd7cddfSDavid du Colombier int i; 3513e12c5d1SDavid du Colombier 352*7dd7cddfSDavid du Colombier for (i = n1; i <= n2; i++) { 353*7dd7cddfSDavid du Colombier p = fldtab[i]; 354*7dd7cddfSDavid du Colombier if (freeable(p)) 3553e12c5d1SDavid du Colombier xfree(p->sval); 356*7dd7cddfSDavid du Colombier p->sval = ""; 3573e12c5d1SDavid du Colombier p->tval = FLD | STR | DONTFREE; 3583e12c5d1SDavid du Colombier } 3593e12c5d1SDavid du Colombier } 3603e12c5d1SDavid du Colombier 361*7dd7cddfSDavid du Colombier void newfld(int n) /* add field n after end of existing lastfld */ 3623e12c5d1SDavid du Colombier { 363*7dd7cddfSDavid du Colombier if (n > nfields) 364*7dd7cddfSDavid du Colombier growfldtab(n); 365*7dd7cddfSDavid du Colombier cleanfld(lastfld+1, n); 366*7dd7cddfSDavid du Colombier lastfld = n; 3673e12c5d1SDavid du Colombier setfval(nfloc, (Awkfloat) n); 3683e12c5d1SDavid du Colombier } 3693e12c5d1SDavid du Colombier 370*7dd7cddfSDavid du Colombier Cell *fieldadr(int n) /* get nth field */ 3713e12c5d1SDavid du Colombier { 372*7dd7cddfSDavid du Colombier if (n < 0) 373*7dd7cddfSDavid du Colombier FATAL("trying to access field %d", n); 374*7dd7cddfSDavid du Colombier if (n > nfields) /* fields after NF are empty */ 375*7dd7cddfSDavid du Colombier growfldtab(n); /* but does not increase NF */ 376*7dd7cddfSDavid du Colombier return(fldtab[n]); 377*7dd7cddfSDavid du Colombier } 3783e12c5d1SDavid du Colombier 379*7dd7cddfSDavid du Colombier void growfldtab(int n) /* make new fields up to at least $n */ 380*7dd7cddfSDavid du Colombier { 381*7dd7cddfSDavid du Colombier int nf = 2 * nfields; 382*7dd7cddfSDavid du Colombier 383*7dd7cddfSDavid du Colombier if (n > nf) 384*7dd7cddfSDavid du Colombier nf = n; 385*7dd7cddfSDavid du Colombier fldtab = (Cell **) realloc(fldtab, (nf+1) * (sizeof (struct Cell *))); 386*7dd7cddfSDavid du Colombier if (fldtab == NULL) 387*7dd7cddfSDavid du Colombier FATAL("out of space creating %d fields", nf); 388*7dd7cddfSDavid du Colombier makefields(nfields+1, nf); 389*7dd7cddfSDavid du Colombier nfields = nf; 390*7dd7cddfSDavid du Colombier } 391*7dd7cddfSDavid du Colombier 392*7dd7cddfSDavid du Colombier int refldbld(char *rec, char *fs) /* build fields from reg expr in FS */ 393*7dd7cddfSDavid du Colombier { 394*7dd7cddfSDavid du Colombier /* this relies on having fields[] the same length as $0 */ 395*7dd7cddfSDavid du Colombier /* the fields are all stored in this one array with \0's */ 396*7dd7cddfSDavid du Colombier char *fr; 397*7dd7cddfSDavid du Colombier void *p; 398*7dd7cddfSDavid du Colombier int i, tempstat, n; 399*7dd7cddfSDavid du Colombier 400*7dd7cddfSDavid du Colombier n = strlen(rec); 401*7dd7cddfSDavid du Colombier if (n > fieldssize) { 402*7dd7cddfSDavid du Colombier xfree(fields); 403*7dd7cddfSDavid du Colombier if ((fields = (char *) malloc(n+1)) == NULL) 404*7dd7cddfSDavid du Colombier FATAL("out of space for fields in refldbld %d", n); 405*7dd7cddfSDavid du Colombier fieldssize = n; 406*7dd7cddfSDavid du Colombier } 4073e12c5d1SDavid du Colombier fr = fields; 4083e12c5d1SDavid du Colombier *fr = '\0'; 4093e12c5d1SDavid du Colombier if (*rec == '\0') 4103e12c5d1SDavid du Colombier return 0; 4113e12c5d1SDavid du Colombier p = compre(fs); 4123e12c5d1SDavid du Colombier dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) ); 413*7dd7cddfSDavid du Colombier for (i = 1; ; i++) { 414*7dd7cddfSDavid du Colombier if (i > nfields) 415*7dd7cddfSDavid du Colombier growfldtab(i); 416*7dd7cddfSDavid du Colombier if (freeable(fldtab[i])) 417*7dd7cddfSDavid du Colombier xfree(fldtab[i]->sval); 418*7dd7cddfSDavid du Colombier fldtab[i]->tval = FLD | STR | DONTFREE; 419*7dd7cddfSDavid du Colombier fldtab[i]->sval = fr; 4203e12c5d1SDavid du Colombier dprintf( ("refldbld: i=%d\n", i) ); 4213e12c5d1SDavid du Colombier if (nematch(p, rec, rec)) { 4223e12c5d1SDavid du Colombier dprintf( ("match %s (%d chars)\n", patbeg, patlen) ); 4233e12c5d1SDavid du Colombier strncpy(fr, rec, patbeg-rec); 4243e12c5d1SDavid du Colombier fr += patbeg - rec + 1; 4253e12c5d1SDavid du Colombier *(fr-1) = '\0'; 4263e12c5d1SDavid du Colombier rec = patbeg + patlen; 4273e12c5d1SDavid du Colombier } else { 4283e12c5d1SDavid du Colombier dprintf( ("no match %s\n", rec) ); 4293e12c5d1SDavid du Colombier strcpy(fr, rec); 4303e12c5d1SDavid du Colombier break; 4313e12c5d1SDavid du Colombier } 4323e12c5d1SDavid du Colombier } 4333e12c5d1SDavid du Colombier return i; 4343e12c5d1SDavid du Colombier } 4353e12c5d1SDavid du Colombier 436219b2ee8SDavid du Colombier void recbld(void) /* create $0 from $1..$NF if necessary */ 4373e12c5d1SDavid du Colombier { 438*7dd7cddfSDavid du Colombier int i; 439*7dd7cddfSDavid du Colombier char *r, *p; 4403e12c5d1SDavid du Colombier 4413e12c5d1SDavid du Colombier if (donerec == 1) 4423e12c5d1SDavid du Colombier return; 443*7dd7cddfSDavid du Colombier r = record; 4443e12c5d1SDavid du Colombier for (i = 1; i <= *NF; i++) { 445*7dd7cddfSDavid du Colombier p = getsval(fldtab[i]); 446*7dd7cddfSDavid du Colombier if (!adjbuf(&record, &recsize, 1+strlen(p)+r-record, recsize, &r, "recbld 1")) 447*7dd7cddfSDavid du Colombier FATAL("created $0 `%.30s...' too long", record); 448*7dd7cddfSDavid du Colombier while ((*r = *p++) != 0) 4493e12c5d1SDavid du Colombier r++; 450*7dd7cddfSDavid du Colombier if (i < *NF) { 451*7dd7cddfSDavid du Colombier if (!adjbuf(&record, &recsize, 2+strlen(*OFS)+r-record, recsize, &r, "recbld 2")) 452*7dd7cddfSDavid du Colombier FATAL("created $0 `%.30s...' too long", record); 453*7dd7cddfSDavid du Colombier for (p = *OFS; (*r = *p++) != 0; ) 4543e12c5d1SDavid du Colombier r++; 4553e12c5d1SDavid du Colombier } 456*7dd7cddfSDavid du Colombier } 457*7dd7cddfSDavid du Colombier if (!adjbuf(&record, &recsize, 2+r-record, recsize, &r, "recbld 3")) 458*7dd7cddfSDavid du Colombier FATAL("built giant record `%.30s...'", record); 4593e12c5d1SDavid du Colombier *r = '\0'; 460*7dd7cddfSDavid du Colombier dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) ); 461*7dd7cddfSDavid du Colombier 462*7dd7cddfSDavid du Colombier if (freeable(fldtab[0])) 463*7dd7cddfSDavid du Colombier xfree(fldtab[0]->sval); 464*7dd7cddfSDavid du Colombier fldtab[0]->tval = REC | STR | DONTFREE; 465*7dd7cddfSDavid du Colombier fldtab[0]->sval = record; 466*7dd7cddfSDavid du Colombier 467*7dd7cddfSDavid du Colombier dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) ); 4683e12c5d1SDavid du Colombier dprintf( ("recbld = |%s|\n", record) ); 4693e12c5d1SDavid du Colombier donerec = 1; 4703e12c5d1SDavid du Colombier } 4713e12c5d1SDavid du Colombier 472*7dd7cddfSDavid du Colombier int errorflag = 0; 473*7dd7cddfSDavid du Colombier 474*7dd7cddfSDavid du Colombier void yyerror(char *s) 4753e12c5d1SDavid du Colombier { 476*7dd7cddfSDavid du Colombier SYNTAX(s); 4773e12c5d1SDavid du Colombier } 4783e12c5d1SDavid du Colombier 479*7dd7cddfSDavid du Colombier void SYNTAX(char *fmt, ...) 4803e12c5d1SDavid du Colombier { 481*7dd7cddfSDavid du Colombier extern char *cmdname, *curfname; 4823e12c5d1SDavid du Colombier static int been_here = 0; 483*7dd7cddfSDavid du Colombier va_list varg; 4843e12c5d1SDavid du Colombier 4853e12c5d1SDavid du Colombier if (been_here++ > 2) 4863e12c5d1SDavid du Colombier return; 487*7dd7cddfSDavid du Colombier fprintf(stderr, "%s: ", cmdname); 488*7dd7cddfSDavid du Colombier va_start(varg, fmt); 489*7dd7cddfSDavid du Colombier vfprintf(stderr, fmt, varg); 490*7dd7cddfSDavid du Colombier va_end(varg); 491*7dd7cddfSDavid du Colombier if(compile_time == 1 && cursource() != NULL) 492*7dd7cddfSDavid du Colombier fprintf(stderr, " at %s:%d", cursource(), lineno); 493*7dd7cddfSDavid du Colombier else 494*7dd7cddfSDavid du Colombier fprintf(stderr, " at line %d", lineno); 4953e12c5d1SDavid du Colombier if (curfname != NULL) 4963e12c5d1SDavid du Colombier fprintf(stderr, " in function %s", curfname); 4973e12c5d1SDavid du Colombier fprintf(stderr, "\n"); 4983e12c5d1SDavid du Colombier errorflag = 2; 4993e12c5d1SDavid du Colombier eprint(); 5003e12c5d1SDavid du Colombier } 5013e12c5d1SDavid du Colombier 5023e12c5d1SDavid du Colombier void fpecatch(int n) 5033e12c5d1SDavid du Colombier { 504*7dd7cddfSDavid du Colombier FATAL("floating point exception %d", n); 5053e12c5d1SDavid du Colombier } 5063e12c5d1SDavid du Colombier 5073e12c5d1SDavid du Colombier extern int bracecnt, brackcnt, parencnt; 5083e12c5d1SDavid du Colombier 5093e12c5d1SDavid du Colombier void bracecheck(void) 5103e12c5d1SDavid du Colombier { 5113e12c5d1SDavid du Colombier int c; 5123e12c5d1SDavid du Colombier static int beenhere = 0; 5133e12c5d1SDavid du Colombier 5143e12c5d1SDavid du Colombier if (beenhere++) 5153e12c5d1SDavid du Colombier return; 5163e12c5d1SDavid du Colombier while ((c = input()) != EOF && c != '\0') 5173e12c5d1SDavid du Colombier bclass(c); 5183e12c5d1SDavid du Colombier bcheck2(bracecnt, '{', '}'); 5193e12c5d1SDavid du Colombier bcheck2(brackcnt, '[', ']'); 5203e12c5d1SDavid du Colombier bcheck2(parencnt, '(', ')'); 5213e12c5d1SDavid du Colombier } 5223e12c5d1SDavid du Colombier 5233e12c5d1SDavid du Colombier void bcheck2(int n, int c1, int c2) 5243e12c5d1SDavid du Colombier { 5253e12c5d1SDavid du Colombier if (n == 1) 5263e12c5d1SDavid du Colombier fprintf(stderr, "\tmissing %c\n", c2); 5273e12c5d1SDavid du Colombier else if (n > 1) 5283e12c5d1SDavid du Colombier fprintf(stderr, "\t%d missing %c's\n", n, c2); 5293e12c5d1SDavid du Colombier else if (n == -1) 5303e12c5d1SDavid du Colombier fprintf(stderr, "\textra %c\n", c2); 5313e12c5d1SDavid du Colombier else if (n < -1) 5323e12c5d1SDavid du Colombier fprintf(stderr, "\t%d extra %c's\n", -n, c2); 5333e12c5d1SDavid du Colombier } 5343e12c5d1SDavid du Colombier 535*7dd7cddfSDavid du Colombier void FATAL(char *fmt, ...) 5363e12c5d1SDavid du Colombier { 537*7dd7cddfSDavid du Colombier extern char *cmdname; 538*7dd7cddfSDavid du Colombier va_list varg; 5393e12c5d1SDavid du Colombier 5403e12c5d1SDavid du Colombier fflush(stdout); 5413e12c5d1SDavid du Colombier fprintf(stderr, "%s: ", cmdname); 542*7dd7cddfSDavid du Colombier va_start(varg, fmt); 543*7dd7cddfSDavid du Colombier vfprintf(stderr, fmt, varg); 544*7dd7cddfSDavid du Colombier va_end(varg); 545*7dd7cddfSDavid du Colombier error(); 546219b2ee8SDavid du Colombier if (dbg > 1) /* core dump if serious debugging on */ 5473e12c5d1SDavid du Colombier abort(); 5483e12c5d1SDavid du Colombier exit(2); 5493e12c5d1SDavid du Colombier } 550*7dd7cddfSDavid du Colombier 551*7dd7cddfSDavid du Colombier void WARNING(char *fmt, ...) 552*7dd7cddfSDavid du Colombier { 553*7dd7cddfSDavid du Colombier extern char *cmdname; 554*7dd7cddfSDavid du Colombier va_list varg; 555*7dd7cddfSDavid du Colombier 556*7dd7cddfSDavid du Colombier fflush(stdout); 557*7dd7cddfSDavid du Colombier fprintf(stderr, "%s: ", cmdname); 558*7dd7cddfSDavid du Colombier va_start(varg, fmt); 559*7dd7cddfSDavid du Colombier vfprintf(stderr, fmt, varg); 560*7dd7cddfSDavid du Colombier va_end(varg); 561*7dd7cddfSDavid du Colombier error(); 562*7dd7cddfSDavid du Colombier } 563*7dd7cddfSDavid du Colombier 564*7dd7cddfSDavid du Colombier void error() 565*7dd7cddfSDavid du Colombier { 566*7dd7cddfSDavid du Colombier extern Node *curnode; 567*7dd7cddfSDavid du Colombier int line; 568*7dd7cddfSDavid du Colombier 569*7dd7cddfSDavid du Colombier fprintf(stderr, "\n"); 570*7dd7cddfSDavid du Colombier if (compile_time != 2 && NR && *NR > 0) { 571*7dd7cddfSDavid du Colombier if (strcmp(*FILENAME, "-") != 0) 572*7dd7cddfSDavid du Colombier fprintf(stderr, " input record %s:%d", *FILENAME, (int) (*FNR)); 573*7dd7cddfSDavid du Colombier else 574*7dd7cddfSDavid du Colombier fprintf(stderr, " input record number %d", (int) (*FNR)); 575*7dd7cddfSDavid du Colombier fprintf(stderr, "\n"); 576*7dd7cddfSDavid du Colombier } 577*7dd7cddfSDavid du Colombier if (compile_time != 2 && curnode) 578*7dd7cddfSDavid du Colombier line = curnode->lineno; 579*7dd7cddfSDavid du Colombier else if (compile_time != 2 && lineno) 580*7dd7cddfSDavid du Colombier line = lineno; 581*7dd7cddfSDavid du Colombier else 582*7dd7cddfSDavid du Colombier line = -1; 583*7dd7cddfSDavid du Colombier if (compile_time == 1 && cursource() != NULL){ 584*7dd7cddfSDavid du Colombier if(line >= 0) 585*7dd7cddfSDavid du Colombier fprintf(stderr, " source %s:%d", cursource(), line); 586*7dd7cddfSDavid du Colombier else 587*7dd7cddfSDavid du Colombier fprintf(stderr, " source file %s", cursource()); 588*7dd7cddfSDavid du Colombier }else if(line >= 0) 589*7dd7cddfSDavid du Colombier fprintf(stderr, " source line %d", line); 590*7dd7cddfSDavid du Colombier fprintf(stderr, "\n"); 591*7dd7cddfSDavid du Colombier eprint(); 5923e12c5d1SDavid du Colombier } 5933e12c5d1SDavid du Colombier 5943e12c5d1SDavid du Colombier void eprint(void) /* try to print context around error */ 5953e12c5d1SDavid du Colombier { 596*7dd7cddfSDavid du Colombier char *p, *q; 5973e12c5d1SDavid du Colombier int c; 5983e12c5d1SDavid du Colombier static int been_here = 0; 599*7dd7cddfSDavid du Colombier extern char ebuf[], *ep; 6003e12c5d1SDavid du Colombier 6013e12c5d1SDavid du Colombier if (compile_time == 2 || compile_time == 0 || been_here++ > 0) 6023e12c5d1SDavid du Colombier return; 6033e12c5d1SDavid du Colombier p = ep - 1; 6043e12c5d1SDavid du Colombier if (p > ebuf && *p == '\n') 6053e12c5d1SDavid du Colombier p--; 6063e12c5d1SDavid du Colombier for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--) 6073e12c5d1SDavid du Colombier ; 6083e12c5d1SDavid du Colombier while (*p == '\n') 6093e12c5d1SDavid du Colombier p++; 6103e12c5d1SDavid du Colombier fprintf(stderr, " context is\n\t"); 6113e12c5d1SDavid du Colombier for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) 6123e12c5d1SDavid du Colombier ; 6133e12c5d1SDavid du Colombier for ( ; p < q; p++) 6143e12c5d1SDavid du Colombier if (*p) 6153e12c5d1SDavid du Colombier putc(*p, stderr); 6163e12c5d1SDavid du Colombier fprintf(stderr, " >>> "); 6173e12c5d1SDavid du Colombier for ( ; p < ep; p++) 6183e12c5d1SDavid du Colombier if (*p) 6193e12c5d1SDavid du Colombier putc(*p, stderr); 6203e12c5d1SDavid du Colombier fprintf(stderr, " <<< "); 6213e12c5d1SDavid du Colombier if (*ep) 6223e12c5d1SDavid du Colombier while ((c = input()) != '\n' && c != '\0' && c != EOF) { 6233e12c5d1SDavid du Colombier putc(c, stderr); 6243e12c5d1SDavid du Colombier bclass(c); 6253e12c5d1SDavid du Colombier } 6263e12c5d1SDavid du Colombier putc('\n', stderr); 6273e12c5d1SDavid du Colombier ep = ebuf; 6283e12c5d1SDavid du Colombier } 6293e12c5d1SDavid du Colombier 6303e12c5d1SDavid du Colombier void bclass(int c) 6313e12c5d1SDavid du Colombier { 6323e12c5d1SDavid du Colombier switch (c) { 6333e12c5d1SDavid du Colombier case '{': bracecnt++; break; 6343e12c5d1SDavid du Colombier case '}': bracecnt--; break; 6353e12c5d1SDavid du Colombier case '[': brackcnt++; break; 6363e12c5d1SDavid du Colombier case ']': brackcnt--; break; 6373e12c5d1SDavid du Colombier case '(': parencnt++; break; 6383e12c5d1SDavid du Colombier case ')': parencnt--; break; 6393e12c5d1SDavid du Colombier } 6403e12c5d1SDavid du Colombier } 6413e12c5d1SDavid du Colombier 642*7dd7cddfSDavid du Colombier double errcheck(double x, char *s) 6433e12c5d1SDavid du Colombier { 6443e12c5d1SDavid du Colombier 6453e12c5d1SDavid du Colombier if (errno == EDOM) { 6463e12c5d1SDavid du Colombier errno = 0; 647*7dd7cddfSDavid du Colombier WARNING("%s argument out of domain", s); 6483e12c5d1SDavid du Colombier x = 1; 6493e12c5d1SDavid du Colombier } else if (errno == ERANGE) { 6503e12c5d1SDavid du Colombier errno = 0; 651*7dd7cddfSDavid du Colombier WARNING("%s result out of range", s); 6523e12c5d1SDavid du Colombier x = 1; 6533e12c5d1SDavid du Colombier } 6543e12c5d1SDavid du Colombier return x; 6553e12c5d1SDavid du Colombier } 6563e12c5d1SDavid du Colombier 657*7dd7cddfSDavid du Colombier int isclvar(char *s) /* is s of form var=something ? */ 6583e12c5d1SDavid du Colombier { 659*7dd7cddfSDavid du Colombier char *os = s; 6603e12c5d1SDavid du Colombier 6613e12c5d1SDavid du Colombier if (!isalpha(*s) && *s != '_') 6623e12c5d1SDavid du Colombier return 0; 6633e12c5d1SDavid du Colombier for ( ; *s; s++) 6643e12c5d1SDavid du Colombier if (!(isalnum(*s) || *s == '_')) 6653e12c5d1SDavid du Colombier break; 6663e12c5d1SDavid du Colombier return *s == '=' && s > os && *(s+1) != '='; 6673e12c5d1SDavid du Colombier } 6683e12c5d1SDavid du Colombier 669*7dd7cddfSDavid du Colombier /* strtod is supposed to be a proper test of what's a valid number */ 6703e12c5d1SDavid du Colombier 671*7dd7cddfSDavid du Colombier #include <math.h> 672*7dd7cddfSDavid du Colombier int is_number(char *s) 6733e12c5d1SDavid du Colombier { 674*7dd7cddfSDavid du Colombier double r; 675*7dd7cddfSDavid du Colombier char *ep; 676*7dd7cddfSDavid du Colombier errno = 0; 677*7dd7cddfSDavid du Colombier r = strtod(s, &ep); 678*7dd7cddfSDavid du Colombier if (ep == s || r == HUGE_VAL || errno == ERANGE) 679*7dd7cddfSDavid du Colombier return 0; 680*7dd7cddfSDavid du Colombier while (*ep == ' ' || *ep == '\t' || *ep == '\n') 681*7dd7cddfSDavid du Colombier ep++; 682*7dd7cddfSDavid du Colombier if (*ep == '\0') 683*7dd7cddfSDavid du Colombier return 1; 6843e12c5d1SDavid du Colombier else 685*7dd7cddfSDavid du Colombier return 0; 6863e12c5d1SDavid du Colombier } 687