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 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 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 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 * 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 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 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 * 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 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 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 * 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 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 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 * 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 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 * 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 * 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 * 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