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