1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 2.13 */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #define DEBUG 35*7c478bd9Sstevel@tonic-gate #include <stdio.h> 36*7c478bd9Sstevel@tonic-gate #include <ctype.h> 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate #include "awk.h" 39*7c478bd9Sstevel@tonic-gate #include "y.tab.h" 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #define FULLTAB 2 /* rehash when table gets this x full */ 42*7c478bd9Sstevel@tonic-gate #define GROWTAB 4 /* grow table by this factor */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate Array *symtab; /* main symbol table */ 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate uchar **FS; /* initial field sep */ 47*7c478bd9Sstevel@tonic-gate uchar **RS; /* initial record sep */ 48*7c478bd9Sstevel@tonic-gate uchar **OFS; /* output field sep */ 49*7c478bd9Sstevel@tonic-gate uchar **ORS; /* output record sep */ 50*7c478bd9Sstevel@tonic-gate uchar **OFMT; /* output format for numbers*/ 51*7c478bd9Sstevel@tonic-gate Awkfloat *NF; /* number of fields in current record */ 52*7c478bd9Sstevel@tonic-gate Awkfloat *NR; /* number of current record */ 53*7c478bd9Sstevel@tonic-gate Awkfloat *FNR; /* number of current record in current file */ 54*7c478bd9Sstevel@tonic-gate uchar **FILENAME; /* current filename argument */ 55*7c478bd9Sstevel@tonic-gate Awkfloat *ARGC; /* number of arguments from command line */ 56*7c478bd9Sstevel@tonic-gate uchar **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */ 57*7c478bd9Sstevel@tonic-gate Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */ 58*7c478bd9Sstevel@tonic-gate Awkfloat *RLENGTH; /* length of same */ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate Cell *recloc; /* location of record */ 61*7c478bd9Sstevel@tonic-gate Cell *nrloc; /* NR */ 62*7c478bd9Sstevel@tonic-gate Cell *nfloc; /* NF */ 63*7c478bd9Sstevel@tonic-gate Cell *fnrloc; /* FNR */ 64*7c478bd9Sstevel@tonic-gate Array *ARGVtab; /* symbol table containing ARGV[...] */ 65*7c478bd9Sstevel@tonic-gate Array *ENVtab; /* symbol table containing ENVIRON[...] */ 66*7c478bd9Sstevel@tonic-gate Cell *rstartloc; /* RSTART */ 67*7c478bd9Sstevel@tonic-gate Cell *rlengthloc; /* RLENGTH */ 68*7c478bd9Sstevel@tonic-gate Cell *symtabloc; /* SYMTAB */ 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate Cell *nullloc; 71*7c478bd9Sstevel@tonic-gate Node *nullnode; /* zero&null, converted into a node for comparisons */ 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate extern Node *valtonode(); 74*7c478bd9Sstevel@tonic-gate extern Cell fldtab[]; 75*7c478bd9Sstevel@tonic-gate extern uchar recdata[]; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate syminit() 78*7c478bd9Sstevel@tonic-gate { 79*7c478bd9Sstevel@tonic-gate int i; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate fldtab[0].ctype = OCELL; 82*7c478bd9Sstevel@tonic-gate fldtab[0].csub = CFLD; 83*7c478bd9Sstevel@tonic-gate fldtab[0].nval = (uchar*) "$0"; 84*7c478bd9Sstevel@tonic-gate fldtab[0].sval = recdata; 85*7c478bd9Sstevel@tonic-gate fldtab[0].fval = 0.0; 86*7c478bd9Sstevel@tonic-gate fldtab[0].tval = REC|STR|DONTFREE; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate for (i = 1; i < MAXFLD; i++) { 89*7c478bd9Sstevel@tonic-gate fldtab[i].ctype = OCELL; 90*7c478bd9Sstevel@tonic-gate fldtab[i].csub = CFLD; 91*7c478bd9Sstevel@tonic-gate fldtab[i].nval = NULL; 92*7c478bd9Sstevel@tonic-gate fldtab[i].sval = (uchar*) ""; 93*7c478bd9Sstevel@tonic-gate fldtab[i].fval = 0.0; 94*7c478bd9Sstevel@tonic-gate fldtab[i].tval = FLD|STR|DONTFREE; 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate symtab = makesymtab(NSYMTAB); 97*7c478bd9Sstevel@tonic-gate setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab); 98*7c478bd9Sstevel@tonic-gate /* this is used for if(x)... tests: */ 99*7c478bd9Sstevel@tonic-gate nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab); 100*7c478bd9Sstevel@tonic-gate nullnode = valtonode(nullloc, CCON); 101*7c478bd9Sstevel@tonic-gate /* recloc = setsymtab("$0", record, 0.0, REC|STR|DONTFREE, symtab); */ 102*7c478bd9Sstevel@tonic-gate recloc = &fldtab[0]; 103*7c478bd9Sstevel@tonic-gate FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval; 104*7c478bd9Sstevel@tonic-gate RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval; 105*7c478bd9Sstevel@tonic-gate OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval; 106*7c478bd9Sstevel@tonic-gate ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval; 107*7c478bd9Sstevel@tonic-gate OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; 108*7c478bd9Sstevel@tonic-gate FILENAME = &setsymtab("FILENAME", "-", 0.0, STR|DONTFREE, symtab)->sval; 109*7c478bd9Sstevel@tonic-gate nfloc = setsymtab("NF", "", 0.0, NUM, symtab); 110*7c478bd9Sstevel@tonic-gate NF = &nfloc->fval; 111*7c478bd9Sstevel@tonic-gate nrloc = setsymtab("NR", "", 0.0, NUM, symtab); 112*7c478bd9Sstevel@tonic-gate NR = &nrloc->fval; 113*7c478bd9Sstevel@tonic-gate fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab); 114*7c478bd9Sstevel@tonic-gate FNR = &fnrloc->fval; 115*7c478bd9Sstevel@tonic-gate SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval; 116*7c478bd9Sstevel@tonic-gate rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab); 117*7c478bd9Sstevel@tonic-gate RSTART = &rstartloc->fval; 118*7c478bd9Sstevel@tonic-gate rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab); 119*7c478bd9Sstevel@tonic-gate RLENGTH = &rlengthloc->fval; 120*7c478bd9Sstevel@tonic-gate symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab); 121*7c478bd9Sstevel@tonic-gate symtabloc->sval = (uchar *) symtab; 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate arginit(ac, av) 125*7c478bd9Sstevel@tonic-gate int ac; 126*7c478bd9Sstevel@tonic-gate uchar *av[]; 127*7c478bd9Sstevel@tonic-gate { 128*7c478bd9Sstevel@tonic-gate Cell *cp; 129*7c478bd9Sstevel@tonic-gate Array *makesymtab(); 130*7c478bd9Sstevel@tonic-gate int i; 131*7c478bd9Sstevel@tonic-gate uchar temp[5]; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate for (i = 1; i < ac; i++) /* first make FILENAME first real argument */ 134*7c478bd9Sstevel@tonic-gate if (!isclvar(av[i])) { 135*7c478bd9Sstevel@tonic-gate setsval(lookup("FILENAME", symtab), av[i]); 136*7c478bd9Sstevel@tonic-gate break; 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval; 139*7c478bd9Sstevel@tonic-gate cp = setsymtab("ARGV", "", 0.0, ARR, symtab); 140*7c478bd9Sstevel@tonic-gate ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */ 141*7c478bd9Sstevel@tonic-gate cp->sval = (uchar *) ARGVtab; 142*7c478bd9Sstevel@tonic-gate for (i = 0; i < ac; i++) { 143*7c478bd9Sstevel@tonic-gate sprintf((char *)temp, "%d", i); 144*7c478bd9Sstevel@tonic-gate if (isnumber(*av)) 145*7c478bd9Sstevel@tonic-gate setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab); 146*7c478bd9Sstevel@tonic-gate else 147*7c478bd9Sstevel@tonic-gate setsymtab(temp, *av, 0.0, STR, ARGVtab); 148*7c478bd9Sstevel@tonic-gate av++; 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate envinit(envp) 153*7c478bd9Sstevel@tonic-gate uchar *envp[]; 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate Cell *cp; 156*7c478bd9Sstevel@tonic-gate Array *makesymtab(); 157*7c478bd9Sstevel@tonic-gate uchar *p; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab); 160*7c478bd9Sstevel@tonic-gate ENVtab = makesymtab(NSYMTAB); 161*7c478bd9Sstevel@tonic-gate cp->sval = (uchar *) ENVtab; 162*7c478bd9Sstevel@tonic-gate for ( ; *envp; envp++) { 163*7c478bd9Sstevel@tonic-gate if ((p = (uchar *) strchr((char *) *envp, '=')) == NULL) /* index() on bsd */ 164*7c478bd9Sstevel@tonic-gate continue; 165*7c478bd9Sstevel@tonic-gate *p++ = 0; /* split into two strings at = */ 166*7c478bd9Sstevel@tonic-gate if (isnumber(p)) 167*7c478bd9Sstevel@tonic-gate setsymtab(*envp, p, atof(p), STR|NUM, ENVtab); 168*7c478bd9Sstevel@tonic-gate else 169*7c478bd9Sstevel@tonic-gate setsymtab(*envp, p, 0.0, STR, ENVtab); 170*7c478bd9Sstevel@tonic-gate p[-1] = '='; /* restore in case env is passed down to a shell */ 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate Array *makesymtab(n) 175*7c478bd9Sstevel@tonic-gate int n; 176*7c478bd9Sstevel@tonic-gate { 177*7c478bd9Sstevel@tonic-gate Array *ap; 178*7c478bd9Sstevel@tonic-gate Cell **tp; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate ap = (Array *) malloc(sizeof(Array)); 181*7c478bd9Sstevel@tonic-gate tp = (Cell **) calloc(n, sizeof(Cell *)); 182*7c478bd9Sstevel@tonic-gate if (ap == NULL || tp == NULL) 183*7c478bd9Sstevel@tonic-gate ERROR "out of space in makesymtab" FATAL; 184*7c478bd9Sstevel@tonic-gate ap->nelem = 0; 185*7c478bd9Sstevel@tonic-gate ap->size = n; 186*7c478bd9Sstevel@tonic-gate ap->tab = tp; 187*7c478bd9Sstevel@tonic-gate return(ap); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate freesymtab(ap) /* free symbol table */ 191*7c478bd9Sstevel@tonic-gate Cell *ap; 192*7c478bd9Sstevel@tonic-gate { 193*7c478bd9Sstevel@tonic-gate Cell *cp, *next; 194*7c478bd9Sstevel@tonic-gate Array *tp; 195*7c478bd9Sstevel@tonic-gate int i; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate if (!isarr(ap)) 198*7c478bd9Sstevel@tonic-gate return; 199*7c478bd9Sstevel@tonic-gate tp = (Array *) ap->sval; 200*7c478bd9Sstevel@tonic-gate if (tp == NULL) 201*7c478bd9Sstevel@tonic-gate return; 202*7c478bd9Sstevel@tonic-gate for (i = 0; i < tp->size; i++) { 203*7c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp != NULL; cp = next) { 204*7c478bd9Sstevel@tonic-gate next = cp->cnext; 205*7c478bd9Sstevel@tonic-gate xfree(cp->nval); 206*7c478bd9Sstevel@tonic-gate if (freeable(cp)) 207*7c478bd9Sstevel@tonic-gate xfree(cp->sval); 208*7c478bd9Sstevel@tonic-gate free(cp); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate free(tp->tab); 212*7c478bd9Sstevel@tonic-gate free(tp); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate freeelem(ap, s) /* free elem s from ap (i.e., ap["s"] */ 216*7c478bd9Sstevel@tonic-gate Cell *ap; 217*7c478bd9Sstevel@tonic-gate uchar *s; 218*7c478bd9Sstevel@tonic-gate { 219*7c478bd9Sstevel@tonic-gate Array *tp; 220*7c478bd9Sstevel@tonic-gate Cell *p, *prev = NULL; 221*7c478bd9Sstevel@tonic-gate int h; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate tp = (Array *) ap->sval; 224*7c478bd9Sstevel@tonic-gate h = hash(s, tp->size); 225*7c478bd9Sstevel@tonic-gate for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) 226*7c478bd9Sstevel@tonic-gate if (strcmp((char *) s, (char *) p->nval) == 0) { 227*7c478bd9Sstevel@tonic-gate if (prev == NULL) /* 1st one */ 228*7c478bd9Sstevel@tonic-gate tp->tab[h] = p->cnext; 229*7c478bd9Sstevel@tonic-gate else /* middle somewhere */ 230*7c478bd9Sstevel@tonic-gate prev->cnext = p->cnext; 231*7c478bd9Sstevel@tonic-gate if (freeable(p)) 232*7c478bd9Sstevel@tonic-gate xfree(p->sval); 233*7c478bd9Sstevel@tonic-gate free(p->nval); 234*7c478bd9Sstevel@tonic-gate free(p); 235*7c478bd9Sstevel@tonic-gate tp->nelem--; 236*7c478bd9Sstevel@tonic-gate return; 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate Cell *setsymtab(n, s, f, t, tp) 241*7c478bd9Sstevel@tonic-gate uchar *n, *s; 242*7c478bd9Sstevel@tonic-gate Awkfloat f; 243*7c478bd9Sstevel@tonic-gate unsigned t; 244*7c478bd9Sstevel@tonic-gate Array *tp; 245*7c478bd9Sstevel@tonic-gate { 246*7c478bd9Sstevel@tonic-gate register int h; 247*7c478bd9Sstevel@tonic-gate register Cell *p; 248*7c478bd9Sstevel@tonic-gate Cell *lookup(); 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate if (n != NULL && (p = lookup(n, tp)) != NULL) { 251*7c478bd9Sstevel@tonic-gate dprintf( ("setsymtab found %o: n=%s", p, p->nval) ); 252*7c478bd9Sstevel@tonic-gate dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) ); 253*7c478bd9Sstevel@tonic-gate return(p); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate p = (Cell *) malloc(sizeof(Cell)); 256*7c478bd9Sstevel@tonic-gate if (p == NULL) 257*7c478bd9Sstevel@tonic-gate ERROR "symbol table overflow at %s", n FATAL; 258*7c478bd9Sstevel@tonic-gate p->nval = tostring(n); 259*7c478bd9Sstevel@tonic-gate p->sval = s ? tostring(s) : tostring(""); 260*7c478bd9Sstevel@tonic-gate p->fval = f; 261*7c478bd9Sstevel@tonic-gate p->tval = t; 262*7c478bd9Sstevel@tonic-gate p->csub = 0; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate tp->nelem++; 265*7c478bd9Sstevel@tonic-gate if (tp->nelem > FULLTAB * tp->size) 266*7c478bd9Sstevel@tonic-gate rehash(tp); 267*7c478bd9Sstevel@tonic-gate h = hash(n, tp->size); 268*7c478bd9Sstevel@tonic-gate p->cnext = tp->tab[h]; 269*7c478bd9Sstevel@tonic-gate tp->tab[h] = p; 270*7c478bd9Sstevel@tonic-gate dprintf( ("setsymtab set %o: n=%s", p, p->nval) ); 271*7c478bd9Sstevel@tonic-gate dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) ); 272*7c478bd9Sstevel@tonic-gate return(p); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate hash(s, n) /* form hash value for string s */ 276*7c478bd9Sstevel@tonic-gate register uchar *s; 277*7c478bd9Sstevel@tonic-gate int n; 278*7c478bd9Sstevel@tonic-gate { 279*7c478bd9Sstevel@tonic-gate register unsigned hashval; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate for (hashval = 0; *s != '\0'; s++) 282*7c478bd9Sstevel@tonic-gate hashval = (*s + 31 * hashval); 283*7c478bd9Sstevel@tonic-gate return hashval % n; 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate rehash(tp) /* rehash items in small table into big one */ 287*7c478bd9Sstevel@tonic-gate Array *tp; 288*7c478bd9Sstevel@tonic-gate { 289*7c478bd9Sstevel@tonic-gate int i, nh, nsz; 290*7c478bd9Sstevel@tonic-gate Cell *cp, *op, **np; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate nsz = GROWTAB * tp->size; 293*7c478bd9Sstevel@tonic-gate np = (Cell **) calloc(nsz, sizeof(Cell *)); 294*7c478bd9Sstevel@tonic-gate if (np == NULL) 295*7c478bd9Sstevel@tonic-gate ERROR "out of space in rehash" FATAL; 296*7c478bd9Sstevel@tonic-gate for (i = 0; i < tp->size; i++) { 297*7c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp; cp = op) { 298*7c478bd9Sstevel@tonic-gate op = cp->cnext; 299*7c478bd9Sstevel@tonic-gate nh = hash(cp->nval, nsz); 300*7c478bd9Sstevel@tonic-gate cp->cnext = np[nh]; 301*7c478bd9Sstevel@tonic-gate np[nh] = cp; 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate free(tp->tab); 305*7c478bd9Sstevel@tonic-gate tp->tab = np; 306*7c478bd9Sstevel@tonic-gate tp->size = nsz; 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate Cell *lookup(s, tp) /* look for s in tp */ 310*7c478bd9Sstevel@tonic-gate register uchar *s; 311*7c478bd9Sstevel@tonic-gate Array *tp; 312*7c478bd9Sstevel@tonic-gate { 313*7c478bd9Sstevel@tonic-gate register Cell *p, *prev = NULL; 314*7c478bd9Sstevel@tonic-gate int h; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate h = hash(s, tp->size); 317*7c478bd9Sstevel@tonic-gate for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) 318*7c478bd9Sstevel@tonic-gate if (strcmp((char *) s, (char *) p->nval) == 0) 319*7c478bd9Sstevel@tonic-gate return(p); /* found it */ 320*7c478bd9Sstevel@tonic-gate return(NULL); /* not found */ 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate Awkfloat setfval(vp, f) 324*7c478bd9Sstevel@tonic-gate register Cell *vp; 325*7c478bd9Sstevel@tonic-gate Awkfloat f; 326*7c478bd9Sstevel@tonic-gate { 327*7c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0) 328*7c478bd9Sstevel@tonic-gate funnyvar(vp, "assign to"); 329*7c478bd9Sstevel@tonic-gate if (vp->tval & FLD) { 330*7c478bd9Sstevel@tonic-gate donerec = 0; /* mark $0 invalid */ 331*7c478bd9Sstevel@tonic-gate if (vp-fldtab > *NF) 332*7c478bd9Sstevel@tonic-gate newfld(vp-fldtab); 333*7c478bd9Sstevel@tonic-gate dprintf( ("setting field %d to %g\n", vp-fldtab, f) ); 334*7c478bd9Sstevel@tonic-gate } else if (vp->tval & REC) { 335*7c478bd9Sstevel@tonic-gate donefld = 0; /* mark $1... invalid */ 336*7c478bd9Sstevel@tonic-gate donerec = 1; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate vp->tval &= ~STR; /* mark string invalid */ 339*7c478bd9Sstevel@tonic-gate vp->tval |= NUM; /* mark number ok */ 340*7c478bd9Sstevel@tonic-gate dprintf( ("setfval %p: %s = %g, t=%o\n", vp, 341*7c478bd9Sstevel@tonic-gate vp->nval ? vp->nval : (unsigned char *)"NULL", 342*7c478bd9Sstevel@tonic-gate f, vp->tval) ); 343*7c478bd9Sstevel@tonic-gate return vp->fval = f; 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate funnyvar(vp, rw) 347*7c478bd9Sstevel@tonic-gate Cell *vp; 348*7c478bd9Sstevel@tonic-gate char *rw; 349*7c478bd9Sstevel@tonic-gate { 350*7c478bd9Sstevel@tonic-gate if (vp->tval & ARR) 351*7c478bd9Sstevel@tonic-gate ERROR "can't %s %s; it's an array name.", rw, vp->nval FATAL; 352*7c478bd9Sstevel@tonic-gate if (vp->tval & FCN) 353*7c478bd9Sstevel@tonic-gate ERROR "can't %s %s; it's a function.", rw, vp->nval FATAL; 354*7c478bd9Sstevel@tonic-gate ERROR "funny variable %o: n=%s s=\"%s\" f=%g t=%o", 355*7c478bd9Sstevel@tonic-gate vp, vp->nval, vp->sval, vp->fval, vp->tval); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate uchar *setsval(vp, s) 359*7c478bd9Sstevel@tonic-gate register Cell *vp; 360*7c478bd9Sstevel@tonic-gate uchar *s; 361*7c478bd9Sstevel@tonic-gate { 362*7c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0) 363*7c478bd9Sstevel@tonic-gate funnyvar(vp, "assign to"); 364*7c478bd9Sstevel@tonic-gate if (vp->tval & FLD) { 365*7c478bd9Sstevel@tonic-gate donerec = 0; /* mark $0 invalid */ 366*7c478bd9Sstevel@tonic-gate if (vp-fldtab > *NF) 367*7c478bd9Sstevel@tonic-gate newfld(vp-fldtab); 368*7c478bd9Sstevel@tonic-gate dprintf( ("setting field %d to %s\n", vp-fldtab, s) ); 369*7c478bd9Sstevel@tonic-gate } else if (vp->tval & REC) { 370*7c478bd9Sstevel@tonic-gate donefld = 0; /* mark $1... invalid */ 371*7c478bd9Sstevel@tonic-gate donerec = 1; 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate vp->tval &= ~NUM; 374*7c478bd9Sstevel@tonic-gate vp->tval |= STR; 375*7c478bd9Sstevel@tonic-gate if (freeable(vp)) 376*7c478bd9Sstevel@tonic-gate xfree(vp->sval); 377*7c478bd9Sstevel@tonic-gate vp->tval &= ~DONTFREE; 378*7c478bd9Sstevel@tonic-gate dprintf( ("setsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) ); 379*7c478bd9Sstevel@tonic-gate return(vp->sval = tostring(s)); 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate Awkfloat r_getfval(vp) 383*7c478bd9Sstevel@tonic-gate register Cell *vp; 384*7c478bd9Sstevel@tonic-gate { 385*7c478bd9Sstevel@tonic-gate /* if (vp->tval & ARR) 386*7c478bd9Sstevel@tonic-gate ERROR "illegal reference to array %s", vp->nval FATAL; 387*7c478bd9Sstevel@tonic-gate return 0.0; */ 388*7c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0) 389*7c478bd9Sstevel@tonic-gate funnyvar(vp, "read value of"); 390*7c478bd9Sstevel@tonic-gate if ((vp->tval & FLD) && donefld == 0) 391*7c478bd9Sstevel@tonic-gate fldbld(); 392*7c478bd9Sstevel@tonic-gate else if ((vp->tval & REC) && donerec == 0) 393*7c478bd9Sstevel@tonic-gate recbld(); 394*7c478bd9Sstevel@tonic-gate if (!isnum(vp)) { /* not a number */ 395*7c478bd9Sstevel@tonic-gate vp->fval = atof(vp->sval); /* best guess */ 396*7c478bd9Sstevel@tonic-gate if (isnumber(vp->sval) && !(vp->tval&CON)) 397*7c478bd9Sstevel@tonic-gate vp->tval |= NUM; /* make NUM only sparingly */ 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate dprintf( ("getfval %o: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) ); 400*7c478bd9Sstevel@tonic-gate return(vp->fval); 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate uchar *r_getsval(vp) 404*7c478bd9Sstevel@tonic-gate register Cell *vp; 405*7c478bd9Sstevel@tonic-gate { 406*7c478bd9Sstevel@tonic-gate uchar s[100]; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate /* if (vp->tval & ARR) 409*7c478bd9Sstevel@tonic-gate ERROR "illegal reference to array %s", vp->nval FATAL; 410*7c478bd9Sstevel@tonic-gate return ""; */ 411*7c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0) 412*7c478bd9Sstevel@tonic-gate funnyvar(vp, "read value of"); 413*7c478bd9Sstevel@tonic-gate if ((vp->tval & FLD) && donefld == 0) 414*7c478bd9Sstevel@tonic-gate fldbld(); 415*7c478bd9Sstevel@tonic-gate else if ((vp->tval & REC) && donerec == 0) 416*7c478bd9Sstevel@tonic-gate recbld(); 417*7c478bd9Sstevel@tonic-gate if ((vp->tval & STR) == 0) { 418*7c478bd9Sstevel@tonic-gate if (!(vp->tval&DONTFREE)) 419*7c478bd9Sstevel@tonic-gate xfree(vp->sval); 420*7c478bd9Sstevel@tonic-gate if ((long long)vp->fval == vp->fval) 421*7c478bd9Sstevel@tonic-gate sprintf((char *)s, "%.20g", vp->fval); 422*7c478bd9Sstevel@tonic-gate else 423*7c478bd9Sstevel@tonic-gate sprintf((char *)s, (char *)*OFMT, vp->fval); 424*7c478bd9Sstevel@tonic-gate vp->sval = tostring(s); 425*7c478bd9Sstevel@tonic-gate vp->tval &= ~DONTFREE; 426*7c478bd9Sstevel@tonic-gate vp->tval |= STR; 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate dprintf( ("getsval %p: %s = \"%s\", t=%o\n", vp, vp->nval, vp->sval, vp->tval) ); 429*7c478bd9Sstevel@tonic-gate return(vp->sval); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate uchar *tostring(s) 433*7c478bd9Sstevel@tonic-gate register uchar *s; 434*7c478bd9Sstevel@tonic-gate { 435*7c478bd9Sstevel@tonic-gate register uchar *p; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate p = (uchar *) malloc(strlen((char *) s)+1); 438*7c478bd9Sstevel@tonic-gate if (p == NULL) 439*7c478bd9Sstevel@tonic-gate ERROR "out of space in tostring on %s", s FATAL; 440*7c478bd9Sstevel@tonic-gate strcpy((char *) p, (char *) s); 441*7c478bd9Sstevel@tonic-gate return(p); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate uchar *qstring(s, delim) /* collect string up to delim */ 445*7c478bd9Sstevel@tonic-gate uchar *s; 446*7c478bd9Sstevel@tonic-gate int delim; 447*7c478bd9Sstevel@tonic-gate { 448*7c478bd9Sstevel@tonic-gate uchar *q; 449*7c478bd9Sstevel@tonic-gate int c, n; 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate for (q = cbuf; (c = *s) != delim; s++) { 452*7c478bd9Sstevel@tonic-gate if (q >= cbuf + RECSIZE - 1) 453*7c478bd9Sstevel@tonic-gate ERROR "string %.10s... too long", cbuf SYNTAX; 454*7c478bd9Sstevel@tonic-gate else if (c == '\n') 455*7c478bd9Sstevel@tonic-gate ERROR "newline in string %.10s...", cbuf SYNTAX; 456*7c478bd9Sstevel@tonic-gate else if (c != '\\') 457*7c478bd9Sstevel@tonic-gate *q++ = c; 458*7c478bd9Sstevel@tonic-gate else /* \something */ 459*7c478bd9Sstevel@tonic-gate switch (c = *++s) { 460*7c478bd9Sstevel@tonic-gate case '\\': *q++ = '\\'; break; 461*7c478bd9Sstevel@tonic-gate case 'n': *q++ = '\n'; break; 462*7c478bd9Sstevel@tonic-gate case 't': *q++ = '\t'; break; 463*7c478bd9Sstevel@tonic-gate case 'b': *q++ = '\b'; break; 464*7c478bd9Sstevel@tonic-gate case 'f': *q++ = '\f'; break; 465*7c478bd9Sstevel@tonic-gate case 'r': *q++ = '\r'; break; 466*7c478bd9Sstevel@tonic-gate default: 467*7c478bd9Sstevel@tonic-gate if (!isdigit(c)) { 468*7c478bd9Sstevel@tonic-gate *q++ = c; 469*7c478bd9Sstevel@tonic-gate break; 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate n = c - '0'; 472*7c478bd9Sstevel@tonic-gate if (isdigit(s[1])) { 473*7c478bd9Sstevel@tonic-gate n = 8 * n + *++s - '0'; 474*7c478bd9Sstevel@tonic-gate if (isdigit(s[1])) 475*7c478bd9Sstevel@tonic-gate n = 8 * n + *++s - '0'; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate *q++ = n; 478*7c478bd9Sstevel@tonic-gate break; 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate *q = '\0'; 482*7c478bd9Sstevel@tonic-gate return cbuf; 483*7c478bd9Sstevel@tonic-gate } 484