home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / TOP / USR / SRC / gawk2.0.t.Z / gawk2.0.t / awk9.c < prev    next >
Text File  |  1988-12-31  |  6KB  |  298 lines

  1. /*
  2.  * routines for node management
  3.  */
  4.  
  5. /*
  6.  * GAWK is distributed in the hope that it will be useful, but WITHOUT ANY
  7.  * WARRANTY.  No author or distributor accepts responsibility to anyone for
  8.  * the consequences of using it or for whether it serves any particular
  9.  * purpose or works at all, unless he says so in writing. Refer to the GAWK
  10.  * General Public License for full details. 
  11.  *
  12.  * Everyone is granted permission to copy, modify and redistribute GAWK, but
  13.  * only under the conditions described in the GAWK General Public License.  A
  14.  * copy of this license is supposed to have been given to you along with GAWK
  15.  * so you can know your rights and responsibilities.  It should be in a file
  16.  * named COPYING.  Among other things, the copyright notice and this notice
  17.  * must be preserved on all copies. 
  18.  *
  19.  * In other words, go ahead and share GAWK, but don't try to stop anyone else
  20.  * from sharing it farther.  Help stamp out software hoarding! 
  21.  */
  22.  
  23. #include "awk.h"
  24.  
  25. extern struct obstack temp_strings;
  26.  
  27. AWKNUM
  28. r_force_number(n)
  29. NODE *n;
  30. {
  31.     double atof();
  32.  
  33. #ifdef DEBUG
  34.     if (n == NULL)
  35.         cant_happen();
  36.     if (n->type != Node_val)
  37.         cant_happen();
  38.     if(n->flags == 0)
  39.         cant_happen();
  40. #endif
  41.     if (n->flags & NUM)
  42.         return n->numbr;
  43.     n->numbr = (AWKNUM) atof(n->stptr);
  44.     n->flags |= NUM;
  45.     return n->numbr;
  46. }
  47.  
  48. NODE *
  49. r_force_string(s)
  50. NODE *s;
  51. {
  52.     char buf[30];
  53.     char *fmt;
  54.  
  55. #ifdef DEBUG
  56.     if (s == NULL)
  57.         cant_happen();
  58.     if (s->type != Node_val)
  59.         cant_happen();
  60. #endif
  61.     if (s->flags & STR)
  62.         return s;
  63. #ifdef DEBUG
  64.     if (!(s->flags & NUM))
  65.         cant_happen();
  66.     if (s->stref != 0)
  67.         cant_happen();
  68. #endif
  69.     s->flags |= STR;
  70.     fmt = OFMT_node->var_value->stptr;
  71.     /* integral value */
  72.     if (STREQ(fmt, "%.6g") && (long) s->numbr == s->numbr)
  73.         fmt = "%.11g";
  74.     /* should check validity of user supplied OFMT */
  75.     (void) sprintf(buf, fmt, s->numbr);
  76.     s->stlen = strlen(buf);
  77.     s->stref = 1;
  78.     emalloc(s->stptr, char *, s->stlen + 1, "force_string");
  79.     memcpy(s->stptr, buf, s->stlen+1);
  80.     return s;
  81. }
  82.  
  83. /*
  84.  * This allocates a new node of type ty.  Note that this node will not go
  85.  * away unless freed.
  86.  */
  87. NODE *
  88. newnode(ty)
  89. NODETYPE ty;
  90. {
  91.     register NODE *r;
  92.  
  93.     emalloc(r, NODE *, sizeof(NODE), "newnode");
  94.     r->type = ty;
  95.     r->flags = MALLOC;
  96.     return r;
  97. }
  98.  
  99. /*
  100.  * Duplicate a node.  (For global strings, "duplicate" means crank up the
  101.  * reference count.)  This creates global nodes. . . 
  102.  */
  103. NODE *
  104. dupnode(n)
  105. NODE *n;
  106. {
  107.     register NODE *r;
  108.  
  109.     if (n->type == Node_val && (n->flags & STR)) {
  110.         if ((n->flags & MEM) == MALLOC) {
  111.             if (n->stref < 255)
  112.             n->stref++;
  113.             return n;
  114.         } else {
  115.             emalloc(r, NODE *, sizeof(NODE), "dupnode");
  116.             *r = *n;
  117.             r->flags &= ~(PERM|TEMP);
  118.             r->flags |= MALLOC;
  119.             r->stref = 1;
  120.             emalloc(r->stptr, char *, r->stlen + 1, "dupnode");
  121.             bcopy(n->stptr, r->stptr, r->stlen);
  122.             r->stptr[r->stlen] = '\0';
  123.             return r;
  124.         }
  125.     } else {
  126.         emalloc(r, NODE *, sizeof(NODE), "dupnode");
  127.         *r = *n;
  128.         r->flags &= ~(PERM|TEMP);
  129.         r->flags |= MALLOC;
  130.         return r;
  131.     }
  132. }
  133.  
  134. /* this allocates a node with defined numbr */
  135. /* This creates global nodes! */
  136. NODE *
  137. make_number(x)
  138. AWKNUM x;
  139. {
  140.     register NODE *r;
  141.  
  142.     r = newnode(Node_val);
  143.     r->numbr = x;
  144.     r->flags |= NUM;
  145.     r->stref = 0;
  146.     return r;
  147. }
  148.  
  149. /*
  150.  * This creates temporary nodes.  They go away quite quicly, so don't use
  151.  * them for anything important 
  152.  */
  153. NODE *
  154. tmp_number(x)
  155. AWKNUM x;
  156. {
  157.     NODE *r;
  158.  
  159. #ifndef DONTDEF
  160.     r = make_number(x);
  161.     r->flags = (TEMP|NUM);
  162.     return r;
  163. #else
  164.     r = (NODE *) obstack_alloc(&temp_strings, sizeof(NODE));
  165.     r->type = Node_val;
  166.     r->numbr = x;
  167.     r->flags = (PERM|NUM);
  168.     r->stref = 0;
  169.     return r;
  170. #endif
  171. }
  172.  
  173. /*
  174.  * Make a string node.  If len==-1, the string passed in S is supposed to end
  175.  * with a double quote, but have had the beginning double quote already
  176.  * stripped off by yylex. If LEN!=-1, we don't care what s ends with.  This
  177.  * creates a global node 
  178.  */
  179.  
  180. NODE *
  181. make_string(s, len)
  182. char *s;
  183. {
  184.     register NODE *r;
  185.     register char *pf, *pt;
  186.     register int c;
  187.     int count;
  188.  
  189.     /*
  190.      * the aborts are impossible because yylex is supposed to have
  191.      * already checked for unterminated strings 
  192.      */
  193.     if (len == -1) {    /* Called from yyparse, find our own len */
  194.         for (pf = pt = s; *pf != '\0' && *pf != '\"';) {
  195.             c = *pf++;
  196.             switch (c) {
  197.             case '\0':
  198.                 cant_happen();
  199.  
  200.             case '\\':
  201.                 if (*pf == '\0')
  202.                     cant_happen();
  203.                 c = *pf++;
  204.                 switch (c) {
  205.                 case '\\':    /* no massagary needed */
  206.                 case '\'':
  207.                 case '\"':
  208.                     break;
  209.                 case '0':
  210.                 case '1':
  211.                 case '2':
  212.                 case '3':
  213.                 case '4':
  214.                 case '5':
  215.                 case '6':
  216.                 case '7':
  217. #ifdef notdef
  218.                 case '8':
  219.                 case '9':
  220. #endif
  221.                     c -= '0';
  222.                     count = 1;
  223.                     while (*pf && *pf >= '0' && *pf <= '7') {
  224.                         c = c * 8 + *pf++ - '0';
  225.                         if (++count >= 3)
  226.                             break;
  227.                     }
  228.                     break;
  229.                 case 'b':
  230.                     c = '\b';
  231.                     break;
  232.                 case 'f':
  233.                     c = '\f';
  234.                     break;
  235.                 case 'n':
  236.                     c = '\n';
  237.                     break;
  238.                 case 'r':
  239.                     c = '\r';
  240.                     break;
  241.                 case 't':
  242.                     c = '\t';
  243.                     break;
  244.                 case 'v':
  245.                     c = '\v';
  246.                     break;
  247.                 default:
  248.                     *pt++ = '\\';
  249.                     break;
  250.                 }
  251.                 /* FALL THROUGH */
  252.             default:
  253.                 *pt++ = c;
  254.                 break;
  255.             }
  256.         }
  257.         if (*pf == '\0')
  258.             cant_happen();    /* hit the end of the buf */
  259.         len = pt - s;
  260.     }
  261.     r = newnode(Node_val);
  262.     emalloc(r->stptr, char *, len + 1, "make_string");
  263.     r->stlen = len;
  264.     r->stref = 1;
  265.     bcopy(s, r->stptr, len);
  266.     r->stptr[len] = '\0';    /* a hack */
  267.     r->flags = (STR|MALLOC);
  268.  
  269.     return r;
  270. }
  271.  
  272. /* This should be a macro for speed, but the C compiler chokes. */
  273. /* Read the warning under tmp_number */
  274. NODE *
  275. tmp_string(s, len)
  276. char *s;
  277. int len;
  278. {
  279.     register NODE *r;
  280.  
  281. #ifndef DONTDEF
  282.     r = make_string(s, len);
  283.     r->flags = (TEMP|STR);
  284.     return r;
  285. #else
  286.     r = (NODE *) obstack_alloc(&temp_strings, sizeof(NODE));
  287.     r->stptr = (char *) obstack_alloc(&temp_strings, len + 1);
  288.     r->type = Node_val;
  289.     r->stlen = len;
  290.     r->stref = 1;
  291.     bcopy(s, r->stptr, len);
  292.     r->stptr[len] = '\0';    /* a hack */
  293.     r->flags = (STR|PERM);
  294.  
  295.     return r;
  296. #endif
  297. }
  298.