Print this page
3731 Update nawk to version 20121220

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/awk/tran.c
          +++ new/usr/src/cmd/awk/tran.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27      -/*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  28      -/*        All Rights Reserved   */
  29      -
  30      -#pragma ident   "%Z%%M% %I%     %E% SMI"
       27 +/*
       28 + * Copyright (C) Lucent Technologies 1997
       29 + * All Rights Reserved
       30 + *
       31 + * Permission to use, copy, modify, and distribute this software and
       32 + * its documentation for any purpose and without fee is hereby
       33 + * granted, provided that the above copyright notice appear in all
       34 + * copies and that both that the copyright notice and this
       35 + * permission notice and warranty disclaimer appear in supporting
       36 + * documentation, and that the name Lucent Technologies or any of
       37 + * its entities not be used in advertising or publicity pertaining
       38 + * to distribution of the software without specific, written prior
       39 + * permission.
       40 + *
       41 + * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
       42 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
       43 + * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
       44 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
       45 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
       46 + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
       47 + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
       48 + * THIS SOFTWARE.
       49 + */
  31   50  
  32   51  #define DEBUG
  33      -#include <stdio.h>
  34      -#include <stdlib.h>
  35      -#include <ctype.h>
  36      -#include <string.h>
       52 +#include <math.h>
  37   53  #include "awk.h"
  38   54  #include "y.tab.h"
  39   55  
  40   56  #define FULLTAB 2       /* rehash when table gets this x full */
  41   57  #define GROWTAB 4       /* grow table by this factor */
  42   58  
  43   59  Array   *symtab;        /* main symbol table */
  44   60  
  45   61  uchar   **FS;           /* initial field sep */
  46   62  uchar   **RS;           /* initial record sep */
  47   63  uchar   **OFS;          /* output field sep */
  48   64  uchar   **ORS;          /* output record sep */
  49   65  uchar   **OFMT;         /* output format for numbers */
       66 +uchar   **CONVFMT;      /* format for conversions in getsval */
  50   67  Awkfloat *NF;           /* number of fields in current record */
  51   68  Awkfloat *NR;           /* number of current record */
  52   69  Awkfloat *FNR;          /* number of current record in current file */
  53   70  uchar   **FILENAME;     /* current filename argument */
  54   71  Awkfloat *ARGC;         /* number of arguments from command line */
  55   72  uchar   **SUBSEP;       /* subscript separator for a[i,j,k]; default \034 */
  56   73  Awkfloat *RSTART;       /* start of re matched with ~; origin 1 (!) */
  57   74  Awkfloat *RLENGTH;      /* length of same */
  58   75  
  59      -Cell    *recloc;        /* location of record */
       76 +Cell    *fsloc;         /* FS */
  60   77  Cell    *nrloc;         /* NR */
  61   78  Cell    *nfloc;         /* NF */
  62   79  Cell    *fnrloc;        /* FNR */
  63   80  Array   *ARGVtab;       /* symbol table containing ARGV[...] */
  64   81  Array   *ENVtab;        /* symbol table containing ENVIRON[...] */
  65   82  Cell    *rstartloc;     /* RSTART */
  66   83  Cell    *rlengthloc;    /* RLENGTH */
  67   84  Cell    *symtabloc;     /* SYMTAB */
  68   85  
  69      -Cell    *nullloc;
       86 +Cell    *nullloc;       /* a guaranteed empty cell */
  70   87  Node    *nullnode;      /* zero&null, converted into a node for comparisons */
       88 +Cell    *literal0;
  71   89  
  72   90  static  void    rehash(Array *);
  73   91  
  74   92  void
  75      -syminit(void)
       93 +syminit(void)           /* initialize symbol table with builtin vars */
  76   94  {
  77      -        init_buf(&record, &record_size, LINE_INCR);
  78      -
  79      -        /* initialize $0 */
  80      -        recloc = getfld(0);
  81      -        recloc->nval = (uchar *)"$0";
  82      -        recloc->sval = record;
  83      -        recloc->tval = REC|STR|DONTFREE;
  84      -
  85      -        symtab = makesymtab(NSYMTAB);
  86      -        (void) setsymtab((uchar *)"0", (uchar *)"0", 0.0,
       95 +        literal0 = setsymtab((uchar *)"0", (uchar *)"0", 0.0,
  87   96              NUM|STR|CON|DONTFREE, symtab);
  88   97          /* this is used for if(x)... tests: */
  89   98          nullloc = setsymtab((uchar *)"$zero&null", (uchar *)"", 0.0,
  90   99              NUM|STR|CON|DONTFREE, symtab);
  91      -        nullnode = valtonode(nullloc, CCON);
  92      -        FS = &setsymtab((uchar *)"FS", (uchar *)" ", 0.0,
  93      -            STR|DONTFREE, symtab)->sval;
      100 +        nullnode = celltonode(nullloc, CCON);
      101 +
      102 +        fsloc = setsymtab((uchar *)"FS", (uchar *)" ", 0.0,
      103 +            STR|DONTFREE, symtab);
      104 +        FS = &fsloc->sval;
  94  105          RS = &setsymtab((uchar *)"RS", (uchar *)"\n", 0.0,
  95  106              STR|DONTFREE, symtab)->sval;
  96  107          OFS = &setsymtab((uchar *)"OFS", (uchar *)" ", 0.0,
  97  108              STR|DONTFREE, symtab)->sval;
  98  109          ORS = &setsymtab((uchar *)"ORS", (uchar *)"\n", 0.0,
  99  110              STR|DONTFREE, symtab)->sval;
 100  111          OFMT = &setsymtab((uchar *)"OFMT", (uchar *)"%.6g", 0.0,
 101  112              STR|DONTFREE, symtab)->sval;
      113 +        CONVFMT = &setsymtab((uchar *)"CONVFMT", (uchar *)"%.6g", 0.0,
      114 +            STR|DONTFREE, symtab)->sval;
 102  115          FILENAME = &setsymtab((uchar *)"FILENAME", (uchar *)"-", 0.0,
 103  116              STR|DONTFREE, symtab)->sval;
 104  117          nfloc = setsymtab((uchar *)"NF", (uchar *)"", 0.0, NUM, symtab);
 105  118          NF = &nfloc->fval;
 106  119          nrloc = setsymtab((uchar *)"NR", (uchar *)"", 0.0, NUM, symtab);
 107  120          NR = &nrloc->fval;
 108  121          fnrloc = setsymtab((uchar *)"FNR", (uchar *)"", 0.0, NUM, symtab);
 109  122          FNR = &fnrloc->fval;
 110  123          SUBSEP = &setsymtab((uchar *)"SUBSEP", (uchar *)"\034", 0.0,
 111  124              STR|DONTFREE, symtab)->sval;
↓ open down ↓ 1 lines elided ↑ open up ↑
 113  126              NUM, symtab);
 114  127          RSTART = &rstartloc->fval;
 115  128          rlengthloc = setsymtab((uchar *)"RLENGTH", (uchar *)"", 0.0,
 116  129              NUM, symtab);
 117  130          RLENGTH = &rlengthloc->fval;
 118  131          symtabloc = setsymtab((uchar *)"SYMTAB", (uchar *)"", 0.0, ARR, symtab);
 119  132          symtabloc->sval = (uchar *)symtab;
 120  133  }
 121  134  
 122  135  void
 123      -arginit(int ac, uchar *av[])
      136 +arginit(int ac, uchar *av[]) /* set up ARGV and ARGC */
 124  137  {
 125  138          Cell *cp;
 126  139          int i;
 127      -        uchar temp[11];
      140 +        uchar temp[50];
 128  141  
 129      -        /* first make FILENAME first real argument */
 130      -        for (i = 1; i < ac; i++) {
 131      -                if (!isclvar(av[i])) {
 132      -                        (void) setsval(lookup((uchar *)"FILENAME", symtab),
 133      -                            av[i]);
 134      -                        break;
 135      -                }
 136      -        }
 137  142          ARGC = &setsymtab((uchar *)"ARGC", (uchar *)"", (Awkfloat)ac,
 138  143              NUM, symtab)->fval;
 139  144          cp = setsymtab((uchar *)"ARGV", (uchar *)"", 0.0, ARR, symtab);
 140  145          ARGVtab = makesymtab(NSYMTAB);  /* could be (int) ARGC as well */
 141      -        cp->sval = (uchar *) ARGVtab;
      146 +        cp->sval = (uchar *)ARGVtab;
 142  147          for (i = 0; i < ac; i++) {
 143  148                  (void) sprintf((char *)temp, "%d", i);
 144  149                  if (is_number(*av)) {
 145  150                          (void) setsymtab(temp, *av, atof((const char *)*av),
 146  151                              STR|NUM, ARGVtab);
 147  152                  } else {
 148  153                          (void) setsymtab(temp, *av, 0.0, STR, ARGVtab);
 149  154                  }
 150  155                  av++;
 151  156          }
 152  157  }
 153  158  
 154  159  void
 155      -envinit(uchar *envp[])
      160 +envinit(uchar **envp)           /* set up ENVIRON variable */
 156  161  {
 157  162          Cell *cp;
 158  163          uchar *p;
 159  164  
 160  165          cp = setsymtab((uchar *)"ENVIRON", (uchar *)"", 0.0, ARR, symtab);
 161  166          ENVtab = makesymtab(NSYMTAB);
 162      -        cp->sval = (uchar *) ENVtab;
      167 +        cp->sval = (uchar *)ENVtab;
 163  168          for (; *envp; envp++) {
 164  169                  if ((p = (uchar *)strchr((char *)*envp, '=')) == NULL)
 165  170                          continue;
      171 +                if (p == *envp) /* no left hand side name in env string */
      172 +                        continue;
 166  173                  *p++ = 0;       /* split into two strings at = */
 167  174                  if (is_number(p)) {
 168  175                          (void) setsymtab(*envp, p, atof((const char *)p),
 169  176                              STR|NUM, ENVtab);
 170  177                  } else {
 171  178                          (void) setsymtab(*envp, p, 0.0, STR, ENVtab);
 172  179                  }
 173  180                  /* restore in case env is passed down to a shell */
 174  181                  p[-1] = '=';
 175  182          }
 176  183  }
 177  184  
 178  185  Array *
 179      -makesymtab(int n)
      186 +makesymtab(int n)       /* make a new symbol table */
 180  187  {
 181  188          Array *ap;
 182  189          Cell **tp;
 183  190  
 184  191          ap = (Array *)malloc(sizeof (Array));
 185  192          tp = (Cell **)calloc(n, sizeof (Cell *));
 186  193          if (ap == NULL || tp == NULL)
 187      -                ERROR "out of space in makesymtab" FATAL;
      194 +                FATAL("out of space in makesymtab");
 188  195          ap->nelem = 0;
 189  196          ap->size = n;
 190  197          ap->tab = tp;
 191  198          return (ap);
 192  199  }
 193  200  
 194  201  void
 195  202  freesymtab(Cell *ap)    /* free symbol table */
 196  203  {
 197      -        Cell *cp, *next;
      204 +        Cell *cp, *temp;
 198  205          Array *tp;
 199  206          int i;
 200  207  
 201  208          if (!isarr(ap))
 202  209                  return;
 203  210          /*LINTED align*/
 204  211          tp = (Array *)ap->sval;
 205  212          if (tp == NULL)
 206  213                  return;
 207  214          for (i = 0; i < tp->size; i++) {
 208      -                for (cp = tp->tab[i]; cp != NULL; cp = next) {
 209      -                        next = cp->cnext;
      215 +                for (cp = tp->tab[i]; cp != NULL; cp = temp) {
 210  216                          xfree(cp->nval);
 211  217                          if (freeable(cp))
 212  218                                  xfree(cp->sval);
      219 +                        /* avoids freeing then using */
      220 +                        temp = cp->cnext;
 213  221                          free(cp);
      222 +                        tp->nelem--;
 214  223                  }
      224 +                tp->tab[i] = 0;
 215  225          }
      226 +        if (tp->nelem != 0)
      227 +                WARNING("can't happen: inconsistent element count freeing %s",
      228 +                    ap->nval);
 216  229          free(tp->tab);
 217  230          free(tp);
 218  231  }
 219  232  
 220  233  void
 221      -freeelem(Cell *ap, uchar *s)            /* free elem s from ap (i.e., ap["s"] */
      234 +freeelem(Cell *ap, const uchar *s) /* free elem s from ap (i.e., ap["s"] */
 222  235  {
 223  236          Array *tp;
 224  237          Cell *p, *prev = NULL;
 225  238          int h;
 226  239  
 227  240          /*LINTED align*/
 228  241          tp = (Array *)ap->sval;
 229  242          h = hash(s, tp->size);
 230  243          for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
 231  244                  if (strcmp((char *)s, (char *)p->nval) == 0) {
↓ open down ↓ 4 lines elided ↑ open up ↑
 236  249                          if (freeable(p))
 237  250                                  xfree(p->sval);
 238  251                          free(p->nval);
 239  252                          free(p);
 240  253                          tp->nelem--;
 241  254                          return;
 242  255                  }
 243  256  }
 244  257  
 245  258  Cell *
 246      -setsymtab(uchar *n, uchar *s, Awkfloat f, unsigned int t, Array *tp)
      259 +setsymtab(const uchar *n, const uchar *s, Awkfloat f, unsigned int t,
      260 +    Array *tp)
 247  261  {
 248      -        register int h;
 249      -        register Cell *p;
      262 +        int h;
      263 +        Cell *p;
 250  264  
 251  265          if (n != NULL && (p = lookup(n, tp)) != NULL) {
 252      -                dprintf(("setsymtab found %p: n=%s", (void *)p, p->nval));
 253      -                dprintf((" s=\"%s\" f=%g t=%p\n",
 254      -                    p->sval, p->fval, (void *)p->tval));
      266 +                dprintf(("setsymtab found %p: n=%s s=\"%s\" f=%g t=%o\n",
      267 +                    (void *)p, p->nval, p->sval, p->fval, p->tval));
 255  268                  return (p);
 256  269          }
 257  270          p = (Cell *)malloc(sizeof (Cell));
 258  271          if (p == NULL)
 259      -                ERROR "symbol table overflow at %s", n FATAL;
      272 +                FATAL("out of space for symbol table at %s", n);
 260  273          p->nval = tostring(n);
 261  274          p->sval = s ? tostring(s) : tostring((uchar *)"");
 262  275          p->fval = f;
 263  276          p->tval = t;
 264      -        p->csub = 0;
 265      -
      277 +        p->csub = CUNK;
      278 +        p->ctype = OCELL;
 266  279          tp->nelem++;
 267  280          if (tp->nelem > FULLTAB * tp->size)
 268  281                  rehash(tp);
 269  282          h = hash(n, tp->size);
 270  283          p->cnext = tp->tab[h];
 271  284          tp->tab[h] = p;
 272      -        dprintf(("setsymtab set %p: n=%s", (void *)p, p->nval));
 273      -        dprintf((" s=\"%s\" f=%g t=%p\n", p->sval, p->fval, (void *)p->tval));
      285 +        dprintf(("setsymtab set %p: n=%s s=\"%s\" f=%g t=%o\n",
      286 +            (void *)p, p->nval, p->sval, p->fval, p->tval));
 274  287          return (p);
 275  288  }
 276  289  
 277  290  int
 278      -hash(uchar *s, int n)   /* form hash value for string s */
      291 +hash(const uchar *s, int n)     /* form hash value for string s */
 279  292  {
 280      -        register unsigned hashval;
      293 +        unsigned hashval;
 281  294  
 282  295          for (hashval = 0; *s != '\0'; s++)
 283  296                  hashval = (*s + 31 * hashval);
 284  297          return (hashval % n);
 285  298  }
 286  299  
 287  300  static void
 288  301  rehash(Array *tp)       /* rehash items in small table into big one */
 289  302  {
 290  303          int i, nh, nsz;
 291  304          Cell *cp, *op, **np;
 292  305  
 293  306          nsz = GROWTAB * tp->size;
 294  307          np = (Cell **)calloc(nsz, sizeof (Cell *));
 295      -        if (np == NULL)
 296      -                ERROR "out of space in rehash" FATAL;
      308 +        if (np == NULL)         /* can't do it, but can keep running. */
      309 +                return;         /* someone else will run out later. */
 297  310          for (i = 0; i < tp->size; i++) {
 298  311                  for (cp = tp->tab[i]; cp; cp = op) {
 299  312                          op = cp->cnext;
 300  313                          nh = hash(cp->nval, nsz);
 301  314                          cp->cnext = np[nh];
 302  315                          np[nh] = cp;
 303  316                  }
 304  317          }
 305  318          free(tp->tab);
 306  319          tp->tab = np;
 307  320          tp->size = nsz;
 308  321  }
 309  322  
 310  323  Cell *
 311      -lookup(uchar *s, Array *tp)     /* look for s in tp */
      324 +lookup(const uchar *s, Array *tp)       /* look for s in tp */
 312  325  {
 313      -        register Cell *p;
      326 +        Cell *p;
 314  327          int h;
 315  328  
 316  329          h = hash(s, tp->size);
 317  330          for (p = tp->tab[h]; p != NULL; p = p->cnext) {
 318  331                  if (strcmp((char *)s, (char *)p->nval) == 0)
 319  332                          return (p);     /* found it */
 320  333          }
 321  334          return (NULL);                  /* not found */
 322  335  }
 323  336  
 324  337  Awkfloat
 325      -setfval(Cell *vp, Awkfloat f)
      338 +setfval(Cell *vp, Awkfloat f)   /* set float val of a Cell */
 326  339  {
 327      -        int     i;
      340 +        int fldno;
 328  341  
 329  342          if ((vp->tval & (NUM | STR)) == 0)
 330  343                  funnyvar(vp, "assign to");
 331      -        if (vp->tval & FLD) {
      344 +        if (isfld(vp)) {
 332  345                  donerec = 0;    /* mark $0 invalid */
 333      -                i = fldidx(vp);
 334      -                if (i > *NF)
 335      -                        newfld(i);
 336      -                dprintf(("setting field %d to %g\n", i, f));
 337      -        } else if (vp->tval & REC) {
      346 +                fldno = atoi((char *)vp->nval);
      347 +                if (fldno > *NF)
      348 +                        newfld(fldno);
      349 +                dprintf(("setting field %d to %g\n", fldno, f));
      350 +        } else if (isrec(vp)) {
 338  351                  donefld = 0;    /* mark $1... invalid */
 339  352                  donerec = 1;
 340  353          }
      354 +        if (freeable(vp))
      355 +                xfree(vp->sval); /* free any previous string */
 341  356          vp->tval &= ~STR;       /* mark string invalid */
 342  357          vp->tval |= NUM;        /* mark number ok */
 343      -        dprintf(("setfval %p: %s = %g, t=%p\n", (void *)vp,
 344      -            vp->nval ? vp->nval : (unsigned char *)"NULL",
 345      -            f, (void *)vp->tval));
      358 +        if (f == -0)  /* who would have thought this possible? */
      359 +                f = 0;
      360 +        dprintf(("setfval %p: %s = %g, t=%o\n", (void *)vp,
      361 +            vp->nval, f, vp->tval));
 346  362          return (vp->fval = f);
 347  363  }
 348  364  
 349  365  void
 350  366  funnyvar(Cell *vp, char *rw)
 351  367  {
 352      -        if (vp->tval & ARR)
 353      -                ERROR "can't %s %s; it's an array name.", rw, vp->nval FATAL;
      368 +        if (isarr(vp))
      369 +                FATAL("can't %s %s; it's an array name.", rw, vp->nval);
 354  370          if (vp->tval & FCN)
 355      -                ERROR "can't %s %s; it's a function.", rw, vp->nval FATAL;
 356      -        ERROR "funny variable %o: n=%s s=\"%s\" f=%g t=%o",
 357      -            vp, vp->nval, vp->sval, vp->fval, vp->tval CONT;
      371 +                FATAL("can't %s %s; it's a function.", rw, vp->nval);
      372 +        WARNING("funny variable %p: n=%s s=\"%s\" f=%g t=%o",
      373 +            vp, vp->nval, vp->sval, vp->fval, vp->tval);
 358  374  }
 359  375  
 360  376  uchar *
 361      -setsval(Cell *vp, uchar *s)
      377 +setsval(Cell *vp, const uchar *s)       /* set string val of a Cell */
 362  378  {
 363      -        int     i;
      379 +        uchar *t;
      380 +        int fldno;
 364  381  
      382 +        dprintf(("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n",
      383 +            (void*)vp, vp->nval, s, vp->tval, donerec, donefld));
 365  384          if ((vp->tval & (NUM | STR)) == 0)
 366  385                  funnyvar(vp, "assign to");
 367      -        if (vp->tval & FLD) {
      386 +        if (isfld(vp)) {
 368  387                  donerec = 0;    /* mark $0 invalid */
 369      -                i = fldidx(vp);
 370      -                if (i > *NF)
 371      -                        newfld(i);
 372      -                dprintf(("setting field %d to %s\n", i, s));
 373      -        } else if (vp->tval & REC) {
      388 +                fldno = atoi((const char *)vp->nval);
      389 +                if (fldno > *NF)
      390 +                        newfld(fldno);
      391 +                dprintf(("setting field %d to %s (%p)\n", fldno, s, (void *)s));
      392 +        } else if (isrec(vp)) {
 374  393                  donefld = 0;    /* mark $1... invalid */
 375  394                  donerec = 1;
 376  395          }
 377      -        vp->tval &= ~NUM;
 378      -        vp->tval |= STR;
      396 +        t = tostring(s);        /* in case it's self-assign */
 379  397          if (freeable(vp))
 380  398                  xfree(vp->sval);
      399 +        vp->tval &= ~NUM;
      400 +        vp->tval |= STR;
 381  401          vp->tval &= ~DONTFREE;
 382      -        dprintf(("setsval %p: %s = \"%s\", t=%p\n",
 383      -            (void *)vp,
 384      -            vp->nval ? (char *)vp->nval : "",
 385      -            s,
 386      -            (void *)(vp->tval ? (char *)vp->tval : "")));
 387      -        return (vp->sval = tostring(s));
      402 +        dprintf(("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",
      403 +            (void *)vp, vp->nval, t, (void *)t, vp->tval, donerec, donefld));
      404 +        return (vp->sval = t);
 388  405  }
 389  406  
 390  407  Awkfloat
 391      -r_getfval(Cell *vp)
      408 +getfval(Cell *vp)       /* get float val of a Cell */
 392  409  {
 393  410          if ((vp->tval & (NUM | STR)) == 0)
 394  411                  funnyvar(vp, "read value of");
 395      -        if ((vp->tval & FLD) && donefld == 0)
      412 +        if (isfld(vp) && donefld == 0)
 396  413                  fldbld();
 397      -        else if ((vp->tval & REC) && donerec == 0)
      414 +        else if (isrec(vp) && donerec == 0)
 398  415                  recbld();
 399  416          if (!isnum(vp)) {       /* not a number */
 400  417                  vp->fval = atof((const char *)vp->sval);        /* best guess */
 401      -                if (is_number(vp->sval) && !(vp->tval&CON))
      418 +                if (is_number(vp->sval) && !(vp->tval & CON))
 402  419                          vp->tval |= NUM;        /* make NUM only sparingly */
 403  420          }
 404      -        dprintf(("getfval %p: %s = %g, t=%p\n",
 405      -            (void *)vp, vp->nval, vp->fval, (void *)vp->tval));
      421 +        dprintf(("getfval %p: %s = %g, t=%o\n",
      422 +            (void *)vp, vp->nval, vp->fval, vp->tval));
 406  423          return (vp->fval);
 407  424  }
 408  425  
 409      -uchar *
 410      -r_getsval(Cell *vp)
      426 +static uchar *
      427 +get_str_val(Cell *vp, uchar **fmt)      /* get string val of a Cell */
 411  428  {
 412      -        uchar s[256];
      429 +        uchar s[100];   /* BUG: unchecked */
      430 +        double dtemp;
 413  431  
 414  432          if ((vp->tval & (NUM | STR)) == 0)
 415  433                  funnyvar(vp, "read value of");
 416      -        if ((vp->tval & FLD) && donefld == 0)
      434 +        if (isfld(vp) && donefld == 0)
 417  435                  fldbld();
 418      -        else if ((vp->tval & REC) && donerec == 0)
      436 +        else if (isrec(vp) && donerec == 0)
 419  437                  recbld();
 420      -        if ((vp->tval & STR) == 0) {
 421      -                if (!(vp->tval&DONTFREE))
      438 +        if (isstr(vp) == 0) {
      439 +                if (freeable(vp))
 422  440                          xfree(vp->sval);
 423      -                if ((long long)vp->fval == vp->fval) {
      441 +                /* it's integral */
      442 +                if (modf((long long)vp->fval, &dtemp) == 0) {
 424  443                          (void) snprintf((char *)s, sizeof (s),
 425      -                            "%.20g", vp->fval);
      444 +                            "%.30g", vp->fval);
 426  445                  } else {
 427  446                          /*LINTED*/
 428  447                          (void) snprintf((char *)s, sizeof (s),
 429      -                            (char *)*OFMT, vp->fval);
      448 +                            (char *)*fmt, vp->fval);
 430  449                  }
 431  450                  vp->sval = tostring(s);
 432  451                  vp->tval &= ~DONTFREE;
 433  452                  vp->tval |= STR;
 434  453          }
 435      -        dprintf(("getsval %p: %s = \"%s\", t=%p\n",
 436      -            (void *)vp,
 437      -            vp->nval ? (char *)vp->nval : "",
 438      -            vp->sval ? (char *)vp->sval : "",
 439      -            (void *)vp->tval));
      454 +        dprintf(("getsval %p: %s = \"%s (%p)\", t=%o\n",
      455 +            (void *)vp, vp->nval, vp->sval, (void *)vp->sval, vp->tval));
 440  456          return (vp->sval);
 441  457  }
 442  458  
 443  459  uchar *
 444      -tostring(uchar *s)
      460 +getsval(Cell *vp)       /* get string val of a Cell */
      461 +{
      462 +        return (get_str_val(vp, CONVFMT));
      463 +}
      464 +
      465 +uchar *
      466 +getpssval(Cell *vp)     /* get string val of a Cell for print */
 445  467  {
 446      -        register uchar *p;
      468 +        return (get_str_val(vp, OFMT));
      469 +}
      470 +
      471 +uchar *
      472 +tostring(const uchar *s)        /* make a copy of string s */
      473 +{
      474 +        uchar *p;
 447  475  
 448  476          p = (uchar *)malloc(strlen((char *)s)+1);
 449  477          if (p == NULL)
 450      -                ERROR "out of space in tostring on %s", s FATAL;
      478 +                FATAL("out of space in tostring on %s", s);
 451  479          (void) strcpy((char *)p, (char *)s);
 452  480          return (p);
 453  481  }
 454  482  
 455  483  uchar *
 456      -qstring(uchar *s, int delim)    /* collect string up to delim */
      484 +qstring(const uchar *is, int delim)     /* collect string up to delim */
 457  485  {
 458      -        uchar *cbuf, *ret;
      486 +        const uchar *os = is;
 459  487          int c, n;
 460      -        size_t  cbufsz, cnt;
 461      -
 462      -        init_buf(&cbuf, &cbufsz, LINE_INCR);
      488 +        uchar *s = (uchar *)is;
      489 +        uchar *buf, *bp;
 463  490  
 464      -        for (cnt = 0; (c = *s) != delim; s++) {
      491 +        if ((buf = (uchar *)malloc(strlen((char *)is)+3)) == NULL)
      492 +                FATAL("out of space in qstring(%s)", s);
      493 +        for (bp = buf; (c = *s) != delim; s++) {
 465  494                  if (c == '\n') {
 466      -                        ERROR "newline in string %.10s...", cbuf SYNTAX;
      495 +                        SYNTAX("newline in string %.20s...", os);
 467  496                  } else if (c != '\\') {
 468      -                        expand_buf(&cbuf, &cbufsz, cnt);
 469      -                        cbuf[cnt++] = c;
      497 +                        *bp++ = c;
 470  498                  } else {        /* \something */
 471      -                        expand_buf(&cbuf, &cbufsz, cnt);
 472      -                        switch (c = *++s) {
 473      -                        case '\\':      cbuf[cnt++] = '\\'; break;
 474      -                        case 'n':       cbuf[cnt++] = '\n'; break;
 475      -                        case 't':       cbuf[cnt++] = '\t'; break;
 476      -                        case 'b':       cbuf[cnt++] = '\b'; break;
 477      -                        case 'f':       cbuf[cnt++] = '\f'; break;
 478      -                        case 'r':       cbuf[cnt++] = '\r'; break;
      499 +                        c = *++s;
      500 +                        if (c == 0) {   /* \ at end */
      501 +                                *bp++ = '\\';
      502 +                                break;  /* for loop */
      503 +                        }
      504 +                        switch (c) {
      505 +                        case '\\':      *bp++ = '\\'; break;
      506 +                        case 'n':       *bp++ = '\n'; break;
      507 +                        case 't':       *bp++ = '\t'; break;
      508 +                        case 'b':       *bp++ = '\b'; break;
      509 +                        case 'f':       *bp++ = '\f'; break;
      510 +                        case 'r':       *bp++ = '\r'; break;
 479  511                          default:
 480  512                                  if (!isdigit(c)) {
 481      -                                        cbuf[cnt++] = c;
      513 +                                        *bp++ = c;
 482  514                                          break;
 483  515                                  }
 484  516                                  n = c - '0';
 485  517                                  if (isdigit(s[1])) {
 486  518                                          n = 8 * n + *++s - '0';
 487  519                                          if (isdigit(s[1]))
 488  520                                                  n = 8 * n + *++s - '0';
 489  521                                  }
 490      -                                cbuf[cnt++] = n;
      522 +                                *bp++ = n;
 491  523                                  break;
 492  524                          }
 493  525                  }
 494  526          }
 495      -        cbuf[cnt] = '\0';
 496      -        ret = tostring(cbuf);
 497      -        free(cbuf);
 498      -        return (ret);
      527 +        *bp++ = 0;
      528 +        return (buf);
 499  529  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX