1*7dd7cddfSDavid du Colombier /****************************************************************
2*7dd7cddfSDavid du Colombier Copyright (C) Lucent Technologies 1997
33e12c5d1SDavid du Colombier All Rights Reserved
43e12c5d1SDavid du Colombier
5*7dd7cddfSDavid du Colombier Permission to use, copy, modify, and distribute this software and
6*7dd7cddfSDavid du Colombier its documentation for any purpose and without fee is hereby
7*7dd7cddfSDavid du Colombier granted, provided that the above copyright notice appear in all
8*7dd7cddfSDavid du Colombier copies and that both that the copyright notice and this
9*7dd7cddfSDavid du Colombier permission notice and warranty disclaimer appear in supporting
10*7dd7cddfSDavid du Colombier documentation, and that the name Lucent Technologies or any of
11*7dd7cddfSDavid du Colombier its entities not be used in advertising or publicity pertaining
12*7dd7cddfSDavid du Colombier to distribution of the software without specific, written prior
13*7dd7cddfSDavid du Colombier permission.
143e12c5d1SDavid du Colombier
15*7dd7cddfSDavid du Colombier LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16*7dd7cddfSDavid du Colombier INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17*7dd7cddfSDavid du Colombier IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18*7dd7cddfSDavid du Colombier SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*7dd7cddfSDavid du Colombier WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20*7dd7cddfSDavid du Colombier IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21*7dd7cddfSDavid du Colombier ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22*7dd7cddfSDavid du Colombier THIS SOFTWARE.
23*7dd7cddfSDavid du Colombier ****************************************************************/
243e12c5d1SDavid du Colombier
253e12c5d1SDavid du Colombier #define DEBUG
263e12c5d1SDavid du Colombier #include <stdio.h>
273e12c5d1SDavid du Colombier #include <math.h>
283e12c5d1SDavid du Colombier #include <ctype.h>
293e12c5d1SDavid du Colombier #include <string.h>
303e12c5d1SDavid du Colombier #include <stdlib.h>
313e12c5d1SDavid du Colombier #include "awk.h"
323e12c5d1SDavid du Colombier #include "y.tab.h"
333e12c5d1SDavid du Colombier
343e12c5d1SDavid du Colombier #define FULLTAB 2 /* rehash when table gets this x full */
353e12c5d1SDavid du Colombier #define GROWTAB 4 /* grow table by this factor */
363e12c5d1SDavid du Colombier
373e12c5d1SDavid du Colombier Array *symtab; /* main symbol table */
383e12c5d1SDavid du Colombier
39*7dd7cddfSDavid du Colombier char **FS; /* initial field sep */
40*7dd7cddfSDavid du Colombier char **RS; /* initial record sep */
41*7dd7cddfSDavid du Colombier char **OFS; /* output field sep */
42*7dd7cddfSDavid du Colombier char **ORS; /* output record sep */
43*7dd7cddfSDavid du Colombier char **OFMT; /* output format for numbers */
44*7dd7cddfSDavid du Colombier char **CONVFMT; /* format for conversions in getsval */
453e12c5d1SDavid du Colombier Awkfloat *NF; /* number of fields in current record */
463e12c5d1SDavid du Colombier Awkfloat *NR; /* number of current record */
473e12c5d1SDavid du Colombier Awkfloat *FNR; /* number of current record in current file */
48*7dd7cddfSDavid du Colombier char **FILENAME; /* current filename argument */
493e12c5d1SDavid du Colombier Awkfloat *ARGC; /* number of arguments from command line */
50*7dd7cddfSDavid du Colombier char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */
513e12c5d1SDavid du Colombier Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */
523e12c5d1SDavid du Colombier Awkfloat *RLENGTH; /* length of same */
533e12c5d1SDavid du Colombier
543e12c5d1SDavid du Colombier Cell *nrloc; /* NR */
553e12c5d1SDavid du Colombier Cell *nfloc; /* NF */
563e12c5d1SDavid du Colombier Cell *fnrloc; /* FNR */
573e12c5d1SDavid du Colombier Array *ARGVtab; /* symbol table containing ARGV[...] */
583e12c5d1SDavid du Colombier Array *ENVtab; /* symbol table containing ENVIRON[...] */
593e12c5d1SDavid du Colombier Cell *rstartloc; /* RSTART */
603e12c5d1SDavid du Colombier Cell *rlengthloc; /* RLENGTH */
613e12c5d1SDavid du Colombier Cell *symtabloc; /* SYMTAB */
623e12c5d1SDavid du Colombier
63219b2ee8SDavid du Colombier Cell *nullloc; /* a guaranteed empty cell */
643e12c5d1SDavid du Colombier Node *nullnode; /* zero&null, converted into a node for comparisons */
65*7dd7cddfSDavid du Colombier Cell *literal0;
663e12c5d1SDavid du Colombier
67*7dd7cddfSDavid du Colombier extern Cell **fldtab;
683e12c5d1SDavid du Colombier
syminit(void)69219b2ee8SDavid du Colombier void syminit(void) /* initialize symbol table with builtin vars */
703e12c5d1SDavid du Colombier {
71*7dd7cddfSDavid du Colombier literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
723e12c5d1SDavid du Colombier /* this is used for if(x)... tests: */
733e12c5d1SDavid du Colombier nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
74*7dd7cddfSDavid du Colombier nullnode = celltonode(nullloc, CCON);
75219b2ee8SDavid du Colombier
763e12c5d1SDavid du Colombier FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
773e12c5d1SDavid du Colombier RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
783e12c5d1SDavid du Colombier OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
793e12c5d1SDavid du Colombier ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
803e12c5d1SDavid du Colombier OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
81219b2ee8SDavid du Colombier CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
82219b2ee8SDavid du Colombier FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
833e12c5d1SDavid du Colombier nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
843e12c5d1SDavid du Colombier NF = &nfloc->fval;
853e12c5d1SDavid du Colombier nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
863e12c5d1SDavid du Colombier NR = &nrloc->fval;
873e12c5d1SDavid du Colombier fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
883e12c5d1SDavid du Colombier FNR = &fnrloc->fval;
893e12c5d1SDavid du Colombier SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
903e12c5d1SDavid du Colombier rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
913e12c5d1SDavid du Colombier RSTART = &rstartloc->fval;
923e12c5d1SDavid du Colombier rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
933e12c5d1SDavid du Colombier RLENGTH = &rlengthloc->fval;
943e12c5d1SDavid du Colombier symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
95*7dd7cddfSDavid du Colombier symtabloc->sval = (char *) symtab;
963e12c5d1SDavid du Colombier }
973e12c5d1SDavid du Colombier
arginit(int ac,char ** av)98*7dd7cddfSDavid du Colombier void arginit(int ac, char **av) /* set up ARGV and ARGC */
993e12c5d1SDavid du Colombier {
1003e12c5d1SDavid du Colombier Cell *cp;
1013e12c5d1SDavid du Colombier int i;
102*7dd7cddfSDavid du Colombier char temp[50];
1033e12c5d1SDavid du Colombier
1043e12c5d1SDavid du Colombier ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
1053e12c5d1SDavid du Colombier cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
1063e12c5d1SDavid du Colombier ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
107*7dd7cddfSDavid du Colombier cp->sval = (char *) ARGVtab;
1083e12c5d1SDavid du Colombier for (i = 0; i < ac; i++) {
109*7dd7cddfSDavid du Colombier sprintf(temp, "%d", i);
110*7dd7cddfSDavid du Colombier if (is_number(*av))
1113e12c5d1SDavid du Colombier setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
1123e12c5d1SDavid du Colombier else
1133e12c5d1SDavid du Colombier setsymtab(temp, *av, 0.0, STR, ARGVtab);
1143e12c5d1SDavid du Colombier av++;
1153e12c5d1SDavid du Colombier }
1163e12c5d1SDavid du Colombier }
1173e12c5d1SDavid du Colombier
envinit(char ** envp)118*7dd7cddfSDavid du Colombier void envinit(char **envp) /* set up ENVIRON variable */
1193e12c5d1SDavid du Colombier {
1203e12c5d1SDavid du Colombier Cell *cp;
121*7dd7cddfSDavid du Colombier char *p;
1223e12c5d1SDavid du Colombier
1233e12c5d1SDavid du Colombier cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
1243e12c5d1SDavid du Colombier ENVtab = makesymtab(NSYMTAB);
125*7dd7cddfSDavid du Colombier cp->sval = (char *) ENVtab;
1263e12c5d1SDavid du Colombier for ( ; *envp; envp++) {
127*7dd7cddfSDavid du Colombier if ((p = strchr(*envp, '=')) == NULL)
1283e12c5d1SDavid du Colombier continue;
1293e12c5d1SDavid du Colombier *p++ = 0; /* split into two strings at = */
130*7dd7cddfSDavid du Colombier if (is_number(p))
1313e12c5d1SDavid du Colombier setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
1323e12c5d1SDavid du Colombier else
1333e12c5d1SDavid du Colombier setsymtab(*envp, p, 0.0, STR, ENVtab);
1343e12c5d1SDavid du Colombier p[-1] = '='; /* restore in case env is passed down to a shell */
1353e12c5d1SDavid du Colombier }
1363e12c5d1SDavid du Colombier }
1373e12c5d1SDavid du Colombier
makesymtab(int n)138219b2ee8SDavid du Colombier Array *makesymtab(int n) /* make a new symbol table */
1393e12c5d1SDavid du Colombier {
1403e12c5d1SDavid du Colombier Array *ap;
1413e12c5d1SDavid du Colombier Cell **tp;
1423e12c5d1SDavid du Colombier
1433e12c5d1SDavid du Colombier ap = (Array *) malloc(sizeof(Array));
1443e12c5d1SDavid du Colombier tp = (Cell **) calloc(n, sizeof(Cell *));
1453e12c5d1SDavid du Colombier if (ap == NULL || tp == NULL)
146*7dd7cddfSDavid du Colombier FATAL("out of space in makesymtab");
1473e12c5d1SDavid du Colombier ap->nelem = 0;
1483e12c5d1SDavid du Colombier ap->size = n;
1493e12c5d1SDavid du Colombier ap->tab = tp;
1503e12c5d1SDavid du Colombier return(ap);
1513e12c5d1SDavid du Colombier }
1523e12c5d1SDavid du Colombier
freesymtab(Cell * ap)153219b2ee8SDavid du Colombier void freesymtab(Cell *ap) /* free a symbol table */
1543e12c5d1SDavid du Colombier {
1553e12c5d1SDavid du Colombier Cell *cp, *temp;
1563e12c5d1SDavid du Colombier Array *tp;
1573e12c5d1SDavid du Colombier int i;
1583e12c5d1SDavid du Colombier
1593e12c5d1SDavid du Colombier if (!isarr(ap))
1603e12c5d1SDavid du Colombier return;
1613e12c5d1SDavid du Colombier tp = (Array *) ap->sval;
1623e12c5d1SDavid du Colombier if (tp == NULL)
1633e12c5d1SDavid du Colombier return;
1643e12c5d1SDavid du Colombier for (i = 0; i < tp->size; i++) {
1653e12c5d1SDavid du Colombier for (cp = tp->tab[i]; cp != NULL; cp = temp) {
1663e12c5d1SDavid du Colombier xfree(cp->nval);
1673e12c5d1SDavid du Colombier if (freeable(cp))
1683e12c5d1SDavid du Colombier xfree(cp->sval);
1693e12c5d1SDavid du Colombier temp = cp->cnext; /* avoids freeing then using */
1703e12c5d1SDavid du Colombier free(cp);
1713e12c5d1SDavid du Colombier }
172*7dd7cddfSDavid du Colombier tp->tab[i] = 0;
1733e12c5d1SDavid du Colombier }
1743e12c5d1SDavid du Colombier free(tp->tab);
1753e12c5d1SDavid du Colombier free(tp);
1763e12c5d1SDavid du Colombier }
1773e12c5d1SDavid du Colombier
freeelem(Cell * ap,char * s)178*7dd7cddfSDavid du Colombier void freeelem(Cell *ap, char *s) /* free elem s from ap (i.e., ap["s"] */
1793e12c5d1SDavid du Colombier {
1803e12c5d1SDavid du Colombier Array *tp;
1813e12c5d1SDavid du Colombier Cell *p, *prev = NULL;
1823e12c5d1SDavid du Colombier int h;
1833e12c5d1SDavid du Colombier
1843e12c5d1SDavid du Colombier tp = (Array *) ap->sval;
1853e12c5d1SDavid du Colombier h = hash(s, tp->size);
1863e12c5d1SDavid du Colombier for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
187*7dd7cddfSDavid du Colombier if (strcmp(s, p->nval) == 0) {
1883e12c5d1SDavid du Colombier if (prev == NULL) /* 1st one */
1893e12c5d1SDavid du Colombier tp->tab[h] = p->cnext;
1903e12c5d1SDavid du Colombier else /* middle somewhere */
1913e12c5d1SDavid du Colombier prev->cnext = p->cnext;
1923e12c5d1SDavid du Colombier if (freeable(p))
1933e12c5d1SDavid du Colombier xfree(p->sval);
1943e12c5d1SDavid du Colombier free(p->nval);
1953e12c5d1SDavid du Colombier free(p);
1963e12c5d1SDavid du Colombier tp->nelem--;
1973e12c5d1SDavid du Colombier return;
1983e12c5d1SDavid du Colombier }
1993e12c5d1SDavid du Colombier }
2003e12c5d1SDavid du Colombier
setsymtab(char * n,char * s,Awkfloat f,unsigned t,Array * tp)201*7dd7cddfSDavid du Colombier Cell *setsymtab(char *n, char *s, Awkfloat f, unsigned t, Array *tp)
2023e12c5d1SDavid du Colombier {
203*7dd7cddfSDavid du Colombier int h;
204*7dd7cddfSDavid du Colombier Cell *p;
2053e12c5d1SDavid du Colombier
2063e12c5d1SDavid du Colombier if (n != NULL && (p = lookup(n, tp)) != NULL) {
207*7dd7cddfSDavid du Colombier dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
208219b2ee8SDavid du Colombier p, p->nval, p->sval, p->fval, p->tval) );
2093e12c5d1SDavid du Colombier return(p);
2103e12c5d1SDavid du Colombier }
2113e12c5d1SDavid du Colombier p = (Cell *) malloc(sizeof(Cell));
2123e12c5d1SDavid du Colombier if (p == NULL)
213*7dd7cddfSDavid du Colombier FATAL("out of space for symbol table at %s", n);
2143e12c5d1SDavid du Colombier p->nval = tostring(n);
2153e12c5d1SDavid du Colombier p->sval = s ? tostring(s) : tostring("");
2163e12c5d1SDavid du Colombier p->fval = f;
2173e12c5d1SDavid du Colombier p->tval = t;
218*7dd7cddfSDavid du Colombier p->csub = CUNK;
219*7dd7cddfSDavid du Colombier p->ctype = OCELL;
2203e12c5d1SDavid du Colombier tp->nelem++;
2213e12c5d1SDavid du Colombier if (tp->nelem > FULLTAB * tp->size)
2223e12c5d1SDavid du Colombier rehash(tp);
2233e12c5d1SDavid du Colombier h = hash(n, tp->size);
2243e12c5d1SDavid du Colombier p->cnext = tp->tab[h];
2253e12c5d1SDavid du Colombier tp->tab[h] = p;
226*7dd7cddfSDavid du Colombier dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n",
227219b2ee8SDavid du Colombier p, p->nval, p->sval, p->fval, p->tval) );
2283e12c5d1SDavid du Colombier return(p);
2293e12c5d1SDavid du Colombier }
2303e12c5d1SDavid du Colombier
hash(char * s,int n)231*7dd7cddfSDavid du Colombier int hash(char *s, int n) /* form hash value for string s */
2323e12c5d1SDavid du Colombier {
233*7dd7cddfSDavid du Colombier unsigned hashval;
2343e12c5d1SDavid du Colombier
2353e12c5d1SDavid du Colombier for (hashval = 0; *s != '\0'; s++)
2363e12c5d1SDavid du Colombier hashval = (*s + 31 * hashval);
2373e12c5d1SDavid du Colombier return hashval % n;
2383e12c5d1SDavid du Colombier }
2393e12c5d1SDavid du Colombier
rehash(Array * tp)2403e12c5d1SDavid du Colombier void rehash(Array *tp) /* rehash items in small table into big one */
2413e12c5d1SDavid du Colombier {
2423e12c5d1SDavid du Colombier int i, nh, nsz;
2433e12c5d1SDavid du Colombier Cell *cp, *op, **np;
2443e12c5d1SDavid du Colombier
2453e12c5d1SDavid du Colombier nsz = GROWTAB * tp->size;
2463e12c5d1SDavid du Colombier np = (Cell **) calloc(nsz, sizeof(Cell *));
247219b2ee8SDavid du Colombier if (np == NULL) /* can't do it, but can keep running. */
248219b2ee8SDavid du Colombier return; /* someone else will run out later. */
2493e12c5d1SDavid du Colombier for (i = 0; i < tp->size; i++) {
2503e12c5d1SDavid du Colombier for (cp = tp->tab[i]; cp; cp = op) {
2513e12c5d1SDavid du Colombier op = cp->cnext;
2523e12c5d1SDavid du Colombier nh = hash(cp->nval, nsz);
2533e12c5d1SDavid du Colombier cp->cnext = np[nh];
2543e12c5d1SDavid du Colombier np[nh] = cp;
2553e12c5d1SDavid du Colombier }
2563e12c5d1SDavid du Colombier }
2573e12c5d1SDavid du Colombier free(tp->tab);
2583e12c5d1SDavid du Colombier tp->tab = np;
2593e12c5d1SDavid du Colombier tp->size = nsz;
2603e12c5d1SDavid du Colombier }
2613e12c5d1SDavid du Colombier
lookup(char * s,Array * tp)262*7dd7cddfSDavid du Colombier Cell *lookup(char *s, Array *tp) /* look for s in tp */
2633e12c5d1SDavid du Colombier {
264*7dd7cddfSDavid du Colombier Cell *p;
2653e12c5d1SDavid du Colombier int h;
2663e12c5d1SDavid du Colombier
2673e12c5d1SDavid du Colombier h = hash(s, tp->size);
268*7dd7cddfSDavid du Colombier for (p = tp->tab[h]; p != NULL; p = p->cnext)
269*7dd7cddfSDavid du Colombier if (strcmp(s, p->nval) == 0)
2703e12c5d1SDavid du Colombier return(p); /* found it */
2713e12c5d1SDavid du Colombier return(NULL); /* not found */
2723e12c5d1SDavid du Colombier }
2733e12c5d1SDavid du Colombier
setfval(Cell * vp,Awkfloat f)274219b2ee8SDavid du Colombier Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */
2753e12c5d1SDavid du Colombier {
276*7dd7cddfSDavid du Colombier int fldno;
277*7dd7cddfSDavid du Colombier
2783e12c5d1SDavid du Colombier if ((vp->tval & (NUM | STR)) == 0)
2793e12c5d1SDavid du Colombier funnyvar(vp, "assign to");
280*7dd7cddfSDavid du Colombier if (isfld(vp)) {
2813e12c5d1SDavid du Colombier donerec = 0; /* mark $0 invalid */
282*7dd7cddfSDavid du Colombier fldno = atoi(vp->nval);
283*7dd7cddfSDavid du Colombier if (fldno > *NF)
284*7dd7cddfSDavid du Colombier newfld(fldno);
285*7dd7cddfSDavid du Colombier dprintf( ("setting field %d to %g\n", fldno, f) );
286*7dd7cddfSDavid du Colombier } else if (isrec(vp)) {
2873e12c5d1SDavid du Colombier donefld = 0; /* mark $1... invalid */
2883e12c5d1SDavid du Colombier donerec = 1;
2893e12c5d1SDavid du Colombier }
290*7dd7cddfSDavid du Colombier if (freeable(vp))
291*7dd7cddfSDavid du Colombier xfree(vp->sval); /* free any previous string */
2923e12c5d1SDavid du Colombier vp->tval &= ~STR; /* mark string invalid */
2933e12c5d1SDavid du Colombier vp->tval |= NUM; /* mark number ok */
294*7dd7cddfSDavid du Colombier dprintf( ("setfval %p: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) );
2953e12c5d1SDavid du Colombier return vp->fval = f;
2963e12c5d1SDavid du Colombier }
2973e12c5d1SDavid du Colombier
funnyvar(Cell * vp,char * rw)2983e12c5d1SDavid du Colombier void funnyvar(Cell *vp, char *rw)
2993e12c5d1SDavid du Colombier {
300*7dd7cddfSDavid du Colombier if (isarr(vp))
301*7dd7cddfSDavid du Colombier FATAL("can't %s %s; it's an array name.", rw, vp->nval);
3023e12c5d1SDavid du Colombier if (vp->tval & FCN)
303*7dd7cddfSDavid du Colombier FATAL("can't %s %s; it's a function.", rw, vp->nval);
304*7dd7cddfSDavid du Colombier WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o",
305*7dd7cddfSDavid du Colombier vp, vp->nval, vp->sval, vp->fval, vp->tval);
3063e12c5d1SDavid du Colombier }
3073e12c5d1SDavid du Colombier
setsval(Cell * vp,char * s)308*7dd7cddfSDavid du Colombier char *setsval(Cell *vp, char *s) /* set string val of a Cell */
3093e12c5d1SDavid du Colombier {
310219b2ee8SDavid du Colombier char *t;
311*7dd7cddfSDavid du Colombier int fldno;
312219b2ee8SDavid du Colombier
313*7dd7cddfSDavid du Colombier dprintf( ("starting setsval %p: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) );
3143e12c5d1SDavid du Colombier if ((vp->tval & (NUM | STR)) == 0)
3153e12c5d1SDavid du Colombier funnyvar(vp, "assign to");
316*7dd7cddfSDavid du Colombier if (isfld(vp)) {
3173e12c5d1SDavid du Colombier donerec = 0; /* mark $0 invalid */
318*7dd7cddfSDavid du Colombier fldno = atoi(vp->nval);
319*7dd7cddfSDavid du Colombier if (fldno > *NF)
320*7dd7cddfSDavid du Colombier newfld(fldno);
321*7dd7cddfSDavid du Colombier dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) );
322*7dd7cddfSDavid du Colombier } else if (isrec(vp)) {
3233e12c5d1SDavid du Colombier donefld = 0; /* mark $1... invalid */
3243e12c5d1SDavid du Colombier donerec = 1;
3253e12c5d1SDavid du Colombier }
326219b2ee8SDavid du Colombier t = tostring(s); /* in case it's self-assign */
3273e12c5d1SDavid du Colombier vp->tval &= ~NUM;
3283e12c5d1SDavid du Colombier vp->tval |= STR;
3293e12c5d1SDavid du Colombier if (freeable(vp))
3303e12c5d1SDavid du Colombier xfree(vp->sval);
3313e12c5d1SDavid du Colombier vp->tval &= ~DONTFREE;
332*7dd7cddfSDavid du Colombier dprintf( ("setsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, t,t, vp->tval) );
333219b2ee8SDavid du Colombier return(vp->sval = t);
3343e12c5d1SDavid du Colombier }
3353e12c5d1SDavid du Colombier
getfval(Cell * vp)336*7dd7cddfSDavid du Colombier Awkfloat getfval(Cell *vp) /* get float val of a Cell */
3373e12c5d1SDavid du Colombier {
3383e12c5d1SDavid du Colombier if ((vp->tval & (NUM | STR)) == 0)
3393e12c5d1SDavid du Colombier funnyvar(vp, "read value of");
340*7dd7cddfSDavid du Colombier if (isfld(vp) && donefld == 0)
3413e12c5d1SDavid du Colombier fldbld();
342*7dd7cddfSDavid du Colombier else if (isrec(vp) && donerec == 0)
3433e12c5d1SDavid du Colombier recbld();
3443e12c5d1SDavid du Colombier if (!isnum(vp)) { /* not a number */
3453e12c5d1SDavid du Colombier vp->fval = atof(vp->sval); /* best guess */
346*7dd7cddfSDavid du Colombier if (is_number(vp->sval) && !(vp->tval&CON))
3473e12c5d1SDavid du Colombier vp->tval |= NUM; /* make NUM only sparingly */
3483e12c5d1SDavid du Colombier }
349*7dd7cddfSDavid du Colombier dprintf( ("getfval %p: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) );
3503e12c5d1SDavid du Colombier return(vp->fval);
3513e12c5d1SDavid du Colombier }
3523e12c5d1SDavid du Colombier
getsval(Cell * vp)353*7dd7cddfSDavid du Colombier char *getsval(Cell *vp) /* get string val of a Cell */
3543e12c5d1SDavid du Colombier {
355*7dd7cddfSDavid du Colombier char s[100]; /* BUG: unchecked */
3563e12c5d1SDavid du Colombier double dtemp;
3573e12c5d1SDavid du Colombier
3583e12c5d1SDavid du Colombier if ((vp->tval & (NUM | STR)) == 0)
3593e12c5d1SDavid du Colombier funnyvar(vp, "read value of");
360*7dd7cddfSDavid du Colombier if (isfld(vp) && donefld == 0)
3613e12c5d1SDavid du Colombier fldbld();
362*7dd7cddfSDavid du Colombier else if (isrec(vp) && donerec == 0)
3633e12c5d1SDavid du Colombier recbld();
364*7dd7cddfSDavid du Colombier if (isstr(vp) == 0) {
365*7dd7cddfSDavid du Colombier if (freeable(vp))
3663e12c5d1SDavid du Colombier xfree(vp->sval);
3673e12c5d1SDavid du Colombier if (modf(vp->fval, &dtemp) == 0) /* it's integral */
368*7dd7cddfSDavid du Colombier sprintf(s, "%.30g", vp->fval);
3693e12c5d1SDavid du Colombier else
370*7dd7cddfSDavid du Colombier sprintf(s, *CONVFMT, vp->fval);
3713e12c5d1SDavid du Colombier vp->sval = tostring(s);
3723e12c5d1SDavid du Colombier vp->tval &= ~DONTFREE;
3733e12c5d1SDavid du Colombier vp->tval |= STR;
3743e12c5d1SDavid du Colombier }
375*7dd7cddfSDavid du Colombier dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", vp, vp->nval, vp->sval, vp->sval, vp->tval) );
3763e12c5d1SDavid du Colombier return(vp->sval);
3773e12c5d1SDavid du Colombier }
3783e12c5d1SDavid du Colombier
tostring(char * s)379*7dd7cddfSDavid du Colombier char *tostring(char *s) /* make a copy of string s */
3803e12c5d1SDavid du Colombier {
381*7dd7cddfSDavid du Colombier char *p;
3823e12c5d1SDavid du Colombier
383*7dd7cddfSDavid du Colombier p = (char *) malloc(strlen(s)+1);
3843e12c5d1SDavid du Colombier if (p == NULL)
385*7dd7cddfSDavid du Colombier FATAL("out of space in tostring on %s", s);
386*7dd7cddfSDavid du Colombier strcpy(p, s);
3873e12c5d1SDavid du Colombier return(p);
3883e12c5d1SDavid du Colombier }
3893e12c5d1SDavid du Colombier
qstring(char * s,int delim)390*7dd7cddfSDavid du Colombier char *qstring(char *s, int delim) /* collect string up to next delim */
3913e12c5d1SDavid du Colombier {
392*7dd7cddfSDavid du Colombier char *os = s;
3933e12c5d1SDavid du Colombier int c, n;
394*7dd7cddfSDavid du Colombier char *buf, *bp;
3953e12c5d1SDavid du Colombier
396*7dd7cddfSDavid du Colombier if ((buf = (char *) malloc(strlen(s)+3)) == NULL)
397*7dd7cddfSDavid du Colombier FATAL( "out of space in qstring(%s)", s);
398*7dd7cddfSDavid du Colombier for (bp = buf; (c = *s) != delim; s++) {
399*7dd7cddfSDavid du Colombier if (c == '\n')
400*7dd7cddfSDavid du Colombier SYNTAX( "newline in string %.20s...", os );
4013e12c5d1SDavid du Colombier else if (c != '\\')
402*7dd7cddfSDavid du Colombier *bp++ = c;
403*7dd7cddfSDavid du Colombier else { /* \something */
404*7dd7cddfSDavid du Colombier c = *++s;
405*7dd7cddfSDavid du Colombier if (c == 0) { /* \ at end */
406*7dd7cddfSDavid du Colombier *bp++ = '\\';
407*7dd7cddfSDavid du Colombier break; /* for loop */
408*7dd7cddfSDavid du Colombier }
409*7dd7cddfSDavid du Colombier switch (c) {
410*7dd7cddfSDavid du Colombier case '\\': *bp++ = '\\'; break;
411*7dd7cddfSDavid du Colombier case 'n': *bp++ = '\n'; break;
412*7dd7cddfSDavid du Colombier case 't': *bp++ = '\t'; break;
413*7dd7cddfSDavid du Colombier case 'b': *bp++ = '\b'; break;
414*7dd7cddfSDavid du Colombier case 'f': *bp++ = '\f'; break;
415*7dd7cddfSDavid du Colombier case 'r': *bp++ = '\r'; break;
4163e12c5d1SDavid du Colombier default:
4173e12c5d1SDavid du Colombier if (!isdigit(c)) {
418*7dd7cddfSDavid du Colombier *bp++ = c;
4193e12c5d1SDavid du Colombier break;
4203e12c5d1SDavid du Colombier }
4213e12c5d1SDavid du Colombier n = c - '0';
4223e12c5d1SDavid du Colombier if (isdigit(s[1])) {
4233e12c5d1SDavid du Colombier n = 8 * n + *++s - '0';
4243e12c5d1SDavid du Colombier if (isdigit(s[1]))
4253e12c5d1SDavid du Colombier n = 8 * n + *++s - '0';
4263e12c5d1SDavid du Colombier }
427*7dd7cddfSDavid du Colombier *bp++ = n;
4283e12c5d1SDavid du Colombier break;
4293e12c5d1SDavid du Colombier }
4303e12c5d1SDavid du Colombier }
431*7dd7cddfSDavid du Colombier }
432*7dd7cddfSDavid du Colombier *bp++ = 0;
433*7dd7cddfSDavid du Colombier return buf;
4343e12c5d1SDavid du Colombier }
435