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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 24*1ee2e5faSnakanon * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 28*1ee2e5faSnakanon /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29*1ee2e5faSnakanon /* All Rights Reserved */ 307c478bd9Sstevel@tonic-gate 31*1ee2e5faSnakanon #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #define DEBUG 347c478bd9Sstevel@tonic-gate #include <stdio.h> 35*1ee2e5faSnakanon #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include <ctype.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 387c478bd9Sstevel@tonic-gate #include "awk.h" 397c478bd9Sstevel@tonic-gate #include "y.tab.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #define FULLTAB 2 /* rehash when table gets this x full */ 427c478bd9Sstevel@tonic-gate #define GROWTAB 4 /* grow table by this factor */ 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate Array *symtab; /* main symbol table */ 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate uchar **FS; /* initial field sep */ 477c478bd9Sstevel@tonic-gate uchar **RS; /* initial record sep */ 487c478bd9Sstevel@tonic-gate uchar **OFS; /* output field sep */ 497c478bd9Sstevel@tonic-gate uchar **ORS; /* output record sep */ 507c478bd9Sstevel@tonic-gate uchar **OFMT; /* output format for numbers */ 517c478bd9Sstevel@tonic-gate Awkfloat *NF; /* number of fields in current record */ 527c478bd9Sstevel@tonic-gate Awkfloat *NR; /* number of current record */ 537c478bd9Sstevel@tonic-gate Awkfloat *FNR; /* number of current record in current file */ 547c478bd9Sstevel@tonic-gate uchar **FILENAME; /* current filename argument */ 557c478bd9Sstevel@tonic-gate Awkfloat *ARGC; /* number of arguments from command line */ 567c478bd9Sstevel@tonic-gate uchar **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */ 577c478bd9Sstevel@tonic-gate Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */ 587c478bd9Sstevel@tonic-gate Awkfloat *RLENGTH; /* length of same */ 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate Cell *recloc; /* location of record */ 617c478bd9Sstevel@tonic-gate Cell *nrloc; /* NR */ 627c478bd9Sstevel@tonic-gate Cell *nfloc; /* NF */ 637c478bd9Sstevel@tonic-gate Cell *fnrloc; /* FNR */ 647c478bd9Sstevel@tonic-gate Array *ARGVtab; /* symbol table containing ARGV[...] */ 657c478bd9Sstevel@tonic-gate Array *ENVtab; /* symbol table containing ENVIRON[...] */ 667c478bd9Sstevel@tonic-gate Cell *rstartloc; /* RSTART */ 677c478bd9Sstevel@tonic-gate Cell *rlengthloc; /* RLENGTH */ 687c478bd9Sstevel@tonic-gate Cell *symtabloc; /* SYMTAB */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate Cell *nullloc; 717c478bd9Sstevel@tonic-gate Node *nullnode; /* zero&null, converted into a node for comparisons */ 727c478bd9Sstevel@tonic-gate 73*1ee2e5faSnakanon static void rehash(Array *); 747c478bd9Sstevel@tonic-gate 75*1ee2e5faSnakanon void 76*1ee2e5faSnakanon syminit(void) 777c478bd9Sstevel@tonic-gate { 78*1ee2e5faSnakanon Cell *p; 797c478bd9Sstevel@tonic-gate 80*1ee2e5faSnakanon init_buf(&recdata, &record_size, LINE_INCR); 81*1ee2e5faSnakanon record = recdata; 827c478bd9Sstevel@tonic-gate 83*1ee2e5faSnakanon p = getfld(0); 84*1ee2e5faSnakanon /* initialize $0 */ 85*1ee2e5faSnakanon p->nval = (uchar*) "$0"; 86*1ee2e5faSnakanon p->sval = recdata; 87*1ee2e5faSnakanon p->tval = REC|STR|DONTFREE; 88*1ee2e5faSnakanon 897c478bd9Sstevel@tonic-gate symtab = makesymtab(NSYMTAB); 90*1ee2e5faSnakanon (void) setsymtab((uchar *)"0", (uchar *)"0", 0.0, 91*1ee2e5faSnakanon NUM|STR|CON|DONTFREE, symtab); 927c478bd9Sstevel@tonic-gate /* this is used for if(x)... tests: */ 93*1ee2e5faSnakanon nullloc = setsymtab((uchar *)"$zero&null", (uchar *)"", 0.0, 94*1ee2e5faSnakanon NUM|STR|CON|DONTFREE, symtab); 957c478bd9Sstevel@tonic-gate nullnode = valtonode(nullloc, CCON); 96*1ee2e5faSnakanon recloc = getfld(0); 97*1ee2e5faSnakanon FS = &setsymtab((uchar *)"FS", (uchar *)" ", 0.0, 98*1ee2e5faSnakanon STR|DONTFREE, symtab)->sval; 99*1ee2e5faSnakanon RS = &setsymtab((uchar *)"RS", (uchar *)"\n", 0.0, 100*1ee2e5faSnakanon STR|DONTFREE, symtab)->sval; 101*1ee2e5faSnakanon OFS = &setsymtab((uchar *)"OFS", (uchar *)" ", 0.0, 102*1ee2e5faSnakanon STR|DONTFREE, symtab)->sval; 103*1ee2e5faSnakanon ORS = &setsymtab((uchar *)"ORS", (uchar *)"\n", 0.0, 104*1ee2e5faSnakanon STR|DONTFREE, symtab)->sval; 105*1ee2e5faSnakanon OFMT = &setsymtab((uchar *)"OFMT", (uchar *)"%.6g", 0.0, 106*1ee2e5faSnakanon STR|DONTFREE, symtab)->sval; 107*1ee2e5faSnakanon FILENAME = &setsymtab((uchar *)"FILENAME", (uchar *)"-", 0.0, 108*1ee2e5faSnakanon STR|DONTFREE, symtab)->sval; 109*1ee2e5faSnakanon nfloc = setsymtab((uchar *)"NF", (uchar *)"", 0.0, NUM, symtab); 1107c478bd9Sstevel@tonic-gate NF = &nfloc->fval; 111*1ee2e5faSnakanon nrloc = setsymtab((uchar *)"NR", (uchar *)"", 0.0, NUM, symtab); 1127c478bd9Sstevel@tonic-gate NR = &nrloc->fval; 113*1ee2e5faSnakanon fnrloc = setsymtab((uchar *)"FNR", (uchar *)"", 0.0, NUM, symtab); 1147c478bd9Sstevel@tonic-gate FNR = &fnrloc->fval; 115*1ee2e5faSnakanon SUBSEP = &setsymtab((uchar *)"SUBSEP", (uchar *)"\034", 0.0, 116*1ee2e5faSnakanon STR|DONTFREE, symtab)->sval; 117*1ee2e5faSnakanon rstartloc = setsymtab((uchar *)"RSTART", (uchar *)"", 0.0, 118*1ee2e5faSnakanon NUM, symtab); 1197c478bd9Sstevel@tonic-gate RSTART = &rstartloc->fval; 120*1ee2e5faSnakanon rlengthloc = setsymtab((uchar *)"RLENGTH", (uchar *)"", 0.0, 121*1ee2e5faSnakanon NUM, symtab); 1227c478bd9Sstevel@tonic-gate RLENGTH = &rlengthloc->fval; 123*1ee2e5faSnakanon symtabloc = setsymtab((uchar *)"SYMTAB", (uchar *)"", 0.0, ARR, symtab); 1247c478bd9Sstevel@tonic-gate symtabloc->sval = (uchar *)symtab; 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 127*1ee2e5faSnakanon void 128*1ee2e5faSnakanon arginit(int ac, uchar *av[]) 1297c478bd9Sstevel@tonic-gate { 1307c478bd9Sstevel@tonic-gate Cell *cp; 1317c478bd9Sstevel@tonic-gate int i; 132*1ee2e5faSnakanon uchar temp[11]; 1337c478bd9Sstevel@tonic-gate 134*1ee2e5faSnakanon /* first make FILENAME first real argument */ 135*1ee2e5faSnakanon for (i = 1; i < ac; i++) { 1367c478bd9Sstevel@tonic-gate if (!isclvar(av[i])) { 137*1ee2e5faSnakanon (void) setsval(lookup((uchar *)"FILENAME", symtab), 138*1ee2e5faSnakanon av[i]); 1397c478bd9Sstevel@tonic-gate break; 1407c478bd9Sstevel@tonic-gate } 141*1ee2e5faSnakanon } 142*1ee2e5faSnakanon ARGC = &setsymtab((uchar *)"ARGC", (uchar *)"", (Awkfloat)ac, 143*1ee2e5faSnakanon NUM, symtab)->fval; 144*1ee2e5faSnakanon cp = setsymtab((uchar *)"ARGV", (uchar *)"", 0.0, ARR, symtab); 1457c478bd9Sstevel@tonic-gate ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */ 1467c478bd9Sstevel@tonic-gate cp->sval = (uchar *) ARGVtab; 1477c478bd9Sstevel@tonic-gate for (i = 0; i < ac; i++) { 148*1ee2e5faSnakanon (void) sprintf((char *)temp, "%d", i); 149*1ee2e5faSnakanon if (is_number(*av)) { 150*1ee2e5faSnakanon (void) setsymtab(temp, *av, atof((const char *)*av), 151*1ee2e5faSnakanon STR|NUM, ARGVtab); 152*1ee2e5faSnakanon } else { 153*1ee2e5faSnakanon (void) setsymtab(temp, *av, 0.0, STR, ARGVtab); 154*1ee2e5faSnakanon } 1557c478bd9Sstevel@tonic-gate av++; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 159*1ee2e5faSnakanon void 160*1ee2e5faSnakanon envinit(uchar *envp[]) 1617c478bd9Sstevel@tonic-gate { 1627c478bd9Sstevel@tonic-gate Cell *cp; 1637c478bd9Sstevel@tonic-gate uchar *p; 1647c478bd9Sstevel@tonic-gate 165*1ee2e5faSnakanon cp = setsymtab((uchar *)"ENVIRON", (uchar *)"", 0.0, ARR, symtab); 1667c478bd9Sstevel@tonic-gate ENVtab = makesymtab(NSYMTAB); 1677c478bd9Sstevel@tonic-gate cp->sval = (uchar *) ENVtab; 1687c478bd9Sstevel@tonic-gate for (; *envp; envp++) { 169*1ee2e5faSnakanon if ((p = (uchar *)strchr((char *)*envp, '=')) == NULL) 1707c478bd9Sstevel@tonic-gate continue; 1717c478bd9Sstevel@tonic-gate *p++ = 0; /* split into two strings at = */ 172*1ee2e5faSnakanon if (is_number(p)) { 173*1ee2e5faSnakanon (void) setsymtab(*envp, p, atof((const char *)p), 174*1ee2e5faSnakanon STR|NUM, ENVtab); 175*1ee2e5faSnakanon } else { 176*1ee2e5faSnakanon (void) setsymtab(*envp, p, 0.0, STR, ENVtab); 177*1ee2e5faSnakanon } 178*1ee2e5faSnakanon /* restore in case env is passed down to a shell */ 179*1ee2e5faSnakanon p[-1] = '='; 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 183*1ee2e5faSnakanon Array * 184*1ee2e5faSnakanon makesymtab(int n) 1857c478bd9Sstevel@tonic-gate { 1867c478bd9Sstevel@tonic-gate Array *ap; 1877c478bd9Sstevel@tonic-gate Cell **tp; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate ap = (Array *)malloc(sizeof (Array)); 1907c478bd9Sstevel@tonic-gate tp = (Cell **)calloc(n, sizeof (Cell *)); 1917c478bd9Sstevel@tonic-gate if (ap == NULL || tp == NULL) 1927c478bd9Sstevel@tonic-gate ERROR "out of space in makesymtab" FATAL; 1937c478bd9Sstevel@tonic-gate ap->nelem = 0; 1947c478bd9Sstevel@tonic-gate ap->size = n; 1957c478bd9Sstevel@tonic-gate ap->tab = tp; 1967c478bd9Sstevel@tonic-gate return (ap); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 199*1ee2e5faSnakanon void 200*1ee2e5faSnakanon freesymtab(Cell *ap) /* free symbol table */ 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate Cell *cp, *next; 2037c478bd9Sstevel@tonic-gate Array *tp; 2047c478bd9Sstevel@tonic-gate int i; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (!isarr(ap)) 2077c478bd9Sstevel@tonic-gate return; 208*1ee2e5faSnakanon /*LINTED align*/ 2097c478bd9Sstevel@tonic-gate tp = (Array *)ap->sval; 2107c478bd9Sstevel@tonic-gate if (tp == NULL) 2117c478bd9Sstevel@tonic-gate return; 2127c478bd9Sstevel@tonic-gate for (i = 0; i < tp->size; i++) { 2137c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp != NULL; cp = next) { 2147c478bd9Sstevel@tonic-gate next = cp->cnext; 2157c478bd9Sstevel@tonic-gate xfree(cp->nval); 2167c478bd9Sstevel@tonic-gate if (freeable(cp)) 2177c478bd9Sstevel@tonic-gate xfree(cp->sval); 2187c478bd9Sstevel@tonic-gate free(cp); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate free(tp->tab); 2227c478bd9Sstevel@tonic-gate free(tp); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 225*1ee2e5faSnakanon void 226*1ee2e5faSnakanon freeelem(Cell *ap, uchar *s) /* free elem s from ap (i.e., ap["s"] */ 2277c478bd9Sstevel@tonic-gate { 2287c478bd9Sstevel@tonic-gate Array *tp; 2297c478bd9Sstevel@tonic-gate Cell *p, *prev = NULL; 2307c478bd9Sstevel@tonic-gate int h; 2317c478bd9Sstevel@tonic-gate 232*1ee2e5faSnakanon /*LINTED align*/ 2337c478bd9Sstevel@tonic-gate tp = (Array *)ap->sval; 2347c478bd9Sstevel@tonic-gate h = hash(s, tp->size); 2357c478bd9Sstevel@tonic-gate for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) 2367c478bd9Sstevel@tonic-gate if (strcmp((char *)s, (char *)p->nval) == 0) { 2377c478bd9Sstevel@tonic-gate if (prev == NULL) /* 1st one */ 2387c478bd9Sstevel@tonic-gate tp->tab[h] = p->cnext; 2397c478bd9Sstevel@tonic-gate else /* middle somewhere */ 2407c478bd9Sstevel@tonic-gate prev->cnext = p->cnext; 2417c478bd9Sstevel@tonic-gate if (freeable(p)) 2427c478bd9Sstevel@tonic-gate xfree(p->sval); 2437c478bd9Sstevel@tonic-gate free(p->nval); 2447c478bd9Sstevel@tonic-gate free(p); 2457c478bd9Sstevel@tonic-gate tp->nelem--; 2467c478bd9Sstevel@tonic-gate return; 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 250*1ee2e5faSnakanon Cell * 251*1ee2e5faSnakanon setsymtab(uchar *n, uchar *s, Awkfloat f, unsigned int t, Array *tp) 2527c478bd9Sstevel@tonic-gate { 2537c478bd9Sstevel@tonic-gate register int h; 2547c478bd9Sstevel@tonic-gate register Cell *p; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate if (n != NULL && (p = lookup(n, tp)) != NULL) { 257*1ee2e5faSnakanon dprintf(("setsymtab found %p: n=%s", (void *)p, p->nval)); 258*1ee2e5faSnakanon dprintf((" s=\"%s\" f=%g t=%p\n", 259*1ee2e5faSnakanon p->sval, p->fval, (void *)p->tval)); 2607c478bd9Sstevel@tonic-gate return (p); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate p = (Cell *)malloc(sizeof (Cell)); 2637c478bd9Sstevel@tonic-gate if (p == NULL) 2647c478bd9Sstevel@tonic-gate ERROR "symbol table overflow at %s", n FATAL; 2657c478bd9Sstevel@tonic-gate p->nval = tostring(n); 266*1ee2e5faSnakanon p->sval = s ? tostring(s) : tostring((uchar *)""); 2677c478bd9Sstevel@tonic-gate p->fval = f; 2687c478bd9Sstevel@tonic-gate p->tval = t; 2697c478bd9Sstevel@tonic-gate p->csub = 0; 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate tp->nelem++; 2727c478bd9Sstevel@tonic-gate if (tp->nelem > FULLTAB * tp->size) 2737c478bd9Sstevel@tonic-gate rehash(tp); 2747c478bd9Sstevel@tonic-gate h = hash(n, tp->size); 2757c478bd9Sstevel@tonic-gate p->cnext = tp->tab[h]; 2767c478bd9Sstevel@tonic-gate tp->tab[h] = p; 277*1ee2e5faSnakanon dprintf(("setsymtab set %p: n=%s", (void *)p, p->nval)); 278*1ee2e5faSnakanon dprintf((" s=\"%s\" f=%g t=%p\n", p->sval, p->fval, (void *)p->tval)); 2797c478bd9Sstevel@tonic-gate return (p); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 282*1ee2e5faSnakanon int 283*1ee2e5faSnakanon hash(uchar *s, int n) /* form hash value for string s */ 2847c478bd9Sstevel@tonic-gate { 2857c478bd9Sstevel@tonic-gate register unsigned hashval; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate for (hashval = 0; *s != '\0'; s++) 2887c478bd9Sstevel@tonic-gate hashval = (*s + 31 * hashval); 289*1ee2e5faSnakanon return (hashval % n); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 292*1ee2e5faSnakanon static void 293*1ee2e5faSnakanon rehash(Array *tp) /* rehash items in small table into big one */ 2947c478bd9Sstevel@tonic-gate { 2957c478bd9Sstevel@tonic-gate int i, nh, nsz; 2967c478bd9Sstevel@tonic-gate Cell *cp, *op, **np; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate nsz = GROWTAB * tp->size; 2997c478bd9Sstevel@tonic-gate np = (Cell **)calloc(nsz, sizeof (Cell *)); 3007c478bd9Sstevel@tonic-gate if (np == NULL) 3017c478bd9Sstevel@tonic-gate ERROR "out of space in rehash" FATAL; 3027c478bd9Sstevel@tonic-gate for (i = 0; i < tp->size; i++) { 3037c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp; cp = op) { 3047c478bd9Sstevel@tonic-gate op = cp->cnext; 3057c478bd9Sstevel@tonic-gate nh = hash(cp->nval, nsz); 3067c478bd9Sstevel@tonic-gate cp->cnext = np[nh]; 3077c478bd9Sstevel@tonic-gate np[nh] = cp; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate free(tp->tab); 3117c478bd9Sstevel@tonic-gate tp->tab = np; 3127c478bd9Sstevel@tonic-gate tp->size = nsz; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 315*1ee2e5faSnakanon Cell * 316*1ee2e5faSnakanon lookup(uchar *s, Array *tp) /* look for s in tp */ 3177c478bd9Sstevel@tonic-gate { 318*1ee2e5faSnakanon register Cell *p; 3197c478bd9Sstevel@tonic-gate int h; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate h = hash(s, tp->size); 322*1ee2e5faSnakanon for (p = tp->tab[h]; p != NULL; p = p->cnext) { 3237c478bd9Sstevel@tonic-gate if (strcmp((char *)s, (char *)p->nval) == 0) 3247c478bd9Sstevel@tonic-gate return (p); /* found it */ 325*1ee2e5faSnakanon } 3267c478bd9Sstevel@tonic-gate return (NULL); /* not found */ 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 329*1ee2e5faSnakanon Awkfloat 330*1ee2e5faSnakanon setfval(Cell *vp, Awkfloat f) 3317c478bd9Sstevel@tonic-gate { 332*1ee2e5faSnakanon int i; 333*1ee2e5faSnakanon 3347c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0) 3357c478bd9Sstevel@tonic-gate funnyvar(vp, "assign to"); 3367c478bd9Sstevel@tonic-gate if (vp->tval & FLD) { 3377c478bd9Sstevel@tonic-gate donerec = 0; /* mark $0 invalid */ 338*1ee2e5faSnakanon i = fldidx(vp); 339*1ee2e5faSnakanon if (i > *NF) 340*1ee2e5faSnakanon newfld(i); 341*1ee2e5faSnakanon dprintf(("setting field %d to %g\n", i, f)); 3427c478bd9Sstevel@tonic-gate } else if (vp->tval & REC) { 3437c478bd9Sstevel@tonic-gate donefld = 0; /* mark $1... invalid */ 3447c478bd9Sstevel@tonic-gate donerec = 1; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate vp->tval &= ~STR; /* mark string invalid */ 3477c478bd9Sstevel@tonic-gate vp->tval |= NUM; /* mark number ok */ 348*1ee2e5faSnakanon dprintf(("setfval %p: %s = %g, t=%p\n", (void *)vp, 3497c478bd9Sstevel@tonic-gate vp->nval ? vp->nval : (unsigned char *)"NULL", 350*1ee2e5faSnakanon f, (void *)vp->tval)); 351*1ee2e5faSnakanon return (vp->fval = f); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 354*1ee2e5faSnakanon void 355*1ee2e5faSnakanon funnyvar(Cell *vp, char *rw) 3567c478bd9Sstevel@tonic-gate { 3577c478bd9Sstevel@tonic-gate if (vp->tval & ARR) 3587c478bd9Sstevel@tonic-gate ERROR "can't %s %s; it's an array name.", rw, vp->nval FATAL; 3597c478bd9Sstevel@tonic-gate if (vp->tval & FCN) 3607c478bd9Sstevel@tonic-gate ERROR "can't %s %s; it's a function.", rw, vp->nval FATAL; 3617c478bd9Sstevel@tonic-gate ERROR "funny variable %o: n=%s s=\"%s\" f=%g t=%o", 362*1ee2e5faSnakanon vp, vp->nval, vp->sval, vp->fval, vp->tval CONT; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 365*1ee2e5faSnakanon uchar * 366*1ee2e5faSnakanon setsval(Cell *vp, uchar *s) 3677c478bd9Sstevel@tonic-gate { 368*1ee2e5faSnakanon int i; 369*1ee2e5faSnakanon 3707c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0) 3717c478bd9Sstevel@tonic-gate funnyvar(vp, "assign to"); 3727c478bd9Sstevel@tonic-gate if (vp->tval & FLD) { 3737c478bd9Sstevel@tonic-gate donerec = 0; /* mark $0 invalid */ 374*1ee2e5faSnakanon i = fldidx(vp); 375*1ee2e5faSnakanon if (i > *NF) 376*1ee2e5faSnakanon newfld(i); 377*1ee2e5faSnakanon dprintf(("setting field %d to %s\n", i, s)); 3787c478bd9Sstevel@tonic-gate } else if (vp->tval & REC) { 3797c478bd9Sstevel@tonic-gate donefld = 0; /* mark $1... invalid */ 3807c478bd9Sstevel@tonic-gate donerec = 1; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate vp->tval &= ~NUM; 3837c478bd9Sstevel@tonic-gate vp->tval |= STR; 3847c478bd9Sstevel@tonic-gate if (freeable(vp)) 3857c478bd9Sstevel@tonic-gate xfree(vp->sval); 3867c478bd9Sstevel@tonic-gate vp->tval &= ~DONTFREE; 387*1ee2e5faSnakanon dprintf(("setsval %p: %s = \"%s\", t=%p\n", 388*1ee2e5faSnakanon (void *)vp, 389*1ee2e5faSnakanon vp->nval ? (char *)vp->nval : "", 390*1ee2e5faSnakanon s, 391*1ee2e5faSnakanon (void *)(vp->tval ? (char *)vp->tval : ""))); 3927c478bd9Sstevel@tonic-gate return (vp->sval = tostring(s)); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 395*1ee2e5faSnakanon Awkfloat 396*1ee2e5faSnakanon r_getfval(Cell *vp) 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0) 3997c478bd9Sstevel@tonic-gate funnyvar(vp, "read value of"); 4007c478bd9Sstevel@tonic-gate if ((vp->tval & FLD) && donefld == 0) 4017c478bd9Sstevel@tonic-gate fldbld(); 4027c478bd9Sstevel@tonic-gate else if ((vp->tval & REC) && donerec == 0) 4037c478bd9Sstevel@tonic-gate recbld(); 4047c478bd9Sstevel@tonic-gate if (!isnum(vp)) { /* not a number */ 405*1ee2e5faSnakanon vp->fval = atof((const char *)vp->sval); /* best guess */ 406*1ee2e5faSnakanon if (is_number(vp->sval) && !(vp->tval&CON)) 4077c478bd9Sstevel@tonic-gate vp->tval |= NUM; /* make NUM only sparingly */ 4087c478bd9Sstevel@tonic-gate } 409*1ee2e5faSnakanon dprintf(("getfval %p: %s = %g, t=%p\n", 410*1ee2e5faSnakanon (void *)vp, vp->nval, vp->fval, (void *)vp->tval)); 4117c478bd9Sstevel@tonic-gate return (vp->fval); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate 414*1ee2e5faSnakanon uchar * 415*1ee2e5faSnakanon r_getsval(Cell *vp) 4167c478bd9Sstevel@tonic-gate { 417*1ee2e5faSnakanon uchar s[256]; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate if ((vp->tval & (NUM | STR)) == 0) 4207c478bd9Sstevel@tonic-gate funnyvar(vp, "read value of"); 4217c478bd9Sstevel@tonic-gate if ((vp->tval & FLD) && donefld == 0) 4227c478bd9Sstevel@tonic-gate fldbld(); 4237c478bd9Sstevel@tonic-gate else if ((vp->tval & REC) && donerec == 0) 4247c478bd9Sstevel@tonic-gate recbld(); 4257c478bd9Sstevel@tonic-gate if ((vp->tval & STR) == 0) { 4267c478bd9Sstevel@tonic-gate if (!(vp->tval&DONTFREE)) 4277c478bd9Sstevel@tonic-gate xfree(vp->sval); 428*1ee2e5faSnakanon if ((long long)vp->fval == vp->fval) { 429*1ee2e5faSnakanon (void) snprintf((char *)s, sizeof (s), 430*1ee2e5faSnakanon "%.20g", vp->fval); 431*1ee2e5faSnakanon } else { 432*1ee2e5faSnakanon /*LINTED*/ 433*1ee2e5faSnakanon (void) snprintf((char *)s, sizeof (s), 434*1ee2e5faSnakanon (char *)*OFMT, vp->fval); 435*1ee2e5faSnakanon } 4367c478bd9Sstevel@tonic-gate vp->sval = tostring(s); 4377c478bd9Sstevel@tonic-gate vp->tval &= ~DONTFREE; 4387c478bd9Sstevel@tonic-gate vp->tval |= STR; 4397c478bd9Sstevel@tonic-gate } 440*1ee2e5faSnakanon dprintf(("getsval %p: %s = \"%s\", t=%p\n", 441*1ee2e5faSnakanon (void *)vp, 442*1ee2e5faSnakanon vp->nval ? (char *)vp->nval : "", 443*1ee2e5faSnakanon vp->sval ? (char *)vp->sval : "", 444*1ee2e5faSnakanon (void *)vp->tval)); 4457c478bd9Sstevel@tonic-gate return (vp->sval); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 448*1ee2e5faSnakanon uchar * 449*1ee2e5faSnakanon tostring(uchar *s) 4507c478bd9Sstevel@tonic-gate { 4517c478bd9Sstevel@tonic-gate register uchar *p; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate p = (uchar *)malloc(strlen((char *)s)+1); 4547c478bd9Sstevel@tonic-gate if (p == NULL) 4557c478bd9Sstevel@tonic-gate ERROR "out of space in tostring on %s", s FATAL; 456*1ee2e5faSnakanon (void) strcpy((char *)p, (char *)s); 4577c478bd9Sstevel@tonic-gate return (p); 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate 460*1ee2e5faSnakanon uchar * 461*1ee2e5faSnakanon qstring(uchar *s, int delim) /* collect string up to delim */ 4627c478bd9Sstevel@tonic-gate { 463*1ee2e5faSnakanon uchar *cbuf, *ret; 4647c478bd9Sstevel@tonic-gate int c, n; 465*1ee2e5faSnakanon size_t cbufsz, cnt; 4667c478bd9Sstevel@tonic-gate 467*1ee2e5faSnakanon init_buf(&cbuf, &cbufsz, LINE_INCR); 468*1ee2e5faSnakanon 469*1ee2e5faSnakanon for (cnt = 0; (c = *s) != delim; s++) { 470*1ee2e5faSnakanon if (c == '\n') { 4717c478bd9Sstevel@tonic-gate ERROR "newline in string %.10s...", cbuf SYNTAX; 472*1ee2e5faSnakanon } else if (c != '\\') { 473*1ee2e5faSnakanon expand_buf(&cbuf, &cbufsz, cnt); 474*1ee2e5faSnakanon cbuf[cnt++] = c; 475*1ee2e5faSnakanon } else { /* \something */ 476*1ee2e5faSnakanon expand_buf(&cbuf, &cbufsz, cnt); 4777c478bd9Sstevel@tonic-gate switch (c = *++s) { 478*1ee2e5faSnakanon case '\\': cbuf[cnt++] = '\\'; break; 479*1ee2e5faSnakanon case 'n': cbuf[cnt++] = '\n'; break; 480*1ee2e5faSnakanon case 't': cbuf[cnt++] = '\t'; break; 481*1ee2e5faSnakanon case 'b': cbuf[cnt++] = '\b'; break; 482*1ee2e5faSnakanon case 'f': cbuf[cnt++] = '\f'; break; 483*1ee2e5faSnakanon case 'r': cbuf[cnt++] = '\r'; break; 4847c478bd9Sstevel@tonic-gate default: 4857c478bd9Sstevel@tonic-gate if (!isdigit(c)) { 486*1ee2e5faSnakanon cbuf[cnt++] = c; 4877c478bd9Sstevel@tonic-gate break; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate n = c - '0'; 4907c478bd9Sstevel@tonic-gate if (isdigit(s[1])) { 4917c478bd9Sstevel@tonic-gate n = 8 * n + *++s - '0'; 4927c478bd9Sstevel@tonic-gate if (isdigit(s[1])) 4937c478bd9Sstevel@tonic-gate n = 8 * n + *++s - '0'; 4947c478bd9Sstevel@tonic-gate } 495*1ee2e5faSnakanon cbuf[cnt++] = n; 4967c478bd9Sstevel@tonic-gate break; 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate } 499*1ee2e5faSnakanon } 500*1ee2e5faSnakanon cbuf[cnt] = '\0'; 501*1ee2e5faSnakanon ret = tostring(cbuf); 502*1ee2e5faSnakanon free(cbuf); 503*1ee2e5faSnakanon return (ret); 5047c478bd9Sstevel@tonic-gate } 505