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