home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / languages / gnuawk / src / awk9.c < prev    next >
C/C++ Source or Header  |  1989-04-13  |  6KB  |  335 lines

  1. /*
  2.  * awk9.c -- routines for node management
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. AWKNUM
  29. r_force_number(n)
  30. NODE *n;
  31. {
  32. #ifdef DEBUG
  33.     if (n == NULL)
  34.         cant_happen();
  35.     if (n->type != Node_val)
  36.         cant_happen();
  37.     if(n->flags == 0)
  38.         cant_happen();
  39.     if (n->flags & NUM)
  40.         return n->numbr;
  41. #endif
  42.     n->numbr = (AWKNUM) atof(n->stptr);
  43.     n->flags |= NUM;
  44.     return n->numbr;
  45. }
  46.  
  47. /*
  48.  * the following lookup table is used as an optimization in force_string
  49.  * variations on this theme didn't seem to pay off, but systematic
  50.  * testing might be in order at some point
  51.  */
  52. static char *values[] = {
  53.     "0",
  54.     "1",
  55.     "2",
  56.     "3",
  57.     "4",
  58.     "5",
  59.     "6",
  60.     "7",
  61.     "8",
  62.     "9",
  63. };
  64. #define    NVAL    (sizeof(values)/sizeof(values[0]))
  65.  
  66. NODE *
  67. r_force_string(s)
  68. NODE *s;
  69. {
  70.     char buf[128];
  71.     char *fmt;
  72.     int num;
  73.     char *sp = buf;
  74.  
  75. #ifdef DEBUG
  76.     if (s == NULL)
  77.         cant_happen();
  78.     if (s->type != Node_val)
  79.         cant_happen();
  80.     if (s->flags & STR)
  81.         return s;
  82.     if (!(s->flags & NUM))
  83.         cant_happen();
  84.     if (s->stref != 0)
  85.         cant_happen();
  86. #endif
  87.     s->flags |= STR;
  88.     /* should check validity of user supplied OFMT */
  89.     fmt = OFMT_node->var_value->stptr;
  90.     if (STREQ(fmt, "%.6g") && (long) s->numbr == s->numbr) {
  91.     /* integral value */
  92.         if ((num = s->numbr) < NVAL) {
  93.             sp = values[num];
  94.             s->stlen = 1;
  95.         } else {
  96.         fmt = "%.11g";
  97.             (void) sprintf(sp, fmt, s->numbr);
  98.             s->stlen = strlen(sp);
  99.         }
  100.     } else {
  101.         (void) sprintf(sp, fmt, s->numbr);
  102.         s->stlen = strlen(sp);
  103.     }
  104.     s->stref = 1;
  105.     emalloc(s->stptr, char *, s->stlen + 1, "force_string");
  106.     bcopy(sp, s->stptr, s->stlen+1);
  107.     return s;
  108. }
  109.  
  110. /*
  111.  * This allocates a new node of type ty.  Note that this node will not go
  112.  * away unless freed.
  113.  */
  114. #ifdef notdef
  115. NODE *
  116. newnode(ty)
  117. NODETYPE ty;
  118. {
  119.     register NODE *r;
  120.  
  121.     emalloc(r, NODE *, sizeof(NODE), "newnode");
  122.     r->type = ty;
  123.     r->flags = MALLOC;
  124.     return r;
  125. }
  126.  
  127. freenode(n)
  128. NODE *n;
  129. {
  130.     free((char *)n);
  131. }
  132. #endif
  133.  
  134. /*
  135.  * Duplicate a node.  (For global strings, "duplicate" means crank up the
  136.  * reference count.)  This creates global nodes. . . 
  137.  */
  138. NODE *
  139. dupnode(n)
  140. NODE *n;
  141. {
  142.     register NODE *r;
  143.  
  144.     if (n->flags & TEMP) {
  145.         n->flags &= ~TEMP;
  146.         n->flags |= MALLOC;
  147.         return n;
  148.     }
  149.     if ((n->flags & (MALLOC|STR)) == (MALLOC|STR)) {
  150.         if (n->stref < 255)
  151.             n->stref++;
  152.         return n;
  153.     }
  154.     r = newnode(Node_illegal);
  155.     *r = *n;
  156.     r->flags &= ~(PERM|TEMP);
  157.     r->flags |= MALLOC;
  158.     if (n->type == Node_val && (n->flags & STR)) {
  159.         r->stref = 1;
  160.         emalloc(r->stptr, char *, r->stlen + 1, "dupnode");
  161.         bcopy(n->stptr, r->stptr, r->stlen);
  162.         r->stptr[r->stlen] = '\0';
  163.     }
  164.     return r;
  165. }
  166.  
  167. /* this allocates a node with defined numbr */
  168. /* This creates global nodes! */
  169. NODE *
  170. make_number(x)
  171. AWKNUM x;
  172. {
  173.     register NODE *r;
  174.  
  175.     r = newnode(Node_val);
  176.     r->numbr = x;
  177.     r->flags |= NUM;
  178.     r->stref = 0;
  179.     return r;
  180. }
  181.  
  182. /*
  183.  * This creates temporary nodes.  They go away quite quicly, so don't use
  184.  * them for anything important 
  185.  */
  186. NODE *
  187. tmp_number(x)
  188. AWKNUM x;
  189. {
  190.     NODE *r;
  191.  
  192.     r = make_number(x);
  193.     r->flags |= TEMP;
  194.     return r;
  195. }
  196.  
  197. /*
  198.  * Make a string node.  If len==-1, the string passed in S is supposed to end
  199.  * with a double quote, but have had the beginning double quote already
  200.  * stripped off by yylex. If LEN!=-1, we don't care what s ends with.  This
  201.  * creates a global node 
  202.  */
  203.  
  204. NODE *
  205. make_string(s, len)
  206. char *s;
  207. {
  208.     register NODE *r;
  209.     register char *pf, *pt;
  210.     register int c;
  211.     int count;
  212.  
  213.     /*
  214.      * the aborts are impossible because yylex is supposed to have
  215.      * already checked for unterminated strings 
  216.      */
  217.     if (len == -1) {    /* Called from yyparse, find our own len */
  218.         for (pf = pt = s; *pf != '\0' && *pf != '\"';) {
  219.             c = *pf++;
  220.             switch (c) {
  221.             case '\0':
  222.                 cant_happen();
  223.  
  224.             case '\\':
  225.                 if (*pf == '\0')
  226.                     cant_happen();
  227.                 c = *pf++;
  228.                 switch (c) {
  229.                 case '\\':    /* no massagary needed */
  230.                 case '\'':
  231.                 case '\"':
  232.                     break;
  233.                 case '0':
  234.                 case '1':
  235.                 case '2':
  236.                 case '3':
  237.                 case '4':
  238.                 case '5':
  239.                 case '6':
  240.                 case '7':
  241. #ifdef notdef
  242.                 case '8':
  243.                 case '9':
  244. #endif
  245.                     c -= '0';
  246.                     count = 1;
  247.                     while (*pf && *pf >= '0' && *pf <= '7') {
  248.                         c = c * 8 + *pf++ - '0';
  249.                         if (++count >= 3)
  250.                             break;
  251.                     }
  252.                     break;
  253.                 case 'a':
  254.                     if (strict)
  255.                         goto def;
  256.                     else
  257.                         c = BELL;
  258.                     break;
  259.                 case 'b':
  260.                     c = '\b';
  261.                     break;
  262.                 case 'f':
  263.                     c = '\f';
  264.                     break;
  265.                 case 'n':
  266.                     c = '\n';
  267.                     break;
  268.                 case 'r':
  269.                     c = '\r';
  270.                     break;
  271.                 case 't':
  272.                     c = '\t';
  273.                     break;
  274.                 case 'v':
  275.                     if (strict)
  276.                         goto def;
  277.                     else
  278.                         c = '\v';
  279.                     break;
  280.                 case 'x':
  281.                     if (strict)
  282.                         goto def;
  283.                     else {
  284.                         c = 0;
  285.                         while (*pf && isxdigit(*pf)) {
  286.                             if (isdigit(*pf))
  287.                                 c += *pf - '0';
  288.                             else if (isupper(*pf))
  289.                                 c += *pf - 'A' + 10;
  290.                             else
  291.                                 c += *pf - 'a' + 10;
  292.                             pf++;
  293.                         }
  294.                     }
  295.                     break;
  296.                 default:
  297.                 def:
  298.                     *pt++ = '\\';
  299.                     break;
  300.                 }
  301.                 /* FALL THROUGH */
  302.             default:
  303.                 *pt++ = c;
  304.                 break;
  305.             }
  306.         }
  307.         if (*pf == '\0')
  308.             cant_happen();    /* hit the end of the buf */
  309.         len = pt - s;
  310.     }
  311.     r = newnode(Node_val);
  312.     emalloc(r->stptr, char *, len + 1, s);
  313.     r->stlen = len;
  314.     r->stref = 1;
  315.     bcopy(s, r->stptr, len);
  316.     r->stptr[len] = '\0';    /* a hack */
  317.     r->flags = (STR|MALLOC);
  318.  
  319.     return r;
  320. }
  321.  
  322. /* This should be a macro for speed, but the C compiler chokes. */
  323. /* Read the warning under tmp_number */
  324. NODE *
  325. tmp_string(s, len)
  326. char *s;
  327. int len;
  328. {
  329.     register NODE *r;
  330.  
  331.     r = make_string(s, len);
  332.     r->flags |= TEMP;
  333.     return r;
  334. }
  335.