15ea9e707SThomas Veerman /****************************************************************
25ea9e707SThomas Veerman Copyright (C) Lucent Technologies 1997
35ea9e707SThomas Veerman All Rights Reserved
45ea9e707SThomas Veerman
55ea9e707SThomas Veerman Permission to use, copy, modify, and distribute this software and
65ea9e707SThomas Veerman its documentation for any purpose and without fee is hereby
75ea9e707SThomas Veerman granted, provided that the above copyright notice appear in all
85ea9e707SThomas Veerman copies and that both that the copyright notice and this
95ea9e707SThomas Veerman permission notice and warranty disclaimer appear in supporting
105ea9e707SThomas Veerman documentation, and that the name Lucent Technologies or any of
115ea9e707SThomas Veerman its entities not be used in advertising or publicity pertaining
125ea9e707SThomas Veerman to distribution of the software without specific, written prior
135ea9e707SThomas Veerman permission.
145ea9e707SThomas Veerman
155ea9e707SThomas Veerman LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
165ea9e707SThomas Veerman INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
175ea9e707SThomas Veerman IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
185ea9e707SThomas Veerman SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
195ea9e707SThomas Veerman WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
205ea9e707SThomas Veerman IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
215ea9e707SThomas Veerman ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
225ea9e707SThomas Veerman THIS SOFTWARE.
235ea9e707SThomas Veerman ****************************************************************/
245ea9e707SThomas Veerman
255ea9e707SThomas Veerman #if HAVE_NBTOOL_CONFIG_H
265ea9e707SThomas Veerman #include "nbtool_config.h"
275ea9e707SThomas Veerman #endif
285ea9e707SThomas Veerman
295ea9e707SThomas Veerman #define DEBUG
305ea9e707SThomas Veerman #include <stdio.h>
315ea9e707SThomas Veerman #include <math.h>
325ea9e707SThomas Veerman #include <ctype.h>
335ea9e707SThomas Veerman #include <string.h>
345ea9e707SThomas Veerman #include <stdlib.h>
355ea9e707SThomas Veerman #include "awk.h"
365ea9e707SThomas Veerman #include "awkgram.h"
375ea9e707SThomas Veerman
385ea9e707SThomas Veerman #define FULLTAB 2 /* rehash when table gets this x full */
395ea9e707SThomas Veerman #define GROWTAB 4 /* grow table by this factor */
405ea9e707SThomas Veerman
415ea9e707SThomas Veerman Array *symtab; /* main symbol table */
425ea9e707SThomas Veerman
435ea9e707SThomas Veerman char **FS; /* initial field sep */
445ea9e707SThomas Veerman char **RS; /* initial record sep */
455ea9e707SThomas Veerman char **OFS; /* output field sep */
465ea9e707SThomas Veerman char **ORS; /* output record sep */
475ea9e707SThomas Veerman char **OFMT; /* output format for numbers */
485ea9e707SThomas Veerman char **CONVFMT; /* format for conversions in getsval */
495ea9e707SThomas Veerman Awkfloat *NF; /* number of fields in current record */
505ea9e707SThomas Veerman Awkfloat *NR; /* number of current record */
515ea9e707SThomas Veerman Awkfloat *FNR; /* number of current record in current file */
525ea9e707SThomas Veerman char **FILENAME; /* current filename argument */
535ea9e707SThomas Veerman Awkfloat *ARGC; /* number of arguments from command line */
545ea9e707SThomas Veerman char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */
555ea9e707SThomas Veerman Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */
565ea9e707SThomas Veerman Awkfloat *RLENGTH; /* length of same */
575ea9e707SThomas Veerman
585ea9e707SThomas Veerman Cell *fsloc; /* FS */
595ea9e707SThomas Veerman Cell *nrloc; /* NR */
605ea9e707SThomas Veerman Cell *nfloc; /* NF */
615ea9e707SThomas Veerman Cell *fnrloc; /* FNR */
625ea9e707SThomas Veerman Array *ARGVtab; /* symbol table containing ARGV[...] */
635ea9e707SThomas Veerman Array *ENVtab; /* symbol table containing ENVIRON[...] */
645ea9e707SThomas Veerman Cell *rstartloc; /* RSTART */
655ea9e707SThomas Veerman Cell *rlengthloc; /* RLENGTH */
665ea9e707SThomas Veerman Cell *symtabloc; /* SYMTAB */
675ea9e707SThomas Veerman
685ea9e707SThomas Veerman Cell *nullloc; /* a guaranteed empty cell */
695ea9e707SThomas Veerman Node *nullnode; /* zero&null, converted into a node for comparisons */
705ea9e707SThomas Veerman Cell *literal0;
715ea9e707SThomas Veerman
725ea9e707SThomas Veerman extern Cell **fldtab;
735ea9e707SThomas Veerman
74*84d9c625SLionel Sambuc static void
setfree(Cell * vp)75*84d9c625SLionel Sambuc setfree(Cell *vp)
76*84d9c625SLionel Sambuc {
77*84d9c625SLionel Sambuc if (&vp->sval == FS || &vp->sval == RS ||
78*84d9c625SLionel Sambuc &vp->sval == OFS || &vp->sval == ORS ||
79*84d9c625SLionel Sambuc &vp->sval == OFMT || &vp->sval == CONVFMT ||
80*84d9c625SLionel Sambuc &vp->sval == FILENAME || &vp->sval == SUBSEP)
81*84d9c625SLionel Sambuc vp->tval |= DONTFREE;
82*84d9c625SLionel Sambuc else
83*84d9c625SLionel Sambuc vp->tval &= ~DONTFREE;
84*84d9c625SLionel Sambuc }
85*84d9c625SLionel Sambuc
syminit(void)865ea9e707SThomas Veerman void syminit(void) /* initialize symbol table with builtin vars */
875ea9e707SThomas Veerman {
885ea9e707SThomas Veerman literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
895ea9e707SThomas Veerman /* this is used for if(x)... tests: */
905ea9e707SThomas Veerman nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
915ea9e707SThomas Veerman nullnode = celltonode(nullloc, CCON);
925ea9e707SThomas Veerman
935ea9e707SThomas Veerman fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab);
945ea9e707SThomas Veerman FS = &fsloc->sval;
955ea9e707SThomas Veerman RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
965ea9e707SThomas Veerman OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
975ea9e707SThomas Veerman ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
985ea9e707SThomas Veerman OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
995ea9e707SThomas Veerman CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
1005ea9e707SThomas Veerman FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval;
1015ea9e707SThomas Veerman nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
1025ea9e707SThomas Veerman NF = &nfloc->fval;
1035ea9e707SThomas Veerman nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
1045ea9e707SThomas Veerman NR = &nrloc->fval;
1055ea9e707SThomas Veerman fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
1065ea9e707SThomas Veerman FNR = &fnrloc->fval;
1075ea9e707SThomas Veerman SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
1085ea9e707SThomas Veerman rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
1095ea9e707SThomas Veerman RSTART = &rstartloc->fval;
1105ea9e707SThomas Veerman rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
1115ea9e707SThomas Veerman RLENGTH = &rlengthloc->fval;
1125ea9e707SThomas Veerman symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
1135ea9e707SThomas Veerman symtabloc->sval = (char *) symtab;
1145ea9e707SThomas Veerman }
1155ea9e707SThomas Veerman
arginit(int ac,char ** av)1165ea9e707SThomas Veerman void arginit(int ac, char **av) /* set up ARGV and ARGC */
1175ea9e707SThomas Veerman {
1185ea9e707SThomas Veerman Cell *cp;
1195ea9e707SThomas Veerman int i;
1205ea9e707SThomas Veerman char temp[50];
1215ea9e707SThomas Veerman
1225ea9e707SThomas Veerman ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
1235ea9e707SThomas Veerman cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
1245ea9e707SThomas Veerman ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
1255ea9e707SThomas Veerman cp->sval = (char *) ARGVtab;
1265ea9e707SThomas Veerman for (i = 0; i < ac; i++) {
1275ea9e707SThomas Veerman snprintf(temp, sizeof(temp), "%d", i);
1285ea9e707SThomas Veerman if (is_number(*av))
1295ea9e707SThomas Veerman setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
1305ea9e707SThomas Veerman else
1315ea9e707SThomas Veerman setsymtab(temp, *av, 0.0, STR, ARGVtab);
1325ea9e707SThomas Veerman av++;
1335ea9e707SThomas Veerman }
1345ea9e707SThomas Veerman }
1355ea9e707SThomas Veerman
envinit(char ** envp)1365ea9e707SThomas Veerman void envinit(char **envp) /* set up ENVIRON variable */
1375ea9e707SThomas Veerman {
1385ea9e707SThomas Veerman Cell *cp;
1395ea9e707SThomas Veerman char *p;
1405ea9e707SThomas Veerman
1415ea9e707SThomas Veerman cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
1425ea9e707SThomas Veerman ENVtab = makesymtab(NSYMTAB);
1435ea9e707SThomas Veerman cp->sval = (char *) ENVtab;
1445ea9e707SThomas Veerman for ( ; *envp; envp++) {
1455ea9e707SThomas Veerman if ((p = strchr(*envp, '=')) == NULL)
1465ea9e707SThomas Veerman continue;
1475ea9e707SThomas Veerman if( p == *envp ) /* no left hand side name in env string */
1485ea9e707SThomas Veerman continue;
1495ea9e707SThomas Veerman *p++ = 0; /* split into two strings at = */
1505ea9e707SThomas Veerman if (is_number(p))
1515ea9e707SThomas Veerman setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
1525ea9e707SThomas Veerman else
1535ea9e707SThomas Veerman setsymtab(*envp, p, 0.0, STR, ENVtab);
1545ea9e707SThomas Veerman p[-1] = '='; /* restore in case env is passed down to a shell */
1555ea9e707SThomas Veerman }
1565ea9e707SThomas Veerman }
1575ea9e707SThomas Veerman
makesymtab(int n)1585ea9e707SThomas Veerman Array *makesymtab(int n) /* make a new symbol table */
1595ea9e707SThomas Veerman {
1605ea9e707SThomas Veerman Array *ap;
1615ea9e707SThomas Veerman Cell **tp;
1625ea9e707SThomas Veerman
1635ea9e707SThomas Veerman ap = malloc(sizeof(*ap));
1645ea9e707SThomas Veerman tp = calloc(n, sizeof(*tp));
1655ea9e707SThomas Veerman if (ap == NULL || tp == NULL)
1665ea9e707SThomas Veerman FATAL("out of space in makesymtab");
1675ea9e707SThomas Veerman ap->nelem = 0;
1685ea9e707SThomas Veerman ap->size = n;
1695ea9e707SThomas Veerman ap->tab = tp;
1705ea9e707SThomas Veerman return(ap);
1715ea9e707SThomas Veerman }
1725ea9e707SThomas Veerman
freesymtab(Cell * ap)1735ea9e707SThomas Veerman void freesymtab(Cell *ap) /* free a symbol table */
1745ea9e707SThomas Veerman {
1755ea9e707SThomas Veerman Cell *cp, *temp;
1765ea9e707SThomas Veerman Array *tp;
1775ea9e707SThomas Veerman int i;
1785ea9e707SThomas Veerman
1795ea9e707SThomas Veerman if (!isarr(ap))
1805ea9e707SThomas Veerman return;
1815ea9e707SThomas Veerman tp = (Array *) ap->sval;
1825ea9e707SThomas Veerman if (tp == NULL)
1835ea9e707SThomas Veerman return;
1845ea9e707SThomas Veerman for (i = 0; i < tp->size; i++) {
1855ea9e707SThomas Veerman for (cp = tp->tab[i]; cp != NULL; cp = temp) {
1865ea9e707SThomas Veerman xfree(cp->nval);
1875ea9e707SThomas Veerman if (freeable(cp))
1885ea9e707SThomas Veerman xfree(cp->sval);
1895ea9e707SThomas Veerman temp = cp->cnext; /* avoids freeing then using */
1905ea9e707SThomas Veerman free(cp);
1915ea9e707SThomas Veerman tp->nelem--;
1925ea9e707SThomas Veerman }
1935ea9e707SThomas Veerman tp->tab[i] = 0;
1945ea9e707SThomas Veerman }
1955ea9e707SThomas Veerman if (tp->nelem != 0)
1965ea9e707SThomas Veerman WARNING("can't happen: inconsistent element count freeing %s", ap->nval);
1975ea9e707SThomas Veerman free(tp->tab);
1985ea9e707SThomas Veerman free(tp);
1995ea9e707SThomas Veerman }
2005ea9e707SThomas Veerman
freeelem(Cell * ap,const char * s)2015ea9e707SThomas Veerman void freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */
2025ea9e707SThomas Veerman {
2035ea9e707SThomas Veerman Array *tp;
2045ea9e707SThomas Veerman Cell *p, *prev = NULL;
2055ea9e707SThomas Veerman int h;
2065ea9e707SThomas Veerman
2075ea9e707SThomas Veerman tp = (Array *) ap->sval;
2085ea9e707SThomas Veerman h = hash(s, tp->size);
2095ea9e707SThomas Veerman for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
2105ea9e707SThomas Veerman if (strcmp(s, p->nval) == 0) {
2115ea9e707SThomas Veerman if (prev == NULL) /* 1st one */
2125ea9e707SThomas Veerman tp->tab[h] = p->cnext;
2135ea9e707SThomas Veerman else /* middle somewhere */
2145ea9e707SThomas Veerman prev->cnext = p->cnext;
2155ea9e707SThomas Veerman if (freeable(p))
2165ea9e707SThomas Veerman xfree(p->sval);
2175ea9e707SThomas Veerman free(p->nval);
2185ea9e707SThomas Veerman free(p);
2195ea9e707SThomas Veerman tp->nelem--;
2205ea9e707SThomas Veerman return;
2215ea9e707SThomas Veerman }
2225ea9e707SThomas Veerman }
2235ea9e707SThomas Veerman
setsymtab(const char * n,const char * s,Awkfloat f,unsigned t,Array * tp)2245ea9e707SThomas Veerman Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp)
2255ea9e707SThomas Veerman {
2265ea9e707SThomas Veerman int h;
2275ea9e707SThomas Veerman Cell *p;
2285ea9e707SThomas Veerman
2295ea9e707SThomas Veerman if (n == NULL)
2305ea9e707SThomas Veerman n = "";
2315ea9e707SThomas Veerman
2325ea9e707SThomas Veerman if ((p = lookup(n, tp)) != NULL) {
2335ea9e707SThomas Veerman dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
2345ea9e707SThomas Veerman p, NN(p->nval), NN(p->sval), p->fval, p->tval) );
2355ea9e707SThomas Veerman return(p);
2365ea9e707SThomas Veerman }
2375ea9e707SThomas Veerman p = malloc(sizeof(*p));
2385ea9e707SThomas Veerman if (p == NULL)
2395ea9e707SThomas Veerman FATAL("out of space for symbol table at %s", n);
2405ea9e707SThomas Veerman p->nval = tostring(n);
2415ea9e707SThomas Veerman p->sval = s ? tostring(s) : tostring("");
2425ea9e707SThomas Veerman p->fval = f;
2435ea9e707SThomas Veerman p->tval = t;
2445ea9e707SThomas Veerman p->csub = CUNK;
2455ea9e707SThomas Veerman p->ctype = OCELL;
2465ea9e707SThomas Veerman tp->nelem++;
2475ea9e707SThomas Veerman if (tp->nelem > FULLTAB * tp->size)
2485ea9e707SThomas Veerman rehash(tp);
2495ea9e707SThomas Veerman h = hash(n, tp->size);
2505ea9e707SThomas Veerman p->cnext = tp->tab[h];
2515ea9e707SThomas Veerman tp->tab[h] = p;
2525ea9e707SThomas Veerman dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n",
2535ea9e707SThomas Veerman p, p->nval, p->sval, p->fval, p->tval) );
2545ea9e707SThomas Veerman return(p);
2555ea9e707SThomas Veerman }
2565ea9e707SThomas Veerman
hash(const char * s,int n)2575ea9e707SThomas Veerman int hash(const char *s, int n) /* form hash value for string s */
2585ea9e707SThomas Veerman {
2595ea9e707SThomas Veerman unsigned hashval;
2605ea9e707SThomas Veerman
2615ea9e707SThomas Veerman for (hashval = 0; *s != '\0'; s++)
2625ea9e707SThomas Veerman hashval = (*s + 31 * hashval);
2635ea9e707SThomas Veerman return hashval % n;
2645ea9e707SThomas Veerman }
2655ea9e707SThomas Veerman
rehash(Array * tp)2665ea9e707SThomas Veerman void rehash(Array *tp) /* rehash items in small table into big one */
2675ea9e707SThomas Veerman {
2685ea9e707SThomas Veerman int i, nh, nsz;
2695ea9e707SThomas Veerman Cell *cp, *op, **np;
2705ea9e707SThomas Veerman
2715ea9e707SThomas Veerman nsz = GROWTAB * tp->size;
2725ea9e707SThomas Veerman np = calloc(nsz, sizeof(*np));
2735ea9e707SThomas Veerman if (np == NULL) /* can't do it, but can keep running. */
2745ea9e707SThomas Veerman return; /* someone else will run out later. */
2755ea9e707SThomas Veerman for (i = 0; i < tp->size; i++) {
2765ea9e707SThomas Veerman for (cp = tp->tab[i]; cp; cp = op) {
2775ea9e707SThomas Veerman op = cp->cnext;
2785ea9e707SThomas Veerman nh = hash(cp->nval, nsz);
2795ea9e707SThomas Veerman cp->cnext = np[nh];
2805ea9e707SThomas Veerman np[nh] = cp;
2815ea9e707SThomas Veerman }
2825ea9e707SThomas Veerman }
2835ea9e707SThomas Veerman free(tp->tab);
2845ea9e707SThomas Veerman tp->tab = np;
2855ea9e707SThomas Veerman tp->size = nsz;
2865ea9e707SThomas Veerman }
2875ea9e707SThomas Veerman
lookup(const char * s,Array * tp)2885ea9e707SThomas Veerman Cell *lookup(const char *s, Array *tp) /* look for s in tp */
2895ea9e707SThomas Veerman {
2905ea9e707SThomas Veerman Cell *p;
2915ea9e707SThomas Veerman int h;
2925ea9e707SThomas Veerman
2935ea9e707SThomas Veerman h = hash(s, tp->size);
2945ea9e707SThomas Veerman for (p = tp->tab[h]; p != NULL; p = p->cnext)
2955ea9e707SThomas Veerman if (strcmp(s, p->nval) == 0)
2965ea9e707SThomas Veerman return(p); /* found it */
2975ea9e707SThomas Veerman return(NULL); /* not found */
2985ea9e707SThomas Veerman }
2995ea9e707SThomas Veerman
setfval(Cell * vp,Awkfloat f)3005ea9e707SThomas Veerman Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */
3015ea9e707SThomas Veerman {
3025ea9e707SThomas Veerman int fldno;
3035ea9e707SThomas Veerman
3045ea9e707SThomas Veerman f += 0.0; /* normalise negative zero to positive zero */
3055ea9e707SThomas Veerman if ((vp->tval & (NUM | STR)) == 0)
3065ea9e707SThomas Veerman funnyvar(vp, "assign to");
3075ea9e707SThomas Veerman if (isfld(vp)) {
3085ea9e707SThomas Veerman donerec = 0; /* mark $0 invalid */
3095ea9e707SThomas Veerman fldno = atoi(vp->nval);
3105ea9e707SThomas Veerman if (fldno > *NF)
3115ea9e707SThomas Veerman newfld(fldno);
3125ea9e707SThomas Veerman dprintf( ("setting field %d to %g\n", fldno, f) );
3135ea9e707SThomas Veerman } else if (&vp->fval == NF) {
3145ea9e707SThomas Veerman donerec = 0; /* mark $0 invalid */
3155ea9e707SThomas Veerman setlastfld(f);
3165ea9e707SThomas Veerman dprintf( ("setting NF to %g\n", f) );
3175ea9e707SThomas Veerman } else if (isrec(vp)) {
3185ea9e707SThomas Veerman donefld = 0; /* mark $1... invalid */
3195ea9e707SThomas Veerman donerec = 1;
3205ea9e707SThomas Veerman }
3215ea9e707SThomas Veerman if (freeable(vp))
3225ea9e707SThomas Veerman xfree(vp->sval); /* free any previous string */
3235ea9e707SThomas Veerman vp->tval &= ~STR; /* mark string invalid */
3245ea9e707SThomas Veerman vp->tval |= NUM; /* mark number ok */
325*84d9c625SLionel Sambuc if (f == -0) /* who would have thought this possible? */
326*84d9c625SLionel Sambuc f = 0;
3275ea9e707SThomas Veerman dprintf( ("setfval %p: %s = %g, t=%o\n", vp, NN(vp->nval), f, vp->tval) );
3285ea9e707SThomas Veerman return vp->fval = f;
3295ea9e707SThomas Veerman }
3305ea9e707SThomas Veerman
funnyvar(Cell * vp,const char * rw)3315ea9e707SThomas Veerman void funnyvar(Cell *vp, const char *rw)
3325ea9e707SThomas Veerman {
3335ea9e707SThomas Veerman if (isarr(vp))
3345ea9e707SThomas Veerman FATAL("can't %s %s; it's an array name.", rw, vp->nval);
3355ea9e707SThomas Veerman if (vp->tval & FCN)
3365ea9e707SThomas Veerman FATAL("can't %s %s; it's a function.", rw, vp->nval);
3375ea9e707SThomas Veerman WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o",
3385ea9e707SThomas Veerman vp, vp->nval, vp->sval, vp->fval, vp->tval);
3395ea9e707SThomas Veerman }
3405ea9e707SThomas Veerman
setsval(Cell * vp,const char * s)3415ea9e707SThomas Veerman char *setsval(Cell *vp, const char *s) /* set string val of a Cell */
3425ea9e707SThomas Veerman {
3435ea9e707SThomas Veerman char *t;
3445ea9e707SThomas Veerman int fldno;
3455ea9e707SThomas Veerman Awkfloat f;
3465ea9e707SThomas Veerman
3475ea9e707SThomas Veerman dprintf( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n",
3485ea9e707SThomas Veerman vp, NN(vp->nval), s, vp->tval, donerec, donefld) );
3495ea9e707SThomas Veerman if ((vp->tval & (NUM | STR)) == 0)
3505ea9e707SThomas Veerman funnyvar(vp, "assign to");
3515ea9e707SThomas Veerman if (isfld(vp)) {
3525ea9e707SThomas Veerman donerec = 0; /* mark $0 invalid */
3535ea9e707SThomas Veerman fldno = atoi(vp->nval);
3545ea9e707SThomas Veerman if (fldno > *NF)
3555ea9e707SThomas Veerman newfld(fldno);
3565ea9e707SThomas Veerman dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) );
3575ea9e707SThomas Veerman } else if (isrec(vp)) {
3585ea9e707SThomas Veerman donefld = 0; /* mark $1... invalid */
3595ea9e707SThomas Veerman donerec = 1;
3605ea9e707SThomas Veerman }
361*84d9c625SLionel Sambuc t = s ? tostring(s) : tostring(""); /* in case it's self-assign */
3625ea9e707SThomas Veerman if (freeable(vp))
3635ea9e707SThomas Veerman xfree(vp->sval);
3645ea9e707SThomas Veerman vp->tval &= ~NUM;
3655ea9e707SThomas Veerman vp->tval |= STR;
366*84d9c625SLionel Sambuc setfree(vp);
3675ea9e707SThomas Veerman dprintf( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",
3685ea9e707SThomas Veerman vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) );
3695ea9e707SThomas Veerman
3705ea9e707SThomas Veerman vp->sval = t;
3715ea9e707SThomas Veerman if (&vp->fval == NF) {
3725ea9e707SThomas Veerman donerec = 0; /* mark $0 invalid */
3735ea9e707SThomas Veerman f = getfval(vp);
3745ea9e707SThomas Veerman setlastfld(f);
3755ea9e707SThomas Veerman dprintf( ("setting NF to %g\n", f) );
3765ea9e707SThomas Veerman }
3775ea9e707SThomas Veerman
3785ea9e707SThomas Veerman return(vp->sval);
3795ea9e707SThomas Veerman }
3805ea9e707SThomas Veerman
getfval(Cell * vp)3815ea9e707SThomas Veerman Awkfloat getfval(Cell *vp) /* get float val of a Cell */
3825ea9e707SThomas Veerman {
3835ea9e707SThomas Veerman if ((vp->tval & (NUM | STR)) == 0)
3845ea9e707SThomas Veerman funnyvar(vp, "read value of");
3855ea9e707SThomas Veerman if (isfld(vp) && donefld == 0)
3865ea9e707SThomas Veerman fldbld();
3875ea9e707SThomas Veerman else if (isrec(vp) && donerec == 0)
3885ea9e707SThomas Veerman recbld();
3895ea9e707SThomas Veerman if (!isnum(vp)) { /* not a number */
3905ea9e707SThomas Veerman vp->fval = atof(vp->sval); /* best guess */
3915ea9e707SThomas Veerman if (is_number(vp->sval) && !(vp->tval&CON))
3925ea9e707SThomas Veerman vp->tval |= NUM; /* make NUM only sparingly */
3935ea9e707SThomas Veerman }
394*84d9c625SLionel Sambuc dprintf( ("getfval %p: %s = %g, t=%o\n",
395*84d9c625SLionel Sambuc vp, NN(vp->nval), vp->fval, vp->tval) );
3965ea9e707SThomas Veerman return(vp->fval);
3975ea9e707SThomas Veerman }
3985ea9e707SThomas Veerman
get_str_val(Cell * vp,char ** fmt)3995ea9e707SThomas Veerman static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */
4005ea9e707SThomas Veerman {
4015ea9e707SThomas Veerman char s[100];
4025ea9e707SThomas Veerman double dtemp;
4035ea9e707SThomas Veerman
4045ea9e707SThomas Veerman if ((vp->tval & (NUM | STR)) == 0)
4055ea9e707SThomas Veerman funnyvar(vp, "read value of");
4065ea9e707SThomas Veerman if (isfld(vp) && donefld == 0)
4075ea9e707SThomas Veerman fldbld();
4085ea9e707SThomas Veerman else if (isrec(vp) && donerec == 0)
4095ea9e707SThomas Veerman recbld();
4105ea9e707SThomas Veerman if (isstr(vp) == 0) {
4115ea9e707SThomas Veerman if (freeable(vp))
4125ea9e707SThomas Veerman xfree(vp->sval);
4135ea9e707SThomas Veerman if (modf(vp->fval, &dtemp) == 0) /* it's integral */
4145ea9e707SThomas Veerman snprintf(s, sizeof(s), "%.30g", vp->fval);
4155ea9e707SThomas Veerman else
4165ea9e707SThomas Veerman snprintf(s, sizeof(s), *fmt, vp->fval);
4175ea9e707SThomas Veerman vp->sval = tostring(s);
4185ea9e707SThomas Veerman vp->tval |= STR;
419*84d9c625SLionel Sambuc setfree(vp);
4205ea9e707SThomas Veerman }
421*84d9c625SLionel Sambuc dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n",
422*84d9c625SLionel Sambuc vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) );
4235ea9e707SThomas Veerman return(vp->sval);
4245ea9e707SThomas Veerman }
4255ea9e707SThomas Veerman
getsval(Cell * vp)4265ea9e707SThomas Veerman char *getsval(Cell *vp) /* get string val of a Cell */
4275ea9e707SThomas Veerman {
4285ea9e707SThomas Veerman return get_str_val(vp, CONVFMT);
4295ea9e707SThomas Veerman }
4305ea9e707SThomas Veerman
getpssval(Cell * vp)4315ea9e707SThomas Veerman char *getpssval(Cell *vp) /* get string val of a Cell for print */
4325ea9e707SThomas Veerman {
4335ea9e707SThomas Veerman return get_str_val(vp, OFMT);
4345ea9e707SThomas Veerman }
4355ea9e707SThomas Veerman
4365ea9e707SThomas Veerman
tostring(const char * s)4375ea9e707SThomas Veerman char *tostring(const char *s) /* make a copy of string s */
4385ea9e707SThomas Veerman {
4395ea9e707SThomas Veerman char *p;
4405ea9e707SThomas Veerman
4415ea9e707SThomas Veerman p = strdup(s);
4425ea9e707SThomas Veerman if (p == NULL)
4435ea9e707SThomas Veerman FATAL("out of space in tostring on %s", s);
4445ea9e707SThomas Veerman return(p);
4455ea9e707SThomas Veerman }
4465ea9e707SThomas Veerman
catstr(Cell * a,Cell * b)4475ea9e707SThomas Veerman Cell *catstr(Cell *a, Cell *b) /* concatenate a and b */
4485ea9e707SThomas Veerman {
4495ea9e707SThomas Veerman Cell *c;
4505ea9e707SThomas Veerman char *p;
4515ea9e707SThomas Veerman char *sa = getsval(a);
4525ea9e707SThomas Veerman char *sb = getsval(b);
4535ea9e707SThomas Veerman size_t l = strlen(sa) + strlen(sb) + 1;
4545ea9e707SThomas Veerman p = malloc(l);
4555ea9e707SThomas Veerman if (p == NULL)
4565ea9e707SThomas Veerman FATAL("out of space concatenating %s and %s", sa, sb);
4575ea9e707SThomas Veerman snprintf(p, l, "%s%s", sa, sb);
4585ea9e707SThomas Veerman c = setsymtab(p, p, 0.0, CON|STR|DONTFREE, symtab);
4595ea9e707SThomas Veerman free(p);
4605ea9e707SThomas Veerman return c;
4615ea9e707SThomas Veerman }
4625ea9e707SThomas Veerman
tostringN(const char * s,size_t n)4635ea9e707SThomas Veerman char *tostringN(const char *s, size_t n) /* make a copy of string s */
4645ea9e707SThomas Veerman {
4655ea9e707SThomas Veerman char *p;
4665ea9e707SThomas Veerman
4675ea9e707SThomas Veerman p = malloc(n);
4685ea9e707SThomas Veerman if (p == NULL)
4695ea9e707SThomas Veerman FATAL("out of space in tostring on %s", s);
4705ea9e707SThomas Veerman strcpy(p, s);
4715ea9e707SThomas Veerman return(p);
4725ea9e707SThomas Veerman }
4735ea9e707SThomas Veerman
qstring(const char * is,int delim)4745ea9e707SThomas Veerman char *qstring(const char *is, int delim) /* collect string up to next delim */
4755ea9e707SThomas Veerman {
4765ea9e707SThomas Veerman const char *os = is;
4775ea9e707SThomas Veerman int c, n;
4785ea9e707SThomas Veerman const uschar *s = (const uschar *) is;
4795ea9e707SThomas Veerman uschar *buf, *bp;
4805ea9e707SThomas Veerman
4815ea9e707SThomas Veerman if ((buf = malloc(strlen(is)+3)) == NULL)
4825ea9e707SThomas Veerman FATAL( "out of space in qstring(%s)", s);
4835ea9e707SThomas Veerman for (bp = buf; (c = *s) != delim; s++) {
4845ea9e707SThomas Veerman if (c == '\n')
4855ea9e707SThomas Veerman SYNTAX( "newline in string %.20s...", os );
4865ea9e707SThomas Veerman else if (c != '\\')
4875ea9e707SThomas Veerman *bp++ = c;
4885ea9e707SThomas Veerman else { /* \something */
4895ea9e707SThomas Veerman c = *++s;
4905ea9e707SThomas Veerman if (c == 0) { /* \ at end */
4915ea9e707SThomas Veerman *bp++ = '\\';
4925ea9e707SThomas Veerman break; /* for loop */
4935ea9e707SThomas Veerman }
4945ea9e707SThomas Veerman switch (c) {
4955ea9e707SThomas Veerman case '\\': *bp++ = '\\'; break;
4965ea9e707SThomas Veerman case 'n': *bp++ = '\n'; break;
4975ea9e707SThomas Veerman case 't': *bp++ = '\t'; break;
4985ea9e707SThomas Veerman case 'b': *bp++ = '\b'; break;
4995ea9e707SThomas Veerman case 'f': *bp++ = '\f'; break;
5005ea9e707SThomas Veerman case 'r': *bp++ = '\r'; break;
5015ea9e707SThomas Veerman default:
5025ea9e707SThomas Veerman if (!isdigit(c)) {
5035ea9e707SThomas Veerman *bp++ = c;
5045ea9e707SThomas Veerman break;
5055ea9e707SThomas Veerman }
5065ea9e707SThomas Veerman n = c - '0';
5075ea9e707SThomas Veerman if (isdigit(s[1])) {
5085ea9e707SThomas Veerman n = 8 * n + *++s - '0';
5095ea9e707SThomas Veerman if (isdigit(s[1]))
5105ea9e707SThomas Veerman n = 8 * n + *++s - '0';
5115ea9e707SThomas Veerman }
5125ea9e707SThomas Veerman *bp++ = n;
5135ea9e707SThomas Veerman break;
5145ea9e707SThomas Veerman }
5155ea9e707SThomas Veerman }
5165ea9e707SThomas Veerman }
5175ea9e707SThomas Veerman *bp++ = 0;
5185ea9e707SThomas Veerman return (char *) buf;
5195ea9e707SThomas Veerman }
520