[BACK]Return to tran.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / awk

Diff for /src/usr.bin/awk/tran.c between version 1.18 and 1.19

version 1.18, 2020/02/27 21:43:46 version 1.19, 2020/06/10 21:00:01
Line 68 
Line 68 
   
 extern Cell **fldtab;  extern Cell **fldtab;
   
   static void
   setfree(Cell *vp)
   {
           if (&vp->sval == FS || &vp->sval == RS ||
               &vp->sval == OFS || &vp->sval == ORS ||
               &vp->sval == OFMT || &vp->sval == CONVFMT ||
               &vp->sval == FILENAME || &vp->sval == SUBSEP)
                   vp->tval |= DONTFREE;
           else
                   vp->tval &= ~DONTFREE;
   }
   
 void syminit(void)      /* initialize symbol table with builtin vars */  void syminit(void)      /* initialize symbol table with builtin vars */
 {  {
         literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);          literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
Line 283 
Line 295 
 {  {
         int fldno;          int fldno;
   
           f += 0.0;               /* normalise negative zero to positive zero */
         if ((vp->tval & (NUM | STR)) == 0)          if ((vp->tval & (NUM | STR)) == 0)
                 funnyvar(vp, "assign to");                  funnyvar(vp, "assign to");
         if (isfld(vp)) {          if (isfld(vp)) {
Line 291 
Line 304 
                 if (fldno > *NF)                  if (fldno > *NF)
                         newfld(fldno);                          newfld(fldno);
                    DPRINTF( ("setting field %d to %g\n", fldno, f) );                     DPRINTF( ("setting field %d to %g\n", fldno, f) );
           } else if (&vp->fval == NF) {
                   donerec = 0;    /* mark $0 invalid */
                   setlastfld(f);
                   DPRINTF( ("setting NF to %g\n", f) );
         } else if (isrec(vp)) {          } else if (isrec(vp)) {
                 donefld = 0;    /* mark $1... invalid */                  donefld = 0;    /* mark $1... invalid */
                 donerec = 1;                  donerec = 1;
         }          }
         if (freeable(vp))          if (freeable(vp))
                 xfree(vp->sval); /* free any previous string */                  xfree(vp->sval); /* free any previous string */
         vp->tval &= ~STR;       /* mark string invalid */          vp->tval &= ~(STR|CONVC|CONVO); /* mark string invalid */
           vp->fmt = NULL;
         vp->tval |= NUM;        /* mark number ok */          vp->tval |= NUM;        /* mark number ok */
         if (f == -0)  /* who would have thought this possible? */          if (f == -0)  /* who would have thought this possible? */
                 f = 0;                  f = 0;
Line 319 
Line 337 
 {  {
         char *t;          char *t;
         int fldno;          int fldno;
           Awkfloat f;
   
            DPRINTF( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n",             DPRINTF( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n",
                 (void*)vp, NN(vp->nval), s, vp->tval, donerec, donefld) );                  (void*)vp, NN(vp->nval), s, vp->tval, donerec, donefld) );
Line 333 
Line 352 
         } else if (isrec(vp)) {          } else if (isrec(vp)) {
                 donefld = 0;    /* mark $1... invalid */                  donefld = 0;    /* mark $1... invalid */
                 donerec = 1;                  donerec = 1;
           } else if (&vp->sval == OFS) {
                   if (donerec == 0)
                           recbld();
         }          }
         t = tostring(s);        /* in case it's self-assign */          t = s ? tostring(s) : tostring("");     /* in case it's self-assign */
         if (freeable(vp))          if (freeable(vp))
                 xfree(vp->sval);                  xfree(vp->sval);
         vp->tval &= ~NUM;          vp->tval &= ~(NUM|CONVC|CONVO);
         vp->tval |= STR;          vp->tval |= STR;
         vp->tval &= ~DONTFREE;          vp->fmt = NULL;
           setfree(vp);
            DPRINTF( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",             DPRINTF( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",
                 (void*)vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) );                  (void*)vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) );
         return(vp->sval = t);          vp->sval = t;
           if (&vp->fval == NF) {
                   donerec = 0;    /* mark $0 invalid */
                   f = getfval(vp);
                   setlastfld(f);
                   DPRINTF( ("setting NF to %g\n", f) );
           }
   
           return(vp->sval);
 }  }
   
 Awkfloat getfval(Cell *vp)      /* get float val of a Cell */  Awkfloat getfval(Cell *vp)      /* get float val of a Cell */
Line 374 
Line 405 
                 fldbld();                  fldbld();
         else if (isrec(vp) && donerec == 0)          else if (isrec(vp) && donerec == 0)
                 recbld();                  recbld();
   
           /*
            * ADR: This is complicated and more fragile than is desirable.
            * Retrieving a string value for a number associates the string
            * value with the scalar.  Previously, the string value was
            * sticky, meaning if converted via OFMT that became the value
            * (even though POSIX wants it to be via CONVFMT). Or if CONVFMT
            * changed after a string value was retrieved, the original value
            * was maintained and used.  Also not per POSIX.
            *
            * We work around this design by adding two additional flags,
            * CONVC and CONVO, indicating how the string value was
            * obtained (via CONVFMT or OFMT) and _also_ maintaining a copy
            * of the pointer to the xFMT format string used for the
            * conversion.  This pointer is only read, **never** dereferenced.
            * The next time we do a conversion, if it's coming from the same
            * xFMT as last time, and the pointer value is different, we
            * know that the xFMT format string changed, and we need to
            * redo the conversion. If it's the same, we don't have to.
            *
            * There are also several cases where we don't do a conversion,
            * such as for a field (see the checks below).
            */
   
           /* Don't duplicate the code for actually updating the value */
   #define update_str_val(vp) \
           { \
                   if (freeable(vp)) \
                           xfree(vp->sval); \
                   if (modf(vp->fval, &dtemp) == 0)        /* it's integral */ \
                           n = asprintf(&vp->sval, "%.30g", vp->fval); \
                   else \
                           n = asprintf(&vp->sval, *fmt, vp->fval); \
                   if (n == -1) \
                           FATAL("out of space in get_str_val"); \
                   vp->tval &= ~DONTFREE; \
                   vp->tval |= STR; \
           }
   
         if (isstr(vp) == 0) {          if (isstr(vp) == 0) {
                 if (freeable(vp))                  update_str_val(vp);
                         xfree(vp->sval);                  if (fmt == OFMT) {
                 if (modf(vp->fval, &dtemp) == 0)        /* it's integral */                          vp->tval &= ~CONVC;
                         n = asprintf(&vp->sval, "%.30g", vp->fval);                          vp->tval |= CONVO;
                 else                  } else {
                         n = asprintf(&vp->sval, *fmt, vp->fval);                          /* CONVFMT */
                 if (n == -1)                          vp->tval &= ~CONVO;
                         FATAL("out of space in get_str_val");                          vp->tval |= CONVC;
                 vp->tval &= ~DONTFREE;                  }
                 vp->tval |= STR;                  vp->fmt = *fmt;
           } else if ((vp->tval & DONTFREE) != 0 || ! isnum(vp) || isfld(vp)) {
                   goto done;
           } else if (isstr(vp)) {
                   if (fmt == OFMT) {
                           if ((vp->tval & CONVC) != 0
                               || ((vp->tval & CONVO) != 0 && vp->fmt != *fmt)) {
                                   update_str_val(vp);
                                   vp->tval &= ~CONVC;
                                   vp->tval |= CONVO;
                                   vp->fmt = *fmt;
                           }
                   } else {
                           /* CONVFMT */
                           if ((vp->tval & CONVO) != 0
                               || ((vp->tval & CONVC) != 0 && vp->fmt != *fmt)) {
                                   update_str_val(vp);
                                   vp->tval &= ~CONVO;
                                   vp->tval |= CONVC;
                                   vp->fmt = *fmt;
                           }
                   }
         }          }
   done:
            DPRINTF( ("getsval %p: %s = \"%s (%p)\", t=%o\n",             DPRINTF( ("getsval %p: %s = \"%s (%p)\", t=%o\n",
                 (void*)vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) );                  (void*)vp, NN(vp->nval), vp->sval, vp->sval, vp->tval) );
         return(vp->sval);          return(vp->sval);
Line 459 
Line 551 
         }          }
         *bp++ = 0;          *bp++ = 0;
         return (char *) buf;          return (char *) buf;
   }
   
   const char *flags2str(int flags)
   {
           static const struct ftab {
                   const char *name;
                   int value;
           } flagtab[] = {
                   { "NUM", NUM },
                   { "STR", STR },
                   { "DONTFREE", DONTFREE },
                   { "CON", CON },
                   { "ARR", ARR },
                   { "FCN", FCN },
                   { "FLD", FLD },
                   { "REC", REC },
                   { "CONVC", CONVC },
                   { "CONVO", CONVO },
                   { NULL, 0 }
           };
           static char buf[100];
           int i, len;
           char *cp = buf;
   
           for (i = 0; flagtab[i].name != NULL; i++) {
                   if ((flags & flagtab[i].value) != 0) {
                           len = snprintf(cp, sizeof(buf) - (cp - buf),
                               "%s%s", cp > buf ? "|" : "", flagtab[i].name);
                           if (len < 0 || len >= sizeof(buf) - (cp - buf))
                                   FATAL("out of space in flags2str");
                           cp += len;
                   }
           }
   
           return buf;
 }  }

Legend:
Removed from v.1.18  
changed lines
  Added in v.1.19