xref: /minix3/external/historical/nawk/dist/tran.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
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