17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*8ef4c21aSnakanon * Common Development and Distribution License (the "License").
6*8ef4c21aSnakanon * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate
227c478bd9Sstevel@tonic-gate /*
23*8ef4c21aSnakanon * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
271ee2e5faSnakanon /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
281ee2e5faSnakanon /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
301ee2e5faSnakanon #pragma ident "%Z%%M% %I% %E% SMI"
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #define DEBUG
337c478bd9Sstevel@tonic-gate #include <stdio.h>
341ee2e5faSnakanon #include <stdlib.h>
357c478bd9Sstevel@tonic-gate #include <ctype.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include "awk.h"
387c478bd9Sstevel@tonic-gate #include "y.tab.h"
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate #define FULLTAB 2 /* rehash when table gets this x full */
417c478bd9Sstevel@tonic-gate #define GROWTAB 4 /* grow table by this factor */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate Array *symtab; /* main symbol table */
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate uchar **FS; /* initial field sep */
467c478bd9Sstevel@tonic-gate uchar **RS; /* initial record sep */
477c478bd9Sstevel@tonic-gate uchar **OFS; /* output field sep */
487c478bd9Sstevel@tonic-gate uchar **ORS; /* output record sep */
497c478bd9Sstevel@tonic-gate uchar **OFMT; /* output format for numbers */
507c478bd9Sstevel@tonic-gate Awkfloat *NF; /* number of fields in current record */
517c478bd9Sstevel@tonic-gate Awkfloat *NR; /* number of current record */
527c478bd9Sstevel@tonic-gate Awkfloat *FNR; /* number of current record in current file */
537c478bd9Sstevel@tonic-gate uchar **FILENAME; /* current filename argument */
547c478bd9Sstevel@tonic-gate Awkfloat *ARGC; /* number of arguments from command line */
557c478bd9Sstevel@tonic-gate uchar **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */
567c478bd9Sstevel@tonic-gate Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */
577c478bd9Sstevel@tonic-gate Awkfloat *RLENGTH; /* length of same */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate Cell *recloc; /* location of record */
607c478bd9Sstevel@tonic-gate Cell *nrloc; /* NR */
617c478bd9Sstevel@tonic-gate Cell *nfloc; /* NF */
627c478bd9Sstevel@tonic-gate Cell *fnrloc; /* FNR */
637c478bd9Sstevel@tonic-gate Array *ARGVtab; /* symbol table containing ARGV[...] */
647c478bd9Sstevel@tonic-gate Array *ENVtab; /* symbol table containing ENVIRON[...] */
657c478bd9Sstevel@tonic-gate Cell *rstartloc; /* RSTART */
667c478bd9Sstevel@tonic-gate Cell *rlengthloc; /* RLENGTH */
677c478bd9Sstevel@tonic-gate Cell *symtabloc; /* SYMTAB */
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate Cell *nullloc;
707c478bd9Sstevel@tonic-gate Node *nullnode; /* zero&null, converted into a node for comparisons */
717c478bd9Sstevel@tonic-gate
721ee2e5faSnakanon static void rehash(Array *);
737c478bd9Sstevel@tonic-gate
741ee2e5faSnakanon void
syminit(void)751ee2e5faSnakanon syminit(void)
767c478bd9Sstevel@tonic-gate {
77*8ef4c21aSnakanon init_buf(&record, &record_size, LINE_INCR);
787c478bd9Sstevel@tonic-gate
791ee2e5faSnakanon /* initialize $0 */
80*8ef4c21aSnakanon recloc = getfld(0);
81*8ef4c21aSnakanon recloc->nval = (uchar *)"$0";
82*8ef4c21aSnakanon recloc->sval = record;
83*8ef4c21aSnakanon recloc->tval = REC|STR|DONTFREE;
841ee2e5faSnakanon
857c478bd9Sstevel@tonic-gate symtab = makesymtab(NSYMTAB);
861ee2e5faSnakanon (void) setsymtab((uchar *)"0", (uchar *)"0", 0.0,
871ee2e5faSnakanon NUM|STR|CON|DONTFREE, symtab);
887c478bd9Sstevel@tonic-gate /* this is used for if(x)... tests: */
891ee2e5faSnakanon nullloc = setsymtab((uchar *)"$zero&null", (uchar *)"", 0.0,
901ee2e5faSnakanon NUM|STR|CON|DONTFREE, symtab);
917c478bd9Sstevel@tonic-gate nullnode = valtonode(nullloc, CCON);
921ee2e5faSnakanon FS = &setsymtab((uchar *)"FS", (uchar *)" ", 0.0,
931ee2e5faSnakanon STR|DONTFREE, symtab)->sval;
941ee2e5faSnakanon RS = &setsymtab((uchar *)"RS", (uchar *)"\n", 0.0,
951ee2e5faSnakanon STR|DONTFREE, symtab)->sval;
961ee2e5faSnakanon OFS = &setsymtab((uchar *)"OFS", (uchar *)" ", 0.0,
971ee2e5faSnakanon STR|DONTFREE, symtab)->sval;
981ee2e5faSnakanon ORS = &setsymtab((uchar *)"ORS", (uchar *)"\n", 0.0,
991ee2e5faSnakanon STR|DONTFREE, symtab)->sval;
1001ee2e5faSnakanon OFMT = &setsymtab((uchar *)"OFMT", (uchar *)"%.6g", 0.0,
1011ee2e5faSnakanon STR|DONTFREE, symtab)->sval;
1021ee2e5faSnakanon FILENAME = &setsymtab((uchar *)"FILENAME", (uchar *)"-", 0.0,
1031ee2e5faSnakanon STR|DONTFREE, symtab)->sval;
1041ee2e5faSnakanon nfloc = setsymtab((uchar *)"NF", (uchar *)"", 0.0, NUM, symtab);
1057c478bd9Sstevel@tonic-gate NF = &nfloc->fval;
1061ee2e5faSnakanon nrloc = setsymtab((uchar *)"NR", (uchar *)"", 0.0, NUM, symtab);
1077c478bd9Sstevel@tonic-gate NR = &nrloc->fval;
1081ee2e5faSnakanon fnrloc = setsymtab((uchar *)"FNR", (uchar *)"", 0.0, NUM, symtab);
1097c478bd9Sstevel@tonic-gate FNR = &fnrloc->fval;
1101ee2e5faSnakanon SUBSEP = &setsymtab((uchar *)"SUBSEP", (uchar *)"\034", 0.0,
1111ee2e5faSnakanon STR|DONTFREE, symtab)->sval;
1121ee2e5faSnakanon rstartloc = setsymtab((uchar *)"RSTART", (uchar *)"", 0.0,
1131ee2e5faSnakanon NUM, symtab);
1147c478bd9Sstevel@tonic-gate RSTART = &rstartloc->fval;
1151ee2e5faSnakanon rlengthloc = setsymtab((uchar *)"RLENGTH", (uchar *)"", 0.0,
1161ee2e5faSnakanon NUM, symtab);
1177c478bd9Sstevel@tonic-gate RLENGTH = &rlengthloc->fval;
1181ee2e5faSnakanon symtabloc = setsymtab((uchar *)"SYMTAB", (uchar *)"", 0.0, ARR, symtab);
1197c478bd9Sstevel@tonic-gate symtabloc->sval = (uchar *)symtab;
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate
1221ee2e5faSnakanon void
arginit(int ac,uchar * av[])1231ee2e5faSnakanon arginit(int ac, uchar *av[])
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate Cell *cp;
1267c478bd9Sstevel@tonic-gate int i;
1271ee2e5faSnakanon uchar temp[11];
1287c478bd9Sstevel@tonic-gate
1291ee2e5faSnakanon /* first make FILENAME first real argument */
1301ee2e5faSnakanon for (i = 1; i < ac; i++) {
1317c478bd9Sstevel@tonic-gate if (!isclvar(av[i])) {
1321ee2e5faSnakanon (void) setsval(lookup((uchar *)"FILENAME", symtab),
1331ee2e5faSnakanon av[i]);
1347c478bd9Sstevel@tonic-gate break;
1357c478bd9Sstevel@tonic-gate }
1361ee2e5faSnakanon }
1371ee2e5faSnakanon ARGC = &setsymtab((uchar *)"ARGC", (uchar *)"", (Awkfloat)ac,
1381ee2e5faSnakanon NUM, symtab)->fval;
1391ee2e5faSnakanon cp = setsymtab((uchar *)"ARGV", (uchar *)"", 0.0, ARR, symtab);
1407c478bd9Sstevel@tonic-gate ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
1417c478bd9Sstevel@tonic-gate cp->sval = (uchar *) ARGVtab;
1427c478bd9Sstevel@tonic-gate for (i = 0; i < ac; i++) {
1431ee2e5faSnakanon (void) sprintf((char *)temp, "%d", i);
1441ee2e5faSnakanon if (is_number(*av)) {
1451ee2e5faSnakanon (void) setsymtab(temp, *av, atof((const char *)*av),
1461ee2e5faSnakanon STR|NUM, ARGVtab);
1471ee2e5faSnakanon } else {
1481ee2e5faSnakanon (void) setsymtab(temp, *av, 0.0, STR, ARGVtab);
1491ee2e5faSnakanon }
1507c478bd9Sstevel@tonic-gate av++;
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate
1541ee2e5faSnakanon void
envinit(uchar * envp[])1551ee2e5faSnakanon envinit(uchar *envp[])
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate Cell *cp;
1587c478bd9Sstevel@tonic-gate uchar *p;
1597c478bd9Sstevel@tonic-gate
1601ee2e5faSnakanon cp = setsymtab((uchar *)"ENVIRON", (uchar *)"", 0.0, ARR, symtab);
1617c478bd9Sstevel@tonic-gate ENVtab = makesymtab(NSYMTAB);
1627c478bd9Sstevel@tonic-gate cp->sval = (uchar *) ENVtab;
1637c478bd9Sstevel@tonic-gate for (; *envp; envp++) {
1641ee2e5faSnakanon if ((p = (uchar *)strchr((char *)*envp, '=')) == NULL)
1657c478bd9Sstevel@tonic-gate continue;
1667c478bd9Sstevel@tonic-gate *p++ = 0; /* split into two strings at = */
1671ee2e5faSnakanon if (is_number(p)) {
1681ee2e5faSnakanon (void) setsymtab(*envp, p, atof((const char *)p),
1691ee2e5faSnakanon STR|NUM, ENVtab);
1701ee2e5faSnakanon } else {
1711ee2e5faSnakanon (void) setsymtab(*envp, p, 0.0, STR, ENVtab);
1721ee2e5faSnakanon }
1731ee2e5faSnakanon /* restore in case env is passed down to a shell */
1741ee2e5faSnakanon p[-1] = '=';
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate
1781ee2e5faSnakanon Array *
makesymtab(int n)1791ee2e5faSnakanon makesymtab(int n)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate Array *ap;
1827c478bd9Sstevel@tonic-gate Cell **tp;
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate ap = (Array *)malloc(sizeof (Array));
1857c478bd9Sstevel@tonic-gate tp = (Cell **)calloc(n, sizeof (Cell *));
1867c478bd9Sstevel@tonic-gate if (ap == NULL || tp == NULL)
1877c478bd9Sstevel@tonic-gate ERROR "out of space in makesymtab" FATAL;
1887c478bd9Sstevel@tonic-gate ap->nelem = 0;
1897c478bd9Sstevel@tonic-gate ap->size = n;
1907c478bd9Sstevel@tonic-gate ap->tab = tp;
1917c478bd9Sstevel@tonic-gate return (ap);
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate
1941ee2e5faSnakanon void
freesymtab(Cell * ap)1951ee2e5faSnakanon freesymtab(Cell *ap) /* free symbol table */
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate Cell *cp, *next;
1987c478bd9Sstevel@tonic-gate Array *tp;
1997c478bd9Sstevel@tonic-gate int i;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate if (!isarr(ap))
2027c478bd9Sstevel@tonic-gate return;
2031ee2e5faSnakanon /*LINTED align*/
2047c478bd9Sstevel@tonic-gate tp = (Array *)ap->sval;
2057c478bd9Sstevel@tonic-gate if (tp == NULL)
2067c478bd9Sstevel@tonic-gate return;
2077c478bd9Sstevel@tonic-gate for (i = 0; i < tp->size; i++) {
2087c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp != NULL; cp = next) {
2097c478bd9Sstevel@tonic-gate next = cp->cnext;
2107c478bd9Sstevel@tonic-gate xfree(cp->nval);
2117c478bd9Sstevel@tonic-gate if (freeable(cp))
2127c478bd9Sstevel@tonic-gate xfree(cp->sval);
2137c478bd9Sstevel@tonic-gate free(cp);
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate free(tp->tab);
2177c478bd9Sstevel@tonic-gate free(tp);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate
2201ee2e5faSnakanon void
freeelem(Cell * ap,uchar * s)2211ee2e5faSnakanon freeelem(Cell *ap, uchar *s) /* free elem s from ap (i.e., ap["s"] */
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate Array *tp;
2247c478bd9Sstevel@tonic-gate Cell *p, *prev = NULL;
2257c478bd9Sstevel@tonic-gate int h;
2267c478bd9Sstevel@tonic-gate
2271ee2e5faSnakanon /*LINTED align*/
2287c478bd9Sstevel@tonic-gate tp = (Array *)ap->sval;
2297c478bd9Sstevel@tonic-gate h = hash(s, tp->size);
2307c478bd9Sstevel@tonic-gate for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
2317c478bd9Sstevel@tonic-gate if (strcmp((char *)s, (char *)p->nval) == 0) {
2327c478bd9Sstevel@tonic-gate if (prev == NULL) /* 1st one */
2337c478bd9Sstevel@tonic-gate tp->tab[h] = p->cnext;
2347c478bd9Sstevel@tonic-gate else /* middle somewhere */
2357c478bd9Sstevel@tonic-gate prev->cnext = p->cnext;
2367c478bd9Sstevel@tonic-gate if (freeable(p))
2377c478bd9Sstevel@tonic-gate xfree(p->sval);
2387c478bd9Sstevel@tonic-gate free(p->nval);
2397c478bd9Sstevel@tonic-gate free(p);
2407c478bd9Sstevel@tonic-gate tp->nelem--;
2417c478bd9Sstevel@tonic-gate return;
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate
2451ee2e5faSnakanon Cell *
setsymtab(uchar * n,uchar * s,Awkfloat f,unsigned int t,Array * tp)2461ee2e5faSnakanon setsymtab(uchar *n, uchar *s, Awkfloat f, unsigned int t, Array *tp)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate register int h;
2497c478bd9Sstevel@tonic-gate register Cell *p;
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate if (n != NULL && (p = lookup(n, tp)) != NULL) {
2521ee2e5faSnakanon dprintf(("setsymtab found %p: n=%s", (void *)p, p->nval));
2531ee2e5faSnakanon dprintf((" s=\"%s\" f=%g t=%p\n",
2541ee2e5faSnakanon p->sval, p->fval, (void *)p->tval));
2557c478bd9Sstevel@tonic-gate return (p);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate p = (Cell *)malloc(sizeof (Cell));
2587c478bd9Sstevel@tonic-gate if (p == NULL)
2597c478bd9Sstevel@tonic-gate ERROR "symbol table overflow at %s", n FATAL;
2607c478bd9Sstevel@tonic-gate p->nval = tostring(n);
2611ee2e5faSnakanon p->sval = s ? tostring(s) : tostring((uchar *)"");
2627c478bd9Sstevel@tonic-gate p->fval = f;
2637c478bd9Sstevel@tonic-gate p->tval = t;
2647c478bd9Sstevel@tonic-gate p->csub = 0;
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate tp->nelem++;
2677c478bd9Sstevel@tonic-gate if (tp->nelem > FULLTAB * tp->size)
2687c478bd9Sstevel@tonic-gate rehash(tp);
2697c478bd9Sstevel@tonic-gate h = hash(n, tp->size);
2707c478bd9Sstevel@tonic-gate p->cnext = tp->tab[h];
2717c478bd9Sstevel@tonic-gate tp->tab[h] = p;
2721ee2e5faSnakanon dprintf(("setsymtab set %p: n=%s", (void *)p, p->nval));
2731ee2e5faSnakanon dprintf((" s=\"%s\" f=%g t=%p\n", p->sval, p->fval, (void *)p->tval));
2747c478bd9Sstevel@tonic-gate return (p);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate
2771ee2e5faSnakanon int
hash(uchar * s,int n)2781ee2e5faSnakanon hash(uchar *s, int n) /* form hash value for string s */
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate register unsigned hashval;
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate for (hashval = 0; *s != '\0'; s++)
2837c478bd9Sstevel@tonic-gate hashval = (*s + 31 * hashval);
2841ee2e5faSnakanon return (hashval % n);
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate
2871ee2e5faSnakanon static void
rehash(Array * tp)2881ee2e5faSnakanon rehash(Array *tp) /* rehash items in small table into big one */
2897c478bd9Sstevel@tonic-gate {
2907c478bd9Sstevel@tonic-gate int i, nh, nsz;
2917c478bd9Sstevel@tonic-gate Cell *cp, *op, **np;
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate nsz = GROWTAB * tp->size;
2947c478bd9Sstevel@tonic-gate np = (Cell **)calloc(nsz, sizeof (Cell *));
2957c478bd9Sstevel@tonic-gate if (np == NULL)
2967c478bd9Sstevel@tonic-gate ERROR "out of space in rehash" FATAL;
2977c478bd9Sstevel@tonic-gate for (i = 0; i < tp->size; i++) {
2987c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp; cp = op) {
2997c478bd9Sstevel@tonic-gate op = cp->cnext;
3007c478bd9Sstevel@tonic-gate nh = hash(cp->nval, nsz);
3017c478bd9Sstevel@tonic-gate cp->cnext = np[nh];
3027c478bd9Sstevel@tonic-gate np[nh] = cp;
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate free(tp->tab);
3067c478bd9Sstevel@tonic-gate tp->tab = np;
3077c478bd9Sstevel@tonic-gate tp->size = nsz;
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3101ee2e5faSnakanon Cell *
lookup(uchar * s,Array * tp)3111ee2e5faSnakanon lookup(uchar *s, Array *tp) /* look for s in tp */
3127c478bd9Sstevel@tonic-gate {
3131ee2e5faSnakanon register Cell *p;
3147c478bd9Sstevel@tonic-gate int h;
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate h = hash(s, tp->size);
3171ee2e5faSnakanon for (p = tp->tab[h]; p != NULL; p = p->cnext) {
3187c478bd9Sstevel@tonic-gate if (strcmp((char *)s, (char *)p->nval) == 0)
3197c478bd9Sstevel@tonic-gate return (p); /* found it */
3201ee2e5faSnakanon }
3217c478bd9Sstevel@tonic-gate return (NULL); /* not found */
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3241ee2e5faSnakanon Awkfloat
setfval(Cell * vp,Awkfloat f)3251ee2e5faSnakanon setfval(Cell *vp, Awkfloat f)
3267c478bd9Sstevel@tonic-gate {
3271ee2e5faSnakanon int i;
3281ee2e5faSnakanon
3297c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0)
3307c478bd9Sstevel@tonic-gate funnyvar(vp, "assign to");
3317c478bd9Sstevel@tonic-gate if (vp->tval & FLD) {
3327c478bd9Sstevel@tonic-gate donerec = 0; /* mark $0 invalid */
3331ee2e5faSnakanon i = fldidx(vp);
3341ee2e5faSnakanon if (i > *NF)
3351ee2e5faSnakanon newfld(i);
3361ee2e5faSnakanon dprintf(("setting field %d to %g\n", i, f));
3377c478bd9Sstevel@tonic-gate } else if (vp->tval & REC) {
3387c478bd9Sstevel@tonic-gate donefld = 0; /* mark $1... invalid */
3397c478bd9Sstevel@tonic-gate donerec = 1;
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate vp->tval &= ~STR; /* mark string invalid */
3427c478bd9Sstevel@tonic-gate vp->tval |= NUM; /* mark number ok */
3431ee2e5faSnakanon dprintf(("setfval %p: %s = %g, t=%p\n", (void *)vp,
3447c478bd9Sstevel@tonic-gate vp->nval ? vp->nval : (unsigned char *)"NULL",
3451ee2e5faSnakanon f, (void *)vp->tval));
3461ee2e5faSnakanon return (vp->fval = f);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3491ee2e5faSnakanon void
funnyvar(Cell * vp,char * rw)3501ee2e5faSnakanon funnyvar(Cell *vp, char *rw)
3517c478bd9Sstevel@tonic-gate {
3527c478bd9Sstevel@tonic-gate if (vp->tval & ARR)
3537c478bd9Sstevel@tonic-gate ERROR "can't %s %s; it's an array name.", rw, vp->nval FATAL;
3547c478bd9Sstevel@tonic-gate if (vp->tval & FCN)
3557c478bd9Sstevel@tonic-gate ERROR "can't %s %s; it's a function.", rw, vp->nval FATAL;
3567c478bd9Sstevel@tonic-gate ERROR "funny variable %o: n=%s s=\"%s\" f=%g t=%o",
3571ee2e5faSnakanon vp, vp->nval, vp->sval, vp->fval, vp->tval CONT;
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
3601ee2e5faSnakanon uchar *
setsval(Cell * vp,uchar * s)3611ee2e5faSnakanon setsval(Cell *vp, uchar *s)
3627c478bd9Sstevel@tonic-gate {
3631ee2e5faSnakanon int i;
3641ee2e5faSnakanon
3657c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0)
3667c478bd9Sstevel@tonic-gate funnyvar(vp, "assign to");
3677c478bd9Sstevel@tonic-gate if (vp->tval & FLD) {
3687c478bd9Sstevel@tonic-gate donerec = 0; /* mark $0 invalid */
3691ee2e5faSnakanon i = fldidx(vp);
3701ee2e5faSnakanon if (i > *NF)
3711ee2e5faSnakanon newfld(i);
3721ee2e5faSnakanon dprintf(("setting field %d to %s\n", i, s));
3737c478bd9Sstevel@tonic-gate } else if (vp->tval & REC) {
3747c478bd9Sstevel@tonic-gate donefld = 0; /* mark $1... invalid */
3757c478bd9Sstevel@tonic-gate donerec = 1;
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate vp->tval &= ~NUM;
3787c478bd9Sstevel@tonic-gate vp->tval |= STR;
3797c478bd9Sstevel@tonic-gate if (freeable(vp))
3807c478bd9Sstevel@tonic-gate xfree(vp->sval);
3817c478bd9Sstevel@tonic-gate vp->tval &= ~DONTFREE;
3821ee2e5faSnakanon dprintf(("setsval %p: %s = \"%s\", t=%p\n",
3831ee2e5faSnakanon (void *)vp,
3841ee2e5faSnakanon vp->nval ? (char *)vp->nval : "",
3851ee2e5faSnakanon s,
3861ee2e5faSnakanon (void *)(vp->tval ? (char *)vp->tval : "")));
3877c478bd9Sstevel@tonic-gate return (vp->sval = tostring(s));
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate
3901ee2e5faSnakanon Awkfloat
r_getfval(Cell * vp)3911ee2e5faSnakanon r_getfval(Cell *vp)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0)
3947c478bd9Sstevel@tonic-gate funnyvar(vp, "read value of");
3957c478bd9Sstevel@tonic-gate if ((vp->tval & FLD) && donefld == 0)
3967c478bd9Sstevel@tonic-gate fldbld();
3977c478bd9Sstevel@tonic-gate else if ((vp->tval & REC) && donerec == 0)
3987c478bd9Sstevel@tonic-gate recbld();
3997c478bd9Sstevel@tonic-gate if (!isnum(vp)) { /* not a number */
4001ee2e5faSnakanon vp->fval = atof((const char *)vp->sval); /* best guess */
4011ee2e5faSnakanon if (is_number(vp->sval) && !(vp->tval&CON))
4027c478bd9Sstevel@tonic-gate vp->tval |= NUM; /* make NUM only sparingly */
4037c478bd9Sstevel@tonic-gate }
4041ee2e5faSnakanon dprintf(("getfval %p: %s = %g, t=%p\n",
4051ee2e5faSnakanon (void *)vp, vp->nval, vp->fval, (void *)vp->tval));
4067c478bd9Sstevel@tonic-gate return (vp->fval);
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate
4091ee2e5faSnakanon uchar *
r_getsval(Cell * vp)4101ee2e5faSnakanon r_getsval(Cell *vp)
4117c478bd9Sstevel@tonic-gate {
4121ee2e5faSnakanon uchar s[256];
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0)
4157c478bd9Sstevel@tonic-gate funnyvar(vp, "read value of");
4167c478bd9Sstevel@tonic-gate if ((vp->tval & FLD) && donefld == 0)
4177c478bd9Sstevel@tonic-gate fldbld();
4187c478bd9Sstevel@tonic-gate else if ((vp->tval & REC) && donerec == 0)
4197c478bd9Sstevel@tonic-gate recbld();
4207c478bd9Sstevel@tonic-gate if ((vp->tval & STR) == 0) {
4217c478bd9Sstevel@tonic-gate if (!(vp->tval&DONTFREE))
4227c478bd9Sstevel@tonic-gate xfree(vp->sval);
4231ee2e5faSnakanon if ((long long)vp->fval == vp->fval) {
4241ee2e5faSnakanon (void) snprintf((char *)s, sizeof (s),
4251ee2e5faSnakanon "%.20g", vp->fval);
4261ee2e5faSnakanon } else {
4271ee2e5faSnakanon /*LINTED*/
4281ee2e5faSnakanon (void) snprintf((char *)s, sizeof (s),
4291ee2e5faSnakanon (char *)*OFMT, vp->fval);
4301ee2e5faSnakanon }
4317c478bd9Sstevel@tonic-gate vp->sval = tostring(s);
4327c478bd9Sstevel@tonic-gate vp->tval &= ~DONTFREE;
4337c478bd9Sstevel@tonic-gate vp->tval |= STR;
4347c478bd9Sstevel@tonic-gate }
4351ee2e5faSnakanon dprintf(("getsval %p: %s = \"%s\", t=%p\n",
4361ee2e5faSnakanon (void *)vp,
4371ee2e5faSnakanon vp->nval ? (char *)vp->nval : "",
4381ee2e5faSnakanon vp->sval ? (char *)vp->sval : "",
4391ee2e5faSnakanon (void *)vp->tval));
4407c478bd9Sstevel@tonic-gate return (vp->sval);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate
4431ee2e5faSnakanon uchar *
tostring(uchar * s)4441ee2e5faSnakanon tostring(uchar *s)
4457c478bd9Sstevel@tonic-gate {
4467c478bd9Sstevel@tonic-gate register uchar *p;
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate p = (uchar *)malloc(strlen((char *)s)+1);
4497c478bd9Sstevel@tonic-gate if (p == NULL)
4507c478bd9Sstevel@tonic-gate ERROR "out of space in tostring on %s", s FATAL;
4511ee2e5faSnakanon (void) strcpy((char *)p, (char *)s);
4527c478bd9Sstevel@tonic-gate return (p);
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate
4551ee2e5faSnakanon uchar *
qstring(uchar * s,int delim)4561ee2e5faSnakanon qstring(uchar *s, int delim) /* collect string up to delim */
4577c478bd9Sstevel@tonic-gate {
4581ee2e5faSnakanon uchar *cbuf, *ret;
4597c478bd9Sstevel@tonic-gate int c, n;
4601ee2e5faSnakanon size_t cbufsz, cnt;
4617c478bd9Sstevel@tonic-gate
4621ee2e5faSnakanon init_buf(&cbuf, &cbufsz, LINE_INCR);
4631ee2e5faSnakanon
4641ee2e5faSnakanon for (cnt = 0; (c = *s) != delim; s++) {
4651ee2e5faSnakanon if (c == '\n') {
4667c478bd9Sstevel@tonic-gate ERROR "newline in string %.10s...", cbuf SYNTAX;
4671ee2e5faSnakanon } else if (c != '\\') {
4681ee2e5faSnakanon expand_buf(&cbuf, &cbufsz, cnt);
4691ee2e5faSnakanon cbuf[cnt++] = c;
4701ee2e5faSnakanon } else { /* \something */
4711ee2e5faSnakanon expand_buf(&cbuf, &cbufsz, cnt);
4727c478bd9Sstevel@tonic-gate switch (c = *++s) {
4731ee2e5faSnakanon case '\\': cbuf[cnt++] = '\\'; break;
4741ee2e5faSnakanon case 'n': cbuf[cnt++] = '\n'; break;
4751ee2e5faSnakanon case 't': cbuf[cnt++] = '\t'; break;
4761ee2e5faSnakanon case 'b': cbuf[cnt++] = '\b'; break;
4771ee2e5faSnakanon case 'f': cbuf[cnt++] = '\f'; break;
4781ee2e5faSnakanon case 'r': cbuf[cnt++] = '\r'; break;
4797c478bd9Sstevel@tonic-gate default:
4807c478bd9Sstevel@tonic-gate if (!isdigit(c)) {
4811ee2e5faSnakanon cbuf[cnt++] = c;
4827c478bd9Sstevel@tonic-gate break;
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate n = c - '0';
4857c478bd9Sstevel@tonic-gate if (isdigit(s[1])) {
4867c478bd9Sstevel@tonic-gate n = 8 * n + *++s - '0';
4877c478bd9Sstevel@tonic-gate if (isdigit(s[1]))
4887c478bd9Sstevel@tonic-gate n = 8 * n + *++s - '0';
4897c478bd9Sstevel@tonic-gate }
4901ee2e5faSnakanon cbuf[cnt++] = n;
4917c478bd9Sstevel@tonic-gate break;
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate }
4941ee2e5faSnakanon }
4951ee2e5faSnakanon cbuf[cnt] = '\0';
4961ee2e5faSnakanon ret = tostring(cbuf);
4971ee2e5faSnakanon free(cbuf);
4981ee2e5faSnakanon return (ret);
4997c478bd9Sstevel@tonic-gate }
500