|
|
1.1 ! root 1: /* ! 2: Copyright (c) 1989 AT&T ! 3: All Rights Reserved ! 4: ! 5: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. ! 6: ! 7: The copyright notice above does not evidence any ! 8: actual or intended publication of such source code. ! 9: */ ! 10: ! 11: #define DEBUG ! 12: #include <stdio.h> ! 13: #include <math.h> ! 14: #include <ctype.h> ! 15: #include <string.h> ! 16: #include <stdlib.h> ! 17: #include "awk.h" ! 18: #include "y.tab.h" ! 19: ! 20: #define FULLTAB 2 /* rehash when table gets this x full */ ! 21: #define GROWTAB 4 /* grow table by this factor */ ! 22: ! 23: Array *symtab; /* main symbol table */ ! 24: ! 25: uchar **FS; /* initial field sep */ ! 26: uchar **RS; /* initial record sep */ ! 27: uchar **OFS; /* output field sep */ ! 28: uchar **ORS; /* output record sep */ ! 29: uchar **OFMT; /* output format for numbers*/ ! 30: Awkfloat *NF; /* number of fields in current record */ ! 31: Awkfloat *NR; /* number of current record */ ! 32: Awkfloat *FNR; /* number of current record in current file */ ! 33: uchar **FILENAME; /* current filename argument */ ! 34: Awkfloat *ARGC; /* number of arguments from command line */ ! 35: uchar **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */ ! 36: Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */ ! 37: Awkfloat *RLENGTH; /* length of same */ ! 38: ! 39: Cell *recloc; /* location of record */ ! 40: Cell *nrloc; /* NR */ ! 41: Cell *nfloc; /* NF */ ! 42: Cell *fnrloc; /* FNR */ ! 43: Array *ARGVtab; /* symbol table containing ARGV[...] */ ! 44: Array *ENVtab; /* symbol table containing ENVIRON[...] */ ! 45: Cell *rstartloc; /* RSTART */ ! 46: Cell *rlengthloc; /* RLENGTH */ ! 47: Cell *symtabloc; /* SYMTAB */ ! 48: ! 49: Cell *nullloc; ! 50: Node *nullnode; /* zero&null, converted into a node for comparisons */ ! 51: ! 52: extern Cell *fldtab; ! 53: ! 54: void syminit(void) ! 55: { ! 56: /* symtab = makesymtab(NSYMTAB); */ ! 57: setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab); ! 58: /* this is used for if(x)... tests: */ ! 59: nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab); ! 60: nullnode = valtonode(nullloc, CCON); ! 61: /* recloc = setsymtab("$0", record, 0.0, REC|STR|DONTFREE, symtab); */ ! 62: recloc = &fldtab[0]; ! 63: FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval; ! 64: RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval; ! 65: OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval; ! 66: ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval; ! 67: OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; ! 68: FILENAME = &setsymtab("FILENAME", "-", 0.0, STR|DONTFREE, symtab)->sval; ! 69: nfloc = setsymtab("NF", "", 0.0, NUM, symtab); ! 70: NF = &nfloc->fval; ! 71: nrloc = setsymtab("NR", "", 0.0, NUM, symtab); ! 72: NR = &nrloc->fval; ! 73: fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab); ! 74: FNR = &fnrloc->fval; ! 75: SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval; ! 76: rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab); ! 77: RSTART = &rstartloc->fval; ! 78: rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab); ! 79: RLENGTH = &rlengthloc->fval; ! 80: symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab); ! 81: symtabloc->sval = (uchar *) symtab; ! 82: } ! 83: ! 84: void arginit(int ac, uchar *av[]) ! 85: { ! 86: Cell *cp; ! 87: int i; ! 88: uchar temp[5]; ! 89: ! 90: for (i = 1; i < ac; i++) /* first make FILENAME first real argument */ ! 91: if (!isclvar(av[i])) { ! 92: setsval(lookup("FILENAME", symtab), av[i]); ! 93: break; ! 94: } ! 95: ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval; ! 96: cp = setsymtab("ARGV", "", 0.0, ARR, symtab); ! 97: ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */ ! 98: cp->sval = (uchar *) ARGVtab; ! 99: for (i = 0; i < ac; i++) { ! 100: sprintf((char *)temp, "%d", i); ! 101: if (isnumber(*av)) ! 102: setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab); ! 103: else ! 104: setsymtab(temp, *av, 0.0, STR, ARGVtab); ! 105: av++; ! 106: } ! 107: } ! 108: ! 109: void envinit(uchar **envp) ! 110: { ! 111: Cell *cp; ! 112: uchar *p; ! 113: ! 114: cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab); ! 115: ENVtab = makesymtab(NSYMTAB); ! 116: cp->sval = (uchar *) ENVtab; ! 117: for ( ; *envp; envp++) { ! 118: if ((p = (uchar *) strchr((char *) *envp, '=')) == NULL) /* index() on bsd */ ! 119: continue; ! 120: *p++ = 0; /* split into two strings at = */ ! 121: if (isnumber(p)) ! 122: setsymtab(*envp, p, atof(p), STR|NUM, ENVtab); ! 123: else ! 124: setsymtab(*envp, p, 0.0, STR, ENVtab); ! 125: p[-1] = '='; /* restore in case env is passed down to a shell */ ! 126: } ! 127: } ! 128: ! 129: Array *makesymtab(int n) ! 130: { ! 131: Array *ap; ! 132: Cell **tp; ! 133: ! 134: ap = (Array *) malloc(sizeof(Array)); ! 135: tp = (Cell **) calloc(n, sizeof(Cell *)); ! 136: if (ap == NULL || tp == NULL) ! 137: ERROR "out of space in makesymtab" FATAL; ! 138: ap->nelem = 0; ! 139: ap->size = n; ! 140: ap->tab = tp; ! 141: return(ap); ! 142: } ! 143: ! 144: void freesymtab(Cell *ap) /* free symbol table */ ! 145: { ! 146: Cell *cp, *temp; ! 147: Array *tp; ! 148: int i; ! 149: ! 150: if (!isarr(ap)) ! 151: return; ! 152: tp = (Array *) ap->sval; ! 153: if (tp == NULL) ! 154: return; ! 155: for (i = 0; i < tp->size; i++) { ! 156: for (cp = tp->tab[i]; cp != NULL; cp = temp) { ! 157: xfree(cp->nval); ! 158: if (freeable(cp)) ! 159: xfree(cp->sval); ! 160: temp = cp->cnext; /* avoids freeing then using */ ! 161: free((char *) cp); ! 162: } ! 163: } ! 164: free((char *) (tp->tab)); ! 165: free((char *) tp); ! 166: } ! 167: ! 168: void freeelem(Cell *ap, uchar *s) /* free elem s from ap (i.e., ap["s"] */ ! 169: { ! 170: Array *tp; ! 171: Cell *p, *prev = NULL; ! 172: int h; ! 173: ! 174: tp = (Array *) ap->sval; ! 175: h = hash(s, tp->size); ! 176: for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) ! 177: if (strcmp((char *) s, (char *) p->nval) == 0) { ! 178: if (prev == NULL) /* 1st one */ ! 179: tp->tab[h] = p->cnext; ! 180: else /* middle somewhere */ ! 181: prev->cnext = p->cnext; ! 182: if (freeable(p)) ! 183: xfree(p->sval); ! 184: free(p->nval); ! 185: free((char *) p); ! 186: tp->nelem--; ! 187: return; ! 188: } ! 189: } ! 190: ! 191: Cell *setsymtab(uchar *n, uchar *s, Awkfloat f, unsigned t, Array *tp) ! 192: { ! 193: register int h; ! 194: register Cell *p; ! 195: ! 196: if (n != NULL && (p = lookup(n, tp)) != NULL) { ! 197: dprintf( ("setsymtab found %o: n=%s", p, p->nval) ); ! 198: dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) ); ! 199: return(p); ! 200: } ! 201: p = (Cell *) malloc(sizeof(Cell)); ! 202: if (p == NULL) ! 203: ERROR "out of space for symbol table at %s", n FATAL; ! 204: p->nval = tostring(n); ! 205: p->sval = s ? tostring(s) : tostring(""); ! 206: p->fval = f; ! 207: p->tval = t; ! 208: tp->nelem++; ! 209: if (tp->nelem > FULLTAB * tp->size) ! 210: rehash(tp); ! 211: h = hash(n, tp->size); ! 212: p->cnext = tp->tab[h]; ! 213: tp->tab[h] = p; ! 214: dprintf( ("setsymtab set %o: n=%s", p, p->nval) ); ! 215: dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) ); ! 216: return(p); ! 217: } ! 218: ! 219: hash(uchar *s, int n) /* form hash value for string s */ ! 220: { ! 221: register unsigned hashval; ! 222: ! 223: for (hashval = 0; *s != '\0'; s++) ! 224: hashval = (*s + 31 * hashval); ! 225: return hashval % n; ! 226: } ! 227: ! 228: void rehash(Array *tp) /* rehash items in small table into big one */ ! 229: { ! 230: int i, nh, nsz; ! 231: Cell *cp, *op, **np; ! 232: ! 233: nsz = GROWTAB * tp->size; ! 234: np = (Cell **) calloc(nsz, sizeof(Cell *)); ! 235: if (np == NULL) /* can't do it, but can keep running. */ ! 236: return; /* someone else will run out later. */ ! 237: for (i = 0; i < tp->size; i++) { ! 238: for (cp = tp->tab[i]; cp; cp = op) { ! 239: op = cp->cnext; ! 240: nh = hash(cp->nval, nsz); ! 241: cp->cnext = np[nh]; ! 242: np[nh] = cp; ! 243: } ! 244: } ! 245: free((char *) (tp->tab)); ! 246: tp->tab = np; ! 247: tp->size = nsz; ! 248: } ! 249: ! 250: Cell *lookup(uchar *s, Array *tp) /* look for s in tp */ ! 251: { ! 252: register Cell *p, *prev = NULL; ! 253: int h; ! 254: ! 255: h = hash(s, tp->size); ! 256: for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) ! 257: if (strcmp((char *) s, (char *) p->nval) == 0) ! 258: return(p); /* found it */ ! 259: return(NULL); /* not found */ ! 260: } ! 261: ! 262: Awkfloat setfval(Cell *vp, Awkfloat f) ! 263: { ! 264: if ((vp->tval & (NUM | STR)) == 0) ! 265: funnyvar(vp, "assign to"); ! 266: if (vp->tval & FLD) { ! 267: donerec = 0; /* mark $0 invalid */ ! 268: if (vp-fldtab > *NF) ! 269: newfld(vp-fldtab); ! 270: dprintf( ("setting field %d to %g\n", vp-fldtab, f) ); ! 271: } else if (vp->tval & REC) { ! 272: donefld = 0; /* mark $1... invalid */ ! 273: donerec = 1; ! 274: } ! 275: vp->tval &= ~STR; /* mark string invalid */ ! 276: vp->tval |= NUM; /* mark number ok */ ! 277: dprintf( ("setfval %o: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) ); ! 278: return vp->fval = f; ! 279: } ! 280: ! 281: void funnyvar(Cell *vp, char *rw) ! 282: { ! 283: if (vp->tval & ARR) ! 284: ERROR "can't %s %s; it's an array name.", rw, vp->nval FATAL; ! 285: if (vp->tval & FCN) ! 286: ERROR "can't %s %s; it's a function.", rw, vp->nval FATAL; ! 287: ERROR "funny variable %o: n=%s s=\"%s\" f=%g t=%o", ! 288: vp, vp->nval, vp->sval, vp->fval, vp->tval WARNING; ! 289: } ! 290: ! 291: uchar *setsval(Cell *vp, uchar *s) ! 292: { ! 293: if ((vp->tval & (NUM | STR)) == 0) ! 294: funnyvar(vp, "assign to"); ! 295: if (vp->tval & FLD) { ! 296: donerec = 0; /* mark $0 invalid */ ! 297: if (vp-fldtab > *NF) ! 298: newfld(vp-fldtab); ! 299: dprintf( ("setting field %d to %s\n", vp-fldtab, s) ); ! 300: } else if (vp->tval & REC) { ! 301: donefld = 0; /* mark $1... invalid */ ! 302: donerec = 1; ! 303: } ! 304: vp->tval &= ~NUM; ! 305: vp->tval |= STR; ! 306: if (freeable(vp)) ! 307: xfree(vp->sval); ! 308: vp->tval &= ~DONTFREE; ! 309: dprintf( ("setsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) ); ! 310: return(vp->sval = tostring(s)); ! 311: } ! 312: ! 313: Awkfloat r_getfval(Cell *vp) ! 314: { ! 315: /* if (vp->tval & ARR) ! 316: ERROR "illegal reference to array %s", vp->nval FATAL; ! 317: return 0.0; */ ! 318: if ((vp->tval & (NUM | STR)) == 0) ! 319: funnyvar(vp, "read value of"); ! 320: if ((vp->tval & FLD) && donefld == 0) ! 321: fldbld(); ! 322: else if ((vp->tval & REC) && donerec == 0) ! 323: recbld(); ! 324: if (!isnum(vp)) { /* not a number */ ! 325: vp->fval = atof(vp->sval); /* best guess */ ! 326: if (isnumber(vp->sval) && !(vp->tval&CON)) ! 327: vp->tval |= NUM; /* make NUM only sparingly */ ! 328: } ! 329: dprintf( ("getfval %o: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) ); ! 330: return(vp->fval); ! 331: } ! 332: ! 333: uchar *r_getsval(Cell *vp) ! 334: { ! 335: uchar s[100]; ! 336: double dtemp; ! 337: ! 338: /* if (vp->tval & ARR) ! 339: ERROR "illegal reference to array %s", vp->nval FATAL; ! 340: return ""; */ ! 341: if ((vp->tval & (NUM | STR)) == 0) ! 342: funnyvar(vp, "read value of"); ! 343: if ((vp->tval & FLD) && donefld == 0) ! 344: fldbld(); ! 345: else if ((vp->tval & REC) && donerec == 0) ! 346: recbld(); ! 347: if ((vp->tval & STR) == 0) { ! 348: if (!(vp->tval&DONTFREE)) ! 349: xfree(vp->sval); ! 350: if (modf(vp->fval, &dtemp) == 0) /* it's integral */ ! 351: sprintf((char *)s, "%.20g", vp->fval); ! 352: else ! 353: sprintf((char *)s, (char *)*OFMT, vp->fval); ! 354: vp->sval = tostring(s); ! 355: vp->tval &= ~DONTFREE; ! 356: vp->tval |= STR; ! 357: } ! 358: dprintf( ("getsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, vp->sval, vp->tval) ); ! 359: return(vp->sval); ! 360: } ! 361: ! 362: uchar *tostring(uchar *s) ! 363: { ! 364: register uchar *p; ! 365: ! 366: p = (uchar *) malloc(strlen((char *) s)+1); ! 367: if (p == NULL) ! 368: ERROR "out of space in tostring on %s", s FATAL; ! 369: strcpy((char *) p, (char *) s); ! 370: return(p); ! 371: } ! 372: ! 373: uchar *qstring(uchar *s, int delim) /* collect string up to delim */ ! 374: { ! 375: uchar *q; ! 376: int c, n; ! 377: ! 378: for (q = cbuf; (c = *s) != delim; s++) { ! 379: if (q >= cbuf + CBUFLEN - 1) ! 380: ERROR "string %.10s... too long", cbuf SYNTAX; ! 381: else if (c == '\n') ! 382: ERROR "newline in string %.10s...", cbuf SYNTAX; ! 383: else if (c != '\\') ! 384: *q++ = c; ! 385: else /* \something */ ! 386: switch (c = *++s) { ! 387: case '\\': *q++ = '\\'; break; ! 388: case 'n': *q++ = '\n'; break; ! 389: case 't': *q++ = '\t'; break; ! 390: case 'b': *q++ = '\b'; break; ! 391: case 'f': *q++ = '\f'; break; ! 392: case 'r': *q++ = '\r'; break; ! 393: default: ! 394: if (!isdigit(c)) { ! 395: *q++ = c; ! 396: break; ! 397: } ! 398: n = c - '0'; ! 399: if (isdigit(s[1])) { ! 400: n = 8 * n + *++s - '0'; ! 401: if (isdigit(s[1])) ! 402: n = 8 * n + *++s - '0'; ! 403: } ! 404: *q++ = n; ! 405: break; ! 406: } ! 407: } ! 408: *q = '\0'; ! 409: return cbuf; ! 410: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.