14b588458SPeter Avalos /**************************************************************** 24b588458SPeter Avalos Copyright (C) Lucent Technologies 1997 34b588458SPeter Avalos All Rights Reserved 44b588458SPeter Avalos 54b588458SPeter Avalos Permission to use, copy, modify, and distribute this software and 64b588458SPeter Avalos its documentation for any purpose and without fee is hereby 74b588458SPeter Avalos granted, provided that the above copyright notice appear in all 84b588458SPeter Avalos copies and that both that the copyright notice and this 94b588458SPeter Avalos permission notice and warranty disclaimer appear in supporting 104b588458SPeter Avalos documentation, and that the name Lucent Technologies or any of 114b588458SPeter Avalos its entities not be used in advertising or publicity pertaining 124b588458SPeter Avalos to distribution of the software without specific, written prior 134b588458SPeter Avalos permission. 144b588458SPeter Avalos 154b588458SPeter Avalos LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 164b588458SPeter Avalos INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 174b588458SPeter Avalos IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 184b588458SPeter Avalos SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 194b588458SPeter Avalos WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 204b588458SPeter Avalos IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 214b588458SPeter Avalos ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 224b588458SPeter Avalos THIS SOFTWARE. 234b588458SPeter Avalos ****************************************************************/ 244b588458SPeter Avalos 254b588458SPeter Avalos #define DEBUG 264b588458SPeter Avalos #include <stdio.h> 274b588458SPeter Avalos #include <math.h> 284b588458SPeter Avalos #include <ctype.h> 294b588458SPeter Avalos #include <string.h> 304b588458SPeter Avalos #include <stdlib.h> 314b588458SPeter Avalos #include "awk.h" 324b588458SPeter Avalos #include "ytab.h" 334b588458SPeter Avalos 344b588458SPeter Avalos #define FULLTAB 2 /* rehash when table gets this x full */ 354b588458SPeter Avalos #define GROWTAB 4 /* grow table by this factor */ 364b588458SPeter Avalos 374b588458SPeter Avalos Array *symtab; /* main symbol table */ 384b588458SPeter Avalos 394b588458SPeter Avalos char **FS; /* initial field sep */ 404b588458SPeter Avalos char **RS; /* initial record sep */ 414b588458SPeter Avalos char **OFS; /* output field sep */ 424b588458SPeter Avalos char **ORS; /* output record sep */ 434b588458SPeter Avalos char **OFMT; /* output format for numbers */ 444b588458SPeter Avalos char **CONVFMT; /* format for conversions in getsval */ 454b588458SPeter Avalos Awkfloat *NF; /* number of fields in current record */ 464b588458SPeter Avalos Awkfloat *NR; /* number of current record */ 474b588458SPeter Avalos Awkfloat *FNR; /* number of current record in current file */ 484b588458SPeter Avalos char **FILENAME; /* current filename argument */ 494b588458SPeter Avalos Awkfloat *ARGC; /* number of arguments from command line */ 504b588458SPeter Avalos char **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */ 514b588458SPeter Avalos Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */ 524b588458SPeter Avalos Awkfloat *RLENGTH; /* length of same */ 534b588458SPeter Avalos 544b588458SPeter Avalos Cell *fsloc; /* FS */ 554b588458SPeter Avalos Cell *nrloc; /* NR */ 564b588458SPeter Avalos Cell *nfloc; /* NF */ 574b588458SPeter Avalos Cell *fnrloc; /* FNR */ 584b588458SPeter Avalos Array *ARGVtab; /* symbol table containing ARGV[...] */ 594b588458SPeter Avalos Array *ENVtab; /* symbol table containing ENVIRON[...] */ 604b588458SPeter Avalos Cell *rstartloc; /* RSTART */ 614b588458SPeter Avalos Cell *rlengthloc; /* RLENGTH */ 624b588458SPeter Avalos Cell *symtabloc; /* SYMTAB */ 634b588458SPeter Avalos 644b588458SPeter Avalos Cell *nullloc; /* a guaranteed empty cell */ 654b588458SPeter Avalos Node *nullnode; /* zero&null, converted into a node for comparisons */ 664b588458SPeter Avalos Cell *literal0; 674b588458SPeter Avalos 684b588458SPeter Avalos extern Cell **fldtab; 694b588458SPeter Avalos 704b588458SPeter Avalos void syminit(void) /* initialize symbol table with builtin vars */ 714b588458SPeter Avalos { 724b588458SPeter Avalos literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab); 734b588458SPeter Avalos /* this is used for if(x)... tests: */ 744b588458SPeter Avalos nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab); 754b588458SPeter Avalos nullnode = celltonode(nullloc, CCON); 764b588458SPeter Avalos 774b588458SPeter Avalos fsloc = setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab); 784b588458SPeter Avalos FS = &fsloc->sval; 794b588458SPeter Avalos RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval; 804b588458SPeter Avalos OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval; 814b588458SPeter Avalos ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval; 824b588458SPeter Avalos OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; 834b588458SPeter Avalos CONVFMT = &setsymtab("CONVFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval; 844b588458SPeter Avalos FILENAME = &setsymtab("FILENAME", "", 0.0, STR|DONTFREE, symtab)->sval; 854b588458SPeter Avalos nfloc = setsymtab("NF", "", 0.0, NUM, symtab); 864b588458SPeter Avalos NF = &nfloc->fval; 874b588458SPeter Avalos nrloc = setsymtab("NR", "", 0.0, NUM, symtab); 884b588458SPeter Avalos NR = &nrloc->fval; 894b588458SPeter Avalos fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab); 904b588458SPeter Avalos FNR = &fnrloc->fval; 914b588458SPeter Avalos SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval; 924b588458SPeter Avalos rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab); 934b588458SPeter Avalos RSTART = &rstartloc->fval; 944b588458SPeter Avalos rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab); 954b588458SPeter Avalos RLENGTH = &rlengthloc->fval; 964b588458SPeter Avalos symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab); 974b588458SPeter Avalos symtabloc->sval = (char *) symtab; 984b588458SPeter Avalos } 994b588458SPeter Avalos 1004b588458SPeter Avalos void arginit(int ac, char **av) /* set up ARGV and ARGC */ 1014b588458SPeter Avalos { 1024b588458SPeter Avalos Cell *cp; 1034b588458SPeter Avalos int i; 1044b588458SPeter Avalos char temp[50]; 1054b588458SPeter Avalos 1064b588458SPeter Avalos ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval; 1074b588458SPeter Avalos cp = setsymtab("ARGV", "", 0.0, ARR, symtab); 1084b588458SPeter Avalos ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */ 1094b588458SPeter Avalos cp->sval = (char *) ARGVtab; 1104b588458SPeter Avalos for (i = 0; i < ac; i++) { 1114b588458SPeter Avalos sprintf(temp, "%d", i); 1124b588458SPeter Avalos if (is_number(*av)) 1134b588458SPeter Avalos setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab); 1144b588458SPeter Avalos else 1154b588458SPeter Avalos setsymtab(temp, *av, 0.0, STR, ARGVtab); 1164b588458SPeter Avalos av++; 1174b588458SPeter Avalos } 1184b588458SPeter Avalos } 1194b588458SPeter Avalos 1204b588458SPeter Avalos void envinit(char **envp) /* set up ENVIRON variable */ 1214b588458SPeter Avalos { 1224b588458SPeter Avalos Cell *cp; 1234b588458SPeter Avalos char *p; 1244b588458SPeter Avalos 1254b588458SPeter Avalos cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab); 1264b588458SPeter Avalos ENVtab = makesymtab(NSYMTAB); 1274b588458SPeter Avalos cp->sval = (char *) ENVtab; 1284b588458SPeter Avalos for ( ; *envp; envp++) { 1294b588458SPeter Avalos if ((p = strchr(*envp, '=')) == NULL) 1304b588458SPeter Avalos continue; 1314b588458SPeter Avalos if( p == *envp ) /* no left hand side name in env string */ 1324b588458SPeter Avalos continue; 1334b588458SPeter Avalos *p++ = 0; /* split into two strings at = */ 1344b588458SPeter Avalos if (is_number(p)) 1354b588458SPeter Avalos setsymtab(*envp, p, atof(p), STR|NUM, ENVtab); 1364b588458SPeter Avalos else 1374b588458SPeter Avalos setsymtab(*envp, p, 0.0, STR, ENVtab); 1384b588458SPeter Avalos p[-1] = '='; /* restore in case env is passed down to a shell */ 1394b588458SPeter Avalos } 1404b588458SPeter Avalos } 1414b588458SPeter Avalos 1424b588458SPeter Avalos Array *makesymtab(int n) /* make a new symbol table */ 1434b588458SPeter Avalos { 1444b588458SPeter Avalos Array *ap; 1454b588458SPeter Avalos Cell **tp; 1464b588458SPeter Avalos 1474b588458SPeter Avalos ap = (Array *) malloc(sizeof(Array)); 1484b588458SPeter Avalos tp = (Cell **) calloc(n, sizeof(Cell *)); 1494b588458SPeter Avalos if (ap == NULL || tp == NULL) 1504b588458SPeter Avalos FATAL("out of space in makesymtab"); 1514b588458SPeter Avalos ap->nelem = 0; 1524b588458SPeter Avalos ap->size = n; 1534b588458SPeter Avalos ap->tab = tp; 1544b588458SPeter Avalos return(ap); 1554b588458SPeter Avalos } 1564b588458SPeter Avalos 1574b588458SPeter Avalos void freesymtab(Cell *ap) /* free a symbol table */ 1584b588458SPeter Avalos { 1594b588458SPeter Avalos Cell *cp, *temp; 1604b588458SPeter Avalos Array *tp; 1614b588458SPeter Avalos int i; 1624b588458SPeter Avalos 1634b588458SPeter Avalos if (!isarr(ap)) 1644b588458SPeter Avalos return; 1654b588458SPeter Avalos tp = (Array *) ap->sval; 1664b588458SPeter Avalos if (tp == NULL) 1674b588458SPeter Avalos return; 1684b588458SPeter Avalos for (i = 0; i < tp->size; i++) { 1694b588458SPeter Avalos for (cp = tp->tab[i]; cp != NULL; cp = temp) { 1704b588458SPeter Avalos xfree(cp->nval); 1714b588458SPeter Avalos if (freeable(cp)) 1724b588458SPeter Avalos xfree(cp->sval); 1734b588458SPeter Avalos temp = cp->cnext; /* avoids freeing then using */ 1744b588458SPeter Avalos free(cp); 1754b588458SPeter Avalos tp->nelem--; 1764b588458SPeter Avalos } 1774b588458SPeter Avalos tp->tab[i] = 0; 1784b588458SPeter Avalos } 1794b588458SPeter Avalos if (tp->nelem != 0) 1804b588458SPeter Avalos WARNING("can't happen: inconsistent element count freeing %s", ap->nval); 1814b588458SPeter Avalos free(tp->tab); 1824b588458SPeter Avalos free(tp); 1834b588458SPeter Avalos } 1844b588458SPeter Avalos 1854b588458SPeter Avalos void freeelem(Cell *ap, const char *s) /* free elem s from ap (i.e., ap["s"] */ 1864b588458SPeter Avalos { 1874b588458SPeter Avalos Array *tp; 1884b588458SPeter Avalos Cell *p, *prev = NULL; 1894b588458SPeter Avalos int h; 1904b588458SPeter Avalos 1914b588458SPeter Avalos tp = (Array *) ap->sval; 1924b588458SPeter Avalos h = hash(s, tp->size); 1934b588458SPeter Avalos for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext) 1944b588458SPeter Avalos if (strcmp(s, p->nval) == 0) { 1954b588458SPeter Avalos if (prev == NULL) /* 1st one */ 1964b588458SPeter Avalos tp->tab[h] = p->cnext; 1974b588458SPeter Avalos else /* middle somewhere */ 1984b588458SPeter Avalos prev->cnext = p->cnext; 1994b588458SPeter Avalos if (freeable(p)) 2004b588458SPeter Avalos xfree(p->sval); 2014b588458SPeter Avalos free(p->nval); 2024b588458SPeter Avalos free(p); 2034b588458SPeter Avalos tp->nelem--; 2044b588458SPeter Avalos return; 2054b588458SPeter Avalos } 2064b588458SPeter Avalos } 2074b588458SPeter Avalos 2084b588458SPeter Avalos Cell *setsymtab(const char *n, const char *s, Awkfloat f, unsigned t, Array *tp) 2094b588458SPeter Avalos { 2104b588458SPeter Avalos int h; 2114b588458SPeter Avalos Cell *p; 2124b588458SPeter Avalos 2134b588458SPeter Avalos if (n != NULL && (p = lookup(n, tp)) != NULL) { 2144b588458SPeter Avalos dprintf( ("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n", 215*b12bae18SSascha Wildner (void*)p, NN(p->nval), NN(p->sval), p->fval, p->tval) ); 2164b588458SPeter Avalos return(p); 2174b588458SPeter Avalos } 2184b588458SPeter Avalos p = (Cell *) malloc(sizeof(Cell)); 2194b588458SPeter Avalos if (p == NULL) 2204b588458SPeter Avalos FATAL("out of space for symbol table at %s", n); 2214b588458SPeter Avalos p->nval = tostring(n); 2224b588458SPeter Avalos p->sval = s ? tostring(s) : tostring(""); 2234b588458SPeter Avalos p->fval = f; 2244b588458SPeter Avalos p->tval = t; 2254b588458SPeter Avalos p->csub = CUNK; 2264b588458SPeter Avalos p->ctype = OCELL; 2274b588458SPeter Avalos tp->nelem++; 2284b588458SPeter Avalos if (tp->nelem > FULLTAB * tp->size) 2294b588458SPeter Avalos rehash(tp); 2304b588458SPeter Avalos h = hash(n, tp->size); 2314b588458SPeter Avalos p->cnext = tp->tab[h]; 2324b588458SPeter Avalos tp->tab[h] = p; 2334b588458SPeter Avalos dprintf( ("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n", 234*b12bae18SSascha Wildner (void*)p, p->nval, p->sval, p->fval, p->tval) ); 2354b588458SPeter Avalos return(p); 2364b588458SPeter Avalos } 2374b588458SPeter Avalos 2384b588458SPeter Avalos int hash(const char *s, int n) /* form hash value for string s */ 2394b588458SPeter Avalos { 2404b588458SPeter Avalos unsigned hashval; 2414b588458SPeter Avalos 2424b588458SPeter Avalos for (hashval = 0; *s != '\0'; s++) 2434b588458SPeter Avalos hashval = (*s + 31 * hashval); 2444b588458SPeter Avalos return hashval % n; 2454b588458SPeter Avalos } 2464b588458SPeter Avalos 2474b588458SPeter Avalos void rehash(Array *tp) /* rehash items in small table into big one */ 2484b588458SPeter Avalos { 2494b588458SPeter Avalos int i, nh, nsz; 2504b588458SPeter Avalos Cell *cp, *op, **np; 2514b588458SPeter Avalos 2524b588458SPeter Avalos nsz = GROWTAB * tp->size; 2534b588458SPeter Avalos np = (Cell **) calloc(nsz, sizeof(Cell *)); 2544b588458SPeter Avalos if (np == NULL) /* can't do it, but can keep running. */ 2554b588458SPeter Avalos return; /* someone else will run out later. */ 2564b588458SPeter Avalos for (i = 0; i < tp->size; i++) { 2574b588458SPeter Avalos for (cp = tp->tab[i]; cp; cp = op) { 2584b588458SPeter Avalos op = cp->cnext; 2594b588458SPeter Avalos nh = hash(cp->nval, nsz); 2604b588458SPeter Avalos cp->cnext = np[nh]; 2614b588458SPeter Avalos np[nh] = cp; 2624b588458SPeter Avalos } 2634b588458SPeter Avalos } 2644b588458SPeter Avalos free(tp->tab); 2654b588458SPeter Avalos tp->tab = np; 2664b588458SPeter Avalos tp->size = nsz; 2674b588458SPeter Avalos } 2684b588458SPeter Avalos 2694b588458SPeter Avalos Cell *lookup(const char *s, Array *tp) /* look for s in tp */ 2704b588458SPeter Avalos { 2714b588458SPeter Avalos Cell *p; 2724b588458SPeter Avalos int h; 2734b588458SPeter Avalos 2744b588458SPeter Avalos h = hash(s, tp->size); 2754b588458SPeter Avalos for (p = tp->tab[h]; p != NULL; p = p->cnext) 2764b588458SPeter Avalos if (strcmp(s, p->nval) == 0) 2774b588458SPeter Avalos return(p); /* found it */ 2784b588458SPeter Avalos return(NULL); /* not found */ 2794b588458SPeter Avalos } 2804b588458SPeter Avalos 2814b588458SPeter Avalos Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */ 2824b588458SPeter Avalos { 2834b588458SPeter Avalos int fldno; 2844b588458SPeter Avalos 2854b588458SPeter Avalos if ((vp->tval & (NUM | STR)) == 0) 2864b588458SPeter Avalos funnyvar(vp, "assign to"); 2874b588458SPeter Avalos if (isfld(vp)) { 2884b588458SPeter Avalos donerec = 0; /* mark $0 invalid */ 2894b588458SPeter Avalos fldno = atoi(vp->nval); 2904b588458SPeter Avalos if (fldno > *NF) 2914b588458SPeter Avalos newfld(fldno); 2924b588458SPeter Avalos dprintf( ("setting field %d to %g\n", fldno, f) ); 2934b588458SPeter Avalos } else if (isrec(vp)) { 2944b588458SPeter Avalos donefld = 0; /* mark $1... invalid */ 2954b588458SPeter Avalos donerec = 1; 2964b588458SPeter Avalos } 2974b588458SPeter Avalos if (freeable(vp)) 2984b588458SPeter Avalos xfree(vp->sval); /* free any previous string */ 2994b588458SPeter Avalos vp->tval &= ~STR; /* mark string invalid */ 3004b588458SPeter Avalos vp->tval |= NUM; /* mark number ok */ 301*b12bae18SSascha Wildner dprintf( ("setfval %p: %s = %g, t=%o\n", (void*)vp, NN(vp->nval), f, vp->tval) ); 3024b588458SPeter Avalos return vp->fval = f; 3034b588458SPeter Avalos } 3044b588458SPeter Avalos 3054b588458SPeter Avalos void funnyvar(Cell *vp, const char *rw) 3064b588458SPeter Avalos { 3074b588458SPeter Avalos if (isarr(vp)) 3084b588458SPeter Avalos FATAL("can't %s %s; it's an array name.", rw, vp->nval); 3094b588458SPeter Avalos if (vp->tval & FCN) 3104b588458SPeter Avalos FATAL("can't %s %s; it's a function.", rw, vp->nval); 3114b588458SPeter Avalos WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o", 3124b588458SPeter Avalos vp, vp->nval, vp->sval, vp->fval, vp->tval); 3134b588458SPeter Avalos } 3144b588458SPeter Avalos 3154b588458SPeter Avalos char *setsval(Cell *vp, const char *s) /* set string val of a Cell */ 3164b588458SPeter Avalos { 3174b588458SPeter Avalos char *t; 3184b588458SPeter Avalos int fldno; 3194b588458SPeter Avalos 3204b588458SPeter Avalos dprintf( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n", 321*b12bae18SSascha Wildner (void*)vp, NN(vp->nval), s, vp->tval, donerec, donefld) ); 3224b588458SPeter Avalos if ((vp->tval & (NUM | STR)) == 0) 3234b588458SPeter Avalos funnyvar(vp, "assign to"); 3244b588458SPeter Avalos if (isfld(vp)) { 3254b588458SPeter Avalos donerec = 0; /* mark $0 invalid */ 3264b588458SPeter Avalos fldno = atoi(vp->nval); 3274b588458SPeter Avalos if (fldno > *NF) 3284b588458SPeter Avalos newfld(fldno); 3294b588458SPeter Avalos dprintf( ("setting field %d to %s (%p)\n", fldno, s, s) ); 3304b588458SPeter Avalos } else if (isrec(vp)) { 3314b588458SPeter Avalos donefld = 0; /* mark $1... invalid */ 3324b588458SPeter Avalos donerec = 1; 3334b588458SPeter Avalos } 3344b588458SPeter Avalos t = tostring(s); /* in case it's self-assign */ 3354b588458SPeter Avalos if (freeable(vp)) 3364b588458SPeter Avalos xfree(vp->sval); 3374b588458SPeter Avalos vp->tval &= ~NUM; 3384b588458SPeter Avalos vp->tval |= STR; 3394b588458SPeter Avalos vp->tval &= ~DONTFREE; 3404b588458SPeter Avalos dprintf( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n", 341*b12bae18SSascha Wildner (void*)vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) ); 3424b588458SPeter Avalos return(vp->sval = t); 3434b588458SPeter Avalos } 3444b588458SPeter Avalos 3454b588458SPeter Avalos Awkfloat getfval(Cell *vp) /* get float val of a Cell */ 3464b588458SPeter Avalos { 3474b588458SPeter Avalos if ((vp->tval & (NUM | STR)) == 0) 3484b588458SPeter Avalos funnyvar(vp, "read value of"); 3494b588458SPeter Avalos if (isfld(vp) && donefld == 0) 3504b588458SPeter Avalos fldbld(); 3514b588458SPeter Avalos else if (isrec(vp) && donerec == 0) 3524b588458SPeter Avalos recbld(); 3534b588458SPeter Avalos if (!isnum(vp)) { /* not a number */ 3544b588458SPeter Avalos vp->fval = atof(vp->sval); /* best guess */ 3554b588458SPeter Avalos if (is_number(vp->sval) && !(vp->tval&CON)) 3564b588458SPeter Avalos vp->tval |= NUM; /* make NUM only sparingly */ 3574b588458SPeter Avalos } 358*b12bae18SSascha Wildner dprintf( ("getfval %p: %s = %g, t=%o\n", 359*b12bae18SSascha Wildner (void*)vp, NN(vp->nval), vp->fval, vp->tval) ); 3604b588458SPeter Avalos return(vp->fval); 3614b588458SPeter Avalos } 3624b588458SPeter Avalos 3634b588458SPeter Avalos static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */ 3644b588458SPeter Avalos { 3654b588458SPeter Avalos char s[100]; /* BUG: unchecked */ 3664b588458SPeter Avalos double dtemp; 3674b588458SPeter Avalos 3684b588458SPeter Avalos if ((vp->tval & (NUM | STR)) == 0) 3694b588458SPeter Avalos funnyvar(vp, "read value of"); 3704b588458SPeter Avalos if (isfld(vp) && donefld == 0) 3714b588458SPeter Avalos fldbld(); 3724b588458SPeter Avalos else if (isrec(vp) && donerec == 0) 3734b588458SPeter Avalos recbld(); 3744b588458SPeter Avalos if (isstr(vp) == 0) { 3754b588458SPeter Avalos if (freeable(vp)) 3764b588458SPeter Avalos xfree(vp->sval); 3774b588458SPeter Avalos if (modf(vp->fval, &dtemp) == 0) /* it's integral */ 3784b588458SPeter Avalos sprintf(s, "%.30g", vp->fval); 3794b588458SPeter Avalos else 3804b588458SPeter Avalos sprintf(s, *fmt, vp->fval); 3814b588458SPeter Avalos vp->sval = tostring(s); 3824b588458SPeter Avalos vp->tval &= ~DONTFREE; 3834b588458SPeter Avalos vp->tval |= STR; 3844b588458SPeter Avalos } 385*b12bae18SSascha Wildner dprintf( ("getsval %p: %s = \"%s (%p)\", t=%o\n", 386*b12bae18SSascha Wildner (void*)vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) ); 3874b588458SPeter Avalos return(vp->sval); 3884b588458SPeter Avalos } 3894b588458SPeter Avalos 3904b588458SPeter Avalos char *getsval(Cell *vp) /* get string val of a Cell */ 3914b588458SPeter Avalos { 3924b588458SPeter Avalos return get_str_val(vp, CONVFMT); 3934b588458SPeter Avalos } 3944b588458SPeter Avalos 3954b588458SPeter Avalos char *getpssval(Cell *vp) /* get string val of a Cell for print */ 3964b588458SPeter Avalos { 3974b588458SPeter Avalos return get_str_val(vp, OFMT); 3984b588458SPeter Avalos } 3994b588458SPeter Avalos 4004b588458SPeter Avalos 4014b588458SPeter Avalos char *tostring(const char *s) /* make a copy of string s */ 4024b588458SPeter Avalos { 4034b588458SPeter Avalos char *p; 4044b588458SPeter Avalos 4054b588458SPeter Avalos p = (char *) malloc(strlen(s)+1); 4064b588458SPeter Avalos if (p == NULL) 4074b588458SPeter Avalos FATAL("out of space in tostring on %s", s); 4084b588458SPeter Avalos strcpy(p, s); 4094b588458SPeter Avalos return(p); 4104b588458SPeter Avalos } 4114b588458SPeter Avalos 4124b588458SPeter Avalos char *qstring(const char *is, int delim) /* collect string up to next delim */ 4134b588458SPeter Avalos { 4144b588458SPeter Avalos const char *os = is; 4154b588458SPeter Avalos int c, n; 4164b588458SPeter Avalos uschar *s = (uschar *) is; 4174b588458SPeter Avalos uschar *buf, *bp; 4184b588458SPeter Avalos 4194b588458SPeter Avalos if ((buf = (uschar *) malloc(strlen(is)+3)) == NULL) 4204b588458SPeter Avalos FATAL( "out of space in qstring(%s)", s); 4214b588458SPeter Avalos for (bp = buf; (c = *s) != delim; s++) { 4224b588458SPeter Avalos if (c == '\n') 4234b588458SPeter Avalos SYNTAX( "newline in string %.20s...", os ); 4244b588458SPeter Avalos else if (c != '\\') 4254b588458SPeter Avalos *bp++ = c; 4264b588458SPeter Avalos else { /* \something */ 4274b588458SPeter Avalos c = *++s; 4284b588458SPeter Avalos if (c == 0) { /* \ at end */ 4294b588458SPeter Avalos *bp++ = '\\'; 4304b588458SPeter Avalos break; /* for loop */ 4314b588458SPeter Avalos } 4324b588458SPeter Avalos switch (c) { 4334b588458SPeter Avalos case '\\': *bp++ = '\\'; break; 4344b588458SPeter Avalos case 'n': *bp++ = '\n'; break; 4354b588458SPeter Avalos case 't': *bp++ = '\t'; break; 4364b588458SPeter Avalos case 'b': *bp++ = '\b'; break; 4374b588458SPeter Avalos case 'f': *bp++ = '\f'; break; 4384b588458SPeter Avalos case 'r': *bp++ = '\r'; break; 4394b588458SPeter Avalos default: 4404b588458SPeter Avalos if (!isdigit(c)) { 4414b588458SPeter Avalos *bp++ = c; 4424b588458SPeter Avalos break; 4434b588458SPeter Avalos } 4444b588458SPeter Avalos n = c - '0'; 4454b588458SPeter Avalos if (isdigit(s[1])) { 4464b588458SPeter Avalos n = 8 * n + *++s - '0'; 4474b588458SPeter Avalos if (isdigit(s[1])) 4484b588458SPeter Avalos n = 8 * n + *++s - '0'; 4494b588458SPeter Avalos } 4504b588458SPeter Avalos *bp++ = n; 4514b588458SPeter Avalos break; 4524b588458SPeter Avalos } 4534b588458SPeter Avalos } 4544b588458SPeter Avalos } 4554b588458SPeter Avalos *bp++ = 0; 4564b588458SPeter Avalos return (char *) buf; 4574b588458SPeter Avalos } 458