12a55deb1SDavid E. O'Brien /**************************************************************** 22a55deb1SDavid E. O'Brien Copyright (C) Lucent Technologies 1997 32a55deb1SDavid E. O'Brien All Rights Reserved 42a55deb1SDavid E. O'Brien 52a55deb1SDavid E. O'Brien Permission to use, copy, modify, and distribute this software and 62a55deb1SDavid E. O'Brien its documentation for any purpose and without fee is hereby 72a55deb1SDavid E. O'Brien granted, provided that the above copyright notice appear in all 82a55deb1SDavid E. O'Brien copies and that both that the copyright notice and this 92a55deb1SDavid E. O'Brien permission notice and warranty disclaimer appear in supporting 102a55deb1SDavid E. O'Brien documentation, and that the name Lucent Technologies or any of 112a55deb1SDavid E. O'Brien its entities not be used in advertising or publicity pertaining 122a55deb1SDavid E. O'Brien to distribution of the software without specific, written prior 132a55deb1SDavid E. O'Brien permission. 142a55deb1SDavid E. O'Brien 152a55deb1SDavid E. O'Brien LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 162a55deb1SDavid E. O'Brien INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 172a55deb1SDavid E. O'Brien IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 182a55deb1SDavid E. O'Brien SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 192a55deb1SDavid E. O'Brien WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 202a55deb1SDavid E. O'Brien IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 212a55deb1SDavid E. O'Brien ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 222a55deb1SDavid E. O'Brien THIS SOFTWARE. 232a55deb1SDavid E. O'Brien ****************************************************************/ 242a55deb1SDavid E. O'Brien 252a55deb1SDavid E. O'Brien #define DEBUG 262a55deb1SDavid E. O'Brien #include <stdio.h> 272a55deb1SDavid E. O'Brien #include <math.h> 282a55deb1SDavid E. O'Brien #include <ctype.h> 292a55deb1SDavid E. O'Brien #include <string.h> 302a55deb1SDavid E. O'Brien #include <stdlib.h> 312a55deb1SDavid E. O'Brien #include "awk.h" 322a55deb1SDavid E. O'Brien #include "ytab.h" 332a55deb1SDavid E. O'Brien 342a55deb1SDavid E. O'Brien #define FULLTAB 2 /* rehash when table gets this x full */ 352a55deb1SDavid E. O'Brien #define GROWTAB 4 /* grow table by this factor */ 362a55deb1SDavid E. O'Brien 372a55deb1SDavid E. O'Brien Array *symtab; /* main symbol table */ 382a55deb1SDavid E. O'Brien 392a55deb1SDavid E. O'Brien char **FS; /* initial field sep */ 402a55deb1SDavid E. O'Brien char **RS; /* initial record sep */ 412a55deb1SDavid E. O'Brien char **OFS; /* output field sep */ 422a55deb1SDavid E. O'Brien char **ORS; /* output record sep */ 432a55deb1SDavid E. O'Brien char **OFMT; /* output format for numbers */ 442a55deb1SDavid E. O'Brien char **CONVFMT; /* format for conversions in getsval */ 452a55deb1SDavid E. O'Brien Awkfloat *NF; /* number of fields in current record */ 462a55deb1SDavid E. O'Brien Awkfloat *NR; /* number of current record */ 472a55deb1SDavid E. O'Brien Awkfloat *FNR; /* number of current record in current file */ 482a55deb1SDavid E. O'Brien char **FILENAME; /* current filename argument */ 492a55deb1SDavid E. O'Brien Awkfloat *ARGC; /* number of arguments from command line */ 502a55deb1SDavid E. O'Brien char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */ 512a55deb1SDavid E. O'Brien Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */ 522a55deb1SDavid E. O'Brien Awkfloat *RLENGTH; /* length of same */ 532a55deb1SDavid E. O'Brien 54c263f9bfSRuslan Ermilov Cell *fsloc; /* FS */ 552a55deb1SDavid E. O'Brien Cell *nrloc; /* NR */ 562a55deb1SDavid E. O'Brien Cell *nfloc; /* NF */ 572a55deb1SDavid E. O'Brien Cell *fnrloc; /* FNR */ 582a55deb1SDavid E. O'Brien Array *ARGVtab; /* symbol table containing ARGV[...] */ 592a55deb1SDavid E. O'Brien Array *ENVtab; /* symbol table containing ENVIRON[...] */ 602a55deb1SDavid E. O'Brien Cell *rstartloc; /* RSTART */ 612a55deb1SDavid E. O'Brien Cell *rlengthloc; /* RLENGTH */ 622a55deb1SDavid E. O'Brien Cell *symtabloc; /* SYMTAB */ 632a55deb1SDavid E. O'Brien 642a55deb1SDavid E. O'Brien Cell *nullloc; /* a guaranteed empty cell */ 652a55deb1SDavid E. O'Brien Node *nullnode; /* zero&null, converted into a node for comparisons */ 662a55deb1SDavid E. O'Brien Cell *literal0; 672a55deb1SDavid E. O'Brien 682a55deb1SDavid E. O'Brien extern Cell **fldtab; 692a55deb1SDavid E. O'Brien 702a55deb1SDavid E. O'Brien void syminit(void) /* initialize symbol table with builtin vars */ 712a55deb1SDavid E. O'Brien { 722a55deb1SDavid E. O'Brien literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab); 732a55deb1SDavid E. O'Brien /* this is used for if(x)... tests: */ 742a55deb1SDavid E. O'Brien nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab); 752a55deb1SDavid E. O'Brien nullnode = celltonode(nullloc, CCON); 762a55deb1SDavid E. O'Brien 77c263f9bfSRuslan Ermilov fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab); 78c263f9bfSRuslan Ermilov FS = &fsloc->sval; 792a55deb1SDavid E. O'Brien RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval; 802a55deb1SDavid E. O'Brien OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval; 812a55deb1SDavid E. O'Brien ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval; 822a55deb1SDavid E. O'Brien OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; 832a55deb1SDavid E. O'Brien CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; 842a55deb1SDavid E. O'Brien FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval; 852a55deb1SDavid E. O'Brien nfloc = setsymtab("NF", "", 0.0, NUM, symtab); 862a55deb1SDavid E. O'Brien NF = &nfloc->fval; 872a55deb1SDavid E. O'Brien nrloc = setsymtab("NR", "", 0.0, NUM, symtab); 882a55deb1SDavid E. O'Brien NR = &nrloc->fval; 892a55deb1SDavid E. O'Brien fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab); 902a55deb1SDavid E. O'Brien FNR = &fnrloc->fval; 912a55deb1SDavid E. O'Brien SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval; 922a55deb1SDavid E. O'Brien rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab); 932a55deb1SDavid E. O'Brien RSTART = &rstartloc->fval; 942a55deb1SDavid E. O'Brien rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab); 952a55deb1SDavid E. O'Brien RLENGTH = &rlengthloc->fval; 962a55deb1SDavid E. O'Brien symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab); 972a55deb1SDavid E. O'Brien symtabloc->sval = (char *) symtab; 982a55deb1SDavid E. O'Brien } 992a55deb1SDavid E. O'Brien 1002a55deb1SDavid E. O'Brien void arginit(int ac, char **av) /* set up ARGV and ARGC */ 1012a55deb1SDavid E. O'Brien { 1022a55deb1SDavid E. O'Brien Cell *cp; 1032a55deb1SDavid E. O'Brien int i; 1042a55deb1SDavid E. O'Brien char temp[50]; 1052a55deb1SDavid E. O'Brien 1062a55deb1SDavid E. O'Brien ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval; 1072a55deb1SDavid E. O'Brien cp = setsymtab("ARGV", "", 0.0, ARR, symtab); 1082a55deb1SDavid E. O'Brien ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */ 1092a55deb1SDavid E. O'Brien cp->sval = (char *) ARGVtab; 1102a55deb1SDavid E. O'Brien for (i = 0; i < ac; i++) { 1112a55deb1SDavid E. O'Brien sprintf(temp, "%d", i); 1122a55deb1SDavid E. O'Brien if (is_number(*av)) 1132a55deb1SDavid E. O'Brien setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab); 1142a55deb1SDavid E. O'Brien else 1152a55deb1SDavid E. O'Brien setsymtab(temp, *av, 0.0, STR, ARGVtab); 1162a55deb1SDavid E. O'Brien av++; 1172a55deb1SDavid E. O'Brien } 1182a55deb1SDavid E. O'Brien } 1192a55deb1SDavid E. O'Brien 1202a55deb1SDavid E. O'Brien void envinit(char **envp) /* set up ENVIRON variable */ 1212a55deb1SDavid E. O'Brien { 1222a55deb1SDavid E. O'Brien Cell *cp; 1232a55deb1SDavid E. O'Brien char *p; 1242a55deb1SDavid E. O'Brien 1252a55deb1SDavid E. O'Brien cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab); 1262a55deb1SDavid E. O'Brien ENVtab = makesymtab(NSYMTAB); 1272a55deb1SDavid E. O'Brien cp->sval = (char *) ENVtab; 1282a55deb1SDavid E. O'Brien for ( ; *envp; envp++) { 1292a55deb1SDavid E. O'Brien if ((p = strchr(*envp, '=')) == NULL) 1302a55deb1SDavid E. O'Brien continue; 1312a55deb1SDavid E. O'Brien if( p == *envp ) /* no left hand side name in env string */ 1322a55deb1SDavid E. O'Brien continue; 1332a55deb1SDavid E. O'Brien *p++ = 0; /* split into two strings at = */ 1342a55deb1SDavid E. O'Brien if (is_number(p)) 1352a55deb1SDavid E. O'Brien setsymtab(*envp, p, atof(p), STR|NUM, ENVtab); 1362a55deb1SDavid E. O'Brien else 1372a55deb1SDavid E. O'Brien setsymtab(*envp, p, 0.0, STR, ENVtab); 1382a55deb1SDavid E. O'Brien p[-1] = '='; /* restore in case env is passed down to a shell */ 1392a55deb1SDavid E. O'Brien } 1402a55deb1SDavid E. O'Brien } 1412a55deb1SDavid E. O'Brien 1422a55deb1SDavid E. O'Brien Array *makesymtab(int n) /* make a new symbol table */ 1432a55deb1SDavid E. O'Brien { 1442a55deb1SDavid E. O'Brien Array *ap; 1452a55deb1SDavid E. O'Brien Cell **tp; 1462a55deb1SDavid E. O'Brien 1472a55deb1SDavid E. O'Brien ap = (Array *) malloc(sizeof(Array)); 1482a55deb1SDavid E. O'Brien tp = (Cell **) calloc(n, sizeof(Cell *)); 1492a55deb1SDavid E. O'Brien if (ap == NULL || tp == NULL) 1502a55deb1SDavid E. O'Brien FATAL("out of space in makesymtab"); 1512a55deb1SDavid E. O'Brien ap->nelem = 0; 1522a55deb1SDavid E. O'Brien ap->size = n; 1532a55deb1SDavid E. O'Brien ap->tab = tp; 1542a55deb1SDavid E. O'Brien return(ap); 1552a55deb1SDavid E. O'Brien } 1562a55deb1SDavid E. O'Brien 1572a55deb1SDavid E. O'Brien void freesymtab(Cell *ap) /* free a symbol table */ 1582a55deb1SDavid E. O'Brien { 1592a55deb1SDavid E. O'Brien Cell *cp, *temp; 1602a55deb1SDavid E. O'Brien Array *tp; 1612a55deb1SDavid E. O'Brien int i; 1622a55deb1SDavid E. O'Brien 1632a55deb1SDavid E. O'Brien if (!isarr(ap)) 1642a55deb1SDavid E. O'Brien return; 1652a55deb1SDavid E. O'Brien tp = (Array *) ap->sval; 1662a55deb1SDavid E. O'Brien if (tp == NULL) 1672a55deb1SDavid E. O'Brien return; 1682a55deb1SDavid E. O'Brien for (i = 0; i < tp->size; i++) { 1692a55deb1SDavid E. O'Brien for (cp = tp->tab[i]; cp != NULL; cp = temp) { 1702a55deb1SDavid E. O'Brien xfree(cp->nval); 1712a55deb1SDavid E. O'Brien if (freeable(cp)) 1722a55deb1SDavid E. O'Brien xfree(cp->sval); 1732a55deb1SDavid E. O'Brien temp = cp->cnext; /* avoids freeing then using */ 1742a55deb1SDavid E. O'Brien free(cp); 175007c6572SDag-Erling Smørgrav tp->nelem--; 1762a55deb1SDavid E. O'Brien } 1772a55deb1SDavid E. O'Brien tp->tab[i] = 0; 1782a55deb1SDavid E. O'Brien } 179007c6572SDag-Erling Smørgrav if (tp->nelem != 0) 180007c6572SDag-Erling Smørgrav WARNING("can't happen: inconsistent element count freeing %s", ap->nval); 1812a55deb1SDavid E. O'Brien free(tp->tab); 1822a55deb1SDavid E. O'Brien free(tp); 1832a55deb1SDavid E. O'Brien } 1842a55deb1SDavid E. O'Brien 185813da98dSDavid E. O'Brien void freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */ 1862a55deb1SDavid E. O'Brien { 1872a55deb1SDavid E. O'Brien Array *tp; 1882a55deb1SDavid E. O'Brien Cell *p, *prev = NULL; 1892a55deb1SDavid E. O'Brien int h; 1902a55deb1SDavid E. O'Brien 1912a55deb1SDavid E. O'Brien tp = (Array *) ap->sval; 1922a55deb1SDavid E. O'Brien h = hash(s, tp->size); 1932a55deb1SDavid E. O'Brien for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) 1942a55deb1SDavid E. O'Brien if (strcmp(s, p->nval) == 0) { 1952a55deb1SDavid E. O'Brien if (prev == NULL) /* 1st one */ 1962a55deb1SDavid E. O'Brien tp->tab[h] = p->cnext; 1972a55deb1SDavid E. O'Brien else /* middle somewhere */ 1982a55deb1SDavid E. O'Brien prev->cnext = p->cnext; 1992a55deb1SDavid E. O'Brien if (freeable(p)) 2002a55deb1SDavid E. O'Brien xfree(p->sval); 2012a55deb1SDavid E. O'Brien free(p->nval); 2022a55deb1SDavid E. O'Brien free(p); 2032a55deb1SDavid E. O'Brien tp->nelem--; 2042a55deb1SDavid E. O'Brien return; 2052a55deb1SDavid E. O'Brien } 2062a55deb1SDavid E. O'Brien } 2072a55deb1SDavid E. O'Brien 208813da98dSDavid E. O'Brien Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp) 2092a55deb1SDavid E. O'Brien { 2102a55deb1SDavid E. O'Brien int h; 2112a55deb1SDavid E. O'Brien Cell *p; 2122a55deb1SDavid E. O'Brien 2132a55deb1SDavid E. O'Brien if (n != NULL && (p = lookup(n, tp)) != NULL) { 2142a55deb1SDavid E. O'Brien dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n", 215d86a0988SRuslan Ermilov (void*)p, NN(p->nval), NN(p->sval), p->fval, p->tval) ); 2162a55deb1SDavid E. O'Brien return(p); 2172a55deb1SDavid E. O'Brien } 2182a55deb1SDavid E. O'Brien p = (Cell *) malloc(sizeof(Cell)); 2192a55deb1SDavid E. O'Brien if (p == NULL) 2202a55deb1SDavid E. O'Brien FATAL("out of space for symbol table at %s", n); 2212a55deb1SDavid E. O'Brien p->nval = tostring(n); 2222a55deb1SDavid E. O'Brien p->sval = s ? tostring(s) : tostring(""); 2232a55deb1SDavid E. O'Brien p->fval = f; 2242a55deb1SDavid E. O'Brien p->tval = t; 2252a55deb1SDavid E. O'Brien p->csub = CUNK; 2262a55deb1SDavid E. O'Brien p->ctype = OCELL; 2272a55deb1SDavid E. O'Brien tp->nelem++; 2282a55deb1SDavid E. O'Brien if (tp->nelem > FULLTAB * tp->size) 2292a55deb1SDavid E. O'Brien rehash(tp); 2302a55deb1SDavid E. O'Brien h = hash(n, tp->size); 2312a55deb1SDavid E. O'Brien p->cnext = tp->tab[h]; 2322a55deb1SDavid E. O'Brien tp->tab[h] = p; 2332a55deb1SDavid E. O'Brien dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n", 234d86a0988SRuslan Ermilov (void*)p, p->nval, p->sval, p->fval, p->tval) ); 2352a55deb1SDavid E. O'Brien return(p); 2362a55deb1SDavid E. O'Brien } 2372a55deb1SDavid E. O'Brien 238813da98dSDavid E. O'Brien int hash(const char *s, int n) /* form hash value for string s */ 2392a55deb1SDavid E. O'Brien { 2402a55deb1SDavid E. O'Brien unsigned hashval; 2412a55deb1SDavid E. O'Brien 2422a55deb1SDavid E. O'Brien for (hashval = 0; *s != '\0'; s++) 2432a55deb1SDavid E. O'Brien hashval = (*s + 31 * hashval); 2442a55deb1SDavid E. O'Brien return hashval % n; 2452a55deb1SDavid E. O'Brien } 2462a55deb1SDavid E. O'Brien 2472a55deb1SDavid E. O'Brien void rehash(Array *tp) /* rehash items in small table into big one */ 2482a55deb1SDavid E. O'Brien { 2492a55deb1SDavid E. O'Brien int i, nh, nsz; 2502a55deb1SDavid E. O'Brien Cell *cp, *op, **np; 2512a55deb1SDavid E. O'Brien 2522a55deb1SDavid E. O'Brien nsz = GROWTAB * tp->size; 2532a55deb1SDavid E. O'Brien np = (Cell **) calloc(nsz, sizeof(Cell *)); 2542a55deb1SDavid E. O'Brien if (np == NULL) /* can't do it, but can keep running. */ 2552a55deb1SDavid E. O'Brien return; /* someone else will run out later. */ 2562a55deb1SDavid E. O'Brien for (i = 0; i < tp->size; i++) { 2572a55deb1SDavid E. O'Brien for (cp = tp->tab[i]; cp; cp = op) { 2582a55deb1SDavid E. O'Brien op = cp->cnext; 2592a55deb1SDavid E. O'Brien nh = hash(cp->nval, nsz); 2602a55deb1SDavid E. O'Brien cp->cnext = np[nh]; 2612a55deb1SDavid E. O'Brien np[nh] = cp; 2622a55deb1SDavid E. O'Brien } 2632a55deb1SDavid E. O'Brien } 2642a55deb1SDavid E. O'Brien free(tp->tab); 2652a55deb1SDavid E. O'Brien tp->tab = np; 2662a55deb1SDavid E. O'Brien tp->size = nsz; 2672a55deb1SDavid E. O'Brien } 2682a55deb1SDavid E. O'Brien 269813da98dSDavid E. O'Brien Cell *lookup(const char *s, Array *tp) /* look for s in tp */ 2702a55deb1SDavid E. O'Brien { 2712a55deb1SDavid E. O'Brien Cell *p; 2722a55deb1SDavid E. O'Brien int h; 2732a55deb1SDavid E. O'Brien 2742a55deb1SDavid E. O'Brien h = hash(s, tp->size); 2752a55deb1SDavid E. O'Brien for (p = tp->tab[h]; p != NULL; p = p->cnext) 2762a55deb1SDavid E. O'Brien if (strcmp(s, p->nval) == 0) 2772a55deb1SDavid E. O'Brien return(p); /* found it */ 2782a55deb1SDavid E. O'Brien return(NULL); /* not found */ 2792a55deb1SDavid E. O'Brien } 2802a55deb1SDavid E. O'Brien 2812a55deb1SDavid E. O'Brien Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */ 2822a55deb1SDavid E. O'Brien { 2832a55deb1SDavid E. O'Brien int fldno; 2842a55deb1SDavid E. O'Brien 2852a55deb1SDavid E. O'Brien if ((vp->tval & (NUM | STR)) == 0) 2862a55deb1SDavid E. O'Brien funnyvar(vp, "assign to"); 2872a55deb1SDavid E. O'Brien if (isfld(vp)) { 2882a55deb1SDavid E. O'Brien donerec = 0; /* mark $0 invalid */ 2892a55deb1SDavid E. O'Brien fldno = atoi(vp->nval); 2902a55deb1SDavid E. O'Brien if (fldno > *NF) 2912a55deb1SDavid E. O'Brien newfld(fldno); 2922a55deb1SDavid E. O'Brien dprintf( ("setting field %d to %g\n", fldno, f) ); 2932a55deb1SDavid E. O'Brien } else if (isrec(vp)) { 2942a55deb1SDavid E. O'Brien donefld = 0; /* mark $1... invalid */ 2952a55deb1SDavid E. O'Brien donerec = 1; 2962a55deb1SDavid E. O'Brien } 2972a55deb1SDavid E. O'Brien if (freeable(vp)) 2982a55deb1SDavid E. O'Brien xfree(vp->sval); /* free any previous string */ 2992a55deb1SDavid E. O'Brien vp->tval &= ~STR; /* mark string invalid */ 3002a55deb1SDavid E. O'Brien vp->tval |= NUM; /* mark number ok */ 3010840e960SXin LI if (f == -0) /* who would have thought this possible? */ 3020840e960SXin LI f = 0; 303d86a0988SRuslan Ermilov dprintf( ("setfval %p: %s = %g, t=%o\n", (void*)vp, NN(vp->nval), f, vp->tval) ); 3042a55deb1SDavid E. O'Brien return vp->fval = f; 3052a55deb1SDavid E. O'Brien } 3062a55deb1SDavid E. O'Brien 307813da98dSDavid E. O'Brien void funnyvar(Cell *vp, const char *rw) 3082a55deb1SDavid E. O'Brien { 3092a55deb1SDavid E. O'Brien if (isarr(vp)) 3102a55deb1SDavid E. O'Brien FATAL("can't %s %s; it's an array name.", rw, vp->nval); 3112a55deb1SDavid E. O'Brien if (vp->tval & FCN) 3122a55deb1SDavid E. O'Brien FATAL("can't %s %s; it's a function.", rw, vp->nval); 3132a55deb1SDavid E. O'Brien WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o", 3142a55deb1SDavid E. O'Brien vp, vp->nval, vp->sval, vp->fval, vp->tval); 3152a55deb1SDavid E. O'Brien } 3162a55deb1SDavid E. O'Brien 317813da98dSDavid E. O'Brien char *setsval(Cell *vp, const char *s) /* set string val of a Cell */ 3182a55deb1SDavid E. O'Brien { 3192a55deb1SDavid E. O'Brien char *t; 3202a55deb1SDavid E. O'Brien int fldno; 3212a55deb1SDavid E. O'Brien 322c263f9bfSRuslan Ermilov dprintf( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n", 323d86a0988SRuslan Ermilov (void*)vp, NN(vp->nval), s, vp->tval, donerec, donefld) ); 3242a55deb1SDavid E. O'Brien if ((vp->tval & (NUM | STR)) == 0) 3252a55deb1SDavid E. O'Brien funnyvar(vp, "assign to"); 3262a55deb1SDavid E. O'Brien if (isfld(vp)) { 3272a55deb1SDavid E. O'Brien donerec = 0; /* mark $0 invalid */ 3282a55deb1SDavid E. O'Brien fldno = atoi(vp->nval); 3292a55deb1SDavid E. O'Brien if (fldno > *NF) 3302a55deb1SDavid E. O'Brien newfld(fldno); 3312a55deb1SDavid E. O'Brien dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) ); 3322a55deb1SDavid E. O'Brien } else if (isrec(vp)) { 3332a55deb1SDavid E. O'Brien donefld = 0; /* mark $1... invalid */ 3342a55deb1SDavid E. O'Brien donerec = 1; 3352a55deb1SDavid E. O'Brien } 3362a55deb1SDavid E. O'Brien t = tostring(s); /* in case it's self-assign */ 3372a55deb1SDavid E. O'Brien if (freeable(vp)) 3382a55deb1SDavid E. O'Brien xfree(vp->sval); 339d2f6e492SDavid E. O'Brien vp->tval &= ~NUM; 340d2f6e492SDavid E. O'Brien vp->tval |= STR; 3412a55deb1SDavid E. O'Brien vp->tval &= ~DONTFREE; 342c263f9bfSRuslan Ermilov dprintf( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n", 343d86a0988SRuslan Ermilov (void*)vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) ); 3442a55deb1SDavid E. O'Brien return(vp->sval = t); 3452a55deb1SDavid E. O'Brien } 3462a55deb1SDavid E. O'Brien 3472a55deb1SDavid E. O'Brien Awkfloat getfval(Cell *vp) /* get float val of a Cell */ 3482a55deb1SDavid E. O'Brien { 3492a55deb1SDavid E. O'Brien if ((vp->tval & (NUM | STR)) == 0) 3502a55deb1SDavid E. O'Brien funnyvar(vp, "read value of"); 3512a55deb1SDavid E. O'Brien if (isfld(vp) && donefld == 0) 3522a55deb1SDavid E. O'Brien fldbld(); 3532a55deb1SDavid E. O'Brien else if (isrec(vp) && donerec == 0) 3542a55deb1SDavid E. O'Brien recbld(); 3552a55deb1SDavid E. O'Brien if (!isnum(vp)) { /* not a number */ 3562a55deb1SDavid E. O'Brien vp->fval = atof(vp->sval); /* best guess */ 3572a55deb1SDavid E. O'Brien if (is_number(vp->sval) && !(vp->tval&CON)) 3582a55deb1SDavid E. O'Brien vp->tval |= NUM; /* make NUM only sparingly */ 3592a55deb1SDavid E. O'Brien } 360d86a0988SRuslan Ermilov dprintf( ("getfval %p: %s = %g, t=%o\n", 361d86a0988SRuslan Ermilov (void*)vp, NN(vp->nval), vp->fval, vp->tval) ); 3622a55deb1SDavid E. O'Brien return(vp->fval); 3632a55deb1SDavid E. O'Brien } 3642a55deb1SDavid E. O'Brien 365813da98dSDavid E. O'Brien static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */ 3662a55deb1SDavid E. O'Brien { 3672a55deb1SDavid E. O'Brien char s[100]; /* BUG: unchecked */ 3682a55deb1SDavid E. O'Brien double dtemp; 3692a55deb1SDavid E. O'Brien 3702a55deb1SDavid E. O'Brien if ((vp->tval & (NUM | STR)) == 0) 3712a55deb1SDavid E. O'Brien funnyvar(vp, "read value of"); 3722a55deb1SDavid E. O'Brien if (isfld(vp) && donefld == 0) 3732a55deb1SDavid E. O'Brien fldbld(); 3742a55deb1SDavid E. O'Brien else if (isrec(vp) && donerec == 0) 3752a55deb1SDavid E. O'Brien recbld(); 3762a55deb1SDavid E. O'Brien if (isstr(vp) == 0) { 3772a55deb1SDavid E. O'Brien if (freeable(vp)) 3782a55deb1SDavid E. O'Brien xfree(vp->sval); 3792a55deb1SDavid E. O'Brien if (modf(vp->fval, &dtemp) == 0) /* it's integral */ 3802a55deb1SDavid E. O'Brien sprintf(s, "%.30g", vp->fval); 3812a55deb1SDavid E. O'Brien else 382813da98dSDavid E. O'Brien sprintf(s, *fmt, vp->fval); 3832a55deb1SDavid E. O'Brien vp->sval = tostring(s); 3842a55deb1SDavid E. O'Brien vp->tval &= ~DONTFREE; 3852a55deb1SDavid E. O'Brien vp->tval |= STR; 3862a55deb1SDavid E. O'Brien } 387d86a0988SRuslan Ermilov dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", 388d86a0988SRuslan Ermilov (void*)vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) ); 3892a55deb1SDavid E. O'Brien return(vp->sval); 3902a55deb1SDavid E. O'Brien } 3912a55deb1SDavid E. O'Brien 392813da98dSDavid E. O'Brien char *getsval(Cell *vp) /* get string val of a Cell */ 393813da98dSDavid E. O'Brien { 394813da98dSDavid E. O'Brien return get_str_val(vp, CONVFMT); 395813da98dSDavid E. O'Brien } 396813da98dSDavid E. O'Brien 397813da98dSDavid E. O'Brien char *getpssval(Cell *vp) /* get string val of a Cell for print */ 398813da98dSDavid E. O'Brien { 399813da98dSDavid E. O'Brien return get_str_val(vp, OFMT); 400813da98dSDavid E. O'Brien } 401813da98dSDavid E. O'Brien 402813da98dSDavid E. O'Brien 403813da98dSDavid E. O'Brien char *tostring(const char *s) /* make a copy of string s */ 4042a55deb1SDavid E. O'Brien { 4052a55deb1SDavid E. O'Brien char *p; 4062a55deb1SDavid E. O'Brien 4072a55deb1SDavid E. O'Brien p = (char *) malloc(strlen(s)+1); 4082a55deb1SDavid E. O'Brien if (p == NULL) 4092a55deb1SDavid E. O'Brien FATAL("out of space in tostring on %s", s); 4102a55deb1SDavid E. O'Brien strcpy(p, s); 4112a55deb1SDavid E. O'Brien return(p); 4122a55deb1SDavid E. O'Brien } 4132a55deb1SDavid E. O'Brien 414813da98dSDavid E. O'Brien char *qstring(const char *is, int delim) /* collect string up to next delim */ 4152a55deb1SDavid E. O'Brien { 416813da98dSDavid E. O'Brien const char *os = is; 4172a55deb1SDavid E. O'Brien int c, n; 4182a55deb1SDavid E. O'Brien uschar *s = (uschar *) is; 4192a55deb1SDavid E. O'Brien uschar *buf, *bp; 4202a55deb1SDavid E. O'Brien 421007c6572SDag-Erling Smørgrav if ((buf = (uschar *) malloc(strlen(is)+3)) == NULL) 4222a55deb1SDavid E. O'Brien FATAL( "out of space in qstring(%s)", s); 4232a55deb1SDavid E. O'Brien for (bp = buf; (c = *s) != delim; s++) { 4242a55deb1SDavid E. O'Brien if (c == '\n') 4252a55deb1SDavid E. O'Brien SYNTAX( "newline in string %.20s...", os ); 4262a55deb1SDavid E. O'Brien else if (c != '\\') 4272a55deb1SDavid E. O'Brien *bp++ = c; 4282a55deb1SDavid E. O'Brien else { /* \something */ 4292a55deb1SDavid E. O'Brien c = *++s; 4302a55deb1SDavid E. O'Brien if (c == 0) { /* \ at end */ 4312a55deb1SDavid E. O'Brien *bp++ = '\\'; 4322a55deb1SDavid E. O'Brien break; /* for loop */ 4332a55deb1SDavid E. O'Brien } 4342a55deb1SDavid E. O'Brien switch (c) { 4352a55deb1SDavid E. O'Brien case '\\': *bp++ = '\\'; break; 4362a55deb1SDavid E. O'Brien case 'n': *bp++ = '\n'; break; 4372a55deb1SDavid E. O'Brien case 't': *bp++ = '\t'; break; 4382a55deb1SDavid E. O'Brien case 'b': *bp++ = '\b'; break; 4392a55deb1SDavid E. O'Brien case 'f': *bp++ = '\f'; break; 4402a55deb1SDavid E. O'Brien case 'r': *bp++ = '\r'; break; 4412a55deb1SDavid E. O'Brien default: 4422a55deb1SDavid E. O'Brien if (!isdigit(c)) { 4432a55deb1SDavid E. O'Brien *bp++ = c; 4442a55deb1SDavid E. O'Brien break; 4452a55deb1SDavid E. O'Brien } 4462a55deb1SDavid E. O'Brien n = c - '0'; 4472a55deb1SDavid E. O'Brien if (isdigit(s[1])) { 4482a55deb1SDavid E. O'Brien n = 8 * n + *++s - '0'; 4492a55deb1SDavid E. O'Brien if (isdigit(s[1])) 4502a55deb1SDavid E. O'Brien n = 8 * n + *++s - '0'; 4512a55deb1SDavid E. O'Brien } 4522a55deb1SDavid E. O'Brien *bp++ = n; 4532a55deb1SDavid E. O'Brien break; 4542a55deb1SDavid E. O'Brien } 4552a55deb1SDavid E. O'Brien } 4562a55deb1SDavid E. O'Brien } 4572a55deb1SDavid E. O'Brien *bp++ = 0; 4582a55deb1SDavid E. O'Brien return (char *) buf; 4592a55deb1SDavid E. O'Brien } 460