Main Page | Class List | Directories | File List | Class Members | File Members

node.c File Reference

#include "awk.h"

Go to the source code of this file.

Defines

#define NVAL   (sizeof(values)/sizeof(values[0]))
#define NODECHUNK   100

Functions

AWKNUM r_force_number (register NODE *n)
NODEformat_val (const char *format, int index, register NODE *s)
NODEr_force_string (register NODE *s)
NODEr_dupnode (NODE *n)
NODEcopynode (NODE *old)
NODEmk_number (AWKNUM x, unsigned int flags)
NODEmake_str_node (char *s, unsigned long len, int flags)
NODEtmp_string (char *s, size_t len)
NODEmore_nodes ()
void unref (register NODE *tmp)
int parse_escape (const char **string_ptr)

Variables

static const char *const values []
NODEnextfree = NULL


Define Documentation

#define NODECHUNK   100
 

Definition at line 388 of file node.c.

Referenced by more_nodes().

#define NVAL   (sizeof(values)/sizeof(values[0]))
 

Definition at line 139 of file node.c.


Function Documentation

NODE* copynode NODE old  ) 
 

Definition at line 292 of file node.c.

References dupnode, exp_node::flags, MALLOC, NULL, and PERM.

Referenced by sub_common().

00293 {
00294         NODE *new;
00295         int saveflags;
00296 
00297         assert(old != NULL);
00298         saveflags = old->flags;
00299         old->flags &= ~(MALLOC|PERM);
00300         new = dupnode(old);
00301         old->flags = saveflags;
00302         return new;
00303 }

NODE* format_val const char *  format,
int  index,
register NODE s
 

Definition at line 144 of file node.c.

References dgettext, do_traditional, double_to_int(), emalloc, fmt_list, format_tree(), freenode, getnode, INTLSTR, LONG_MAX, memcpy, Node_expression_list, NULL, PERM, stlen, STRCUR, TEXTDOMAIN, tmp_string(), exp_node::type, and values.

Referenced by do_print(), and r_force_string().

00145 {
00146         char buf[BUFSIZ];
00147         register char *sp = buf;
00148         double val;
00149         char *orig, *trans, save;
00150 
00151         if (! do_traditional && (s->flags & INTLSTR) != 0) {
00152                 save = s->stptr[s->stlen];
00153                 s->stptr[s->stlen] = '\0';
00154 
00155                 orig = s->stptr;
00156                 trans = dgettext(TEXTDOMAIN, orig);
00157 
00158                 s->stptr[s->stlen] = save;
00159                 return tmp_string(trans, strlen(trans));
00160         }
00161 
00162         /* not an integral value, or out of range */
00163         if ((val = double_to_int(s->numbr)) != s->numbr
00164             || val < LONG_MIN || val > LONG_MAX) {
00165                 /*
00166                  * Once upon a time, if GFMT_WORKAROUND wasn't defined,
00167                  * we just blindly did this:
00168                  *      sprintf(sp, format, s->numbr);
00169                  *      s->stlen = strlen(sp);
00170                  *      s->stfmt = (char) index;
00171                  * but that's no good if, e.g., OFMT is %s. So we punt,
00172                  * and just always format the value ourselves.
00173                  */
00174 
00175                 NODE *dummy, *r;
00176                 unsigned short oflags;
00177                 extern NODE **fmt_list;          /* declared in eval.c */
00178 
00179                 /* create dummy node for a sole use of format_tree */
00180                 getnode(dummy);
00181                 dummy->type = Node_expression_list;
00182                 dummy->lnode = s;
00183                 dummy->rnode = NULL;
00184                 oflags = s->flags;
00185                 s->flags |= PERM; /* prevent from freeing by format_tree() */
00186                 r = format_tree(format, fmt_list[index]->stlen, dummy, 2);
00187                 s->flags = oflags;
00188                 s->stfmt = (char) index;
00189                 s->stlen = r->stlen;
00190                 s->stptr = r->stptr;
00191                 freenode(r);            /* Do not free_temp(r)!  We want */
00192                 freenode(dummy);        /* to keep s->stptr == r->stpr.  */
00193 
00194                 goto no_malloc;
00195         } else {
00196                 /* integral value */
00197                 /* force conversion to long only once */
00198                 register long num = (long) val;
00199                 if (num < NVAL && num >= 0) {
00200                         sp = (char *) values[num];
00201                         s->stlen = 1;
00202                 } else {
00203                         (void) sprintf(sp, "%ld", num);
00204                         s->stlen = strlen(sp);
00205                 }
00206                 s->stfmt = -1;
00207         }
00208         emalloc(s->stptr, char *, s->stlen + 2, "format_val");
00209         memcpy(s->stptr, sp, s->stlen+1);
00210 no_malloc:
00211         s->stref = 1;
00212         s->flags |= STRCUR;
00213         return s;
00214 }

NODE* make_str_node char *  s,
unsigned long  len,
int  flags
 

Definition at line 327 of file node.c.

References _, ALREADY_MALLOCED, do_lint, emalloc, erealloc, exp_node::flags, getnode, lintwarn, MALLOC, memcpy, Node_val, parse_escape(), PERM, SCAN, STRCUR, STRING, and exp_node::type.

Referenced by arg_assign(), assoc_sort_inplace(), cmdline_fs(), concat_exp(), format_tree(), r_tree_eval(), rebuild_record(), and yylex().

00328 {
00329         register NODE *r;
00330 
00331         getnode(r);
00332         r->type = Node_val;
00333         r->flags = (STRING|STRCUR|MALLOC);
00334         if (flags & ALREADY_MALLOCED)
00335                 r->stptr = s;
00336         else {
00337                 emalloc(r->stptr, char *, len + 2, s);
00338                 memcpy(r->stptr, s, len);
00339         }
00340         r->stptr[len] = '\0';
00341                
00342         if ((flags & SCAN) != 0) {      /* scan for escape sequences */
00343                 const char *pf;
00344                 register char *ptm;
00345                 register int c;
00346                 register const char *end;
00347 
00348                 end = &(r->stptr[len]);
00349                 for (pf = ptm = r->stptr; pf < end;) {
00350                         c = *pf++;
00351                         if (c == '\\') {
00352                                 c = parse_escape(&pf);
00353                                 if (c < 0) {
00354                                         if (do_lint)
00355                                                 lintwarn(_("backslash at end of string"));
00356                                         c = '\\';
00357                                 }
00358                                 *ptm++ = c;
00359                         } else
00360                                 *ptm++ = c;
00361                 }
00362                 len = ptm - r->stptr;
00363                 erealloc(r->stptr, char *, len + 1, "make_str_node");
00364                 r->stptr[len] = '\0';
00365                 r->flags |= PERM;
00366         }
00367         r->stlen = len;
00368         r->stref = 1;
00369         r->stfmt = -1;
00370 
00371         return r;
00372 }

NODE* mk_number AWKNUM  x,
unsigned int  flags
 

Definition at line 308 of file node.c.

References exp_node::flags, getnode, Node_val, NULL, and exp_node::type.

00309 {
00310         register NODE *r;
00311 
00312         getnode(r);
00313         r->type = Node_val;
00314         r->numbr = x;
00315         r->flags = flags;
00316 #ifdef GAWKDEBUG
00317         r->stref = 1;
00318         r->stptr = NULL;
00319         r->stlen = 0;
00320 #endif
00321         return r;
00322 }

NODE* more_nodes  ) 
 

Definition at line 393 of file node.c.

References emalloc, exp_node::flags, NODECHUNK, and NULL.

00394 {
00395         register NODE *np;
00396 
00397         /* get more nodes and initialize list */
00398         emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "more_nodes");
00399         for (np = nextfree; np <= &nextfree[NODECHUNK - 1]; np++) {
00400                 np->flags = 0;
00401 #ifndef NO_PROFILING
00402                 np->exec_count = 0;
00403 #endif
00404                 np->nextp = np + 1;
00405         }
00406         --np;
00407         np->nextp = NULL;
00408         np = nextfree;
00409         nextfree = nextfree->nextp;
00410         return np;
00411 }

int parse_escape const char **  string_ptr  ) 
 

Definition at line 487 of file node.c.

References _, BELL, do_lint, do_posix, FALSE, i, ISDIGIT, ISUPPER, ISXDIGIT, lintwarn, TRUE, and warning().

Referenced by make_regexp(), make_str_node(), and vms_arg_fixup().

00488 {
00489         register int c = *(*string_ptr)++;
00490         register int i;
00491         register int count;
00492 
00493         switch (c) {
00494         case 'a':
00495                 return BELL;
00496         case 'b':
00497                 return '\b';
00498         case 'f':
00499                 return '\f';
00500         case 'n':
00501                 return '\n';
00502         case 'r':
00503                 return '\r';
00504         case 't':
00505                 return '\t';
00506         case 'v':
00507                 return '\v';
00508         case '\n':
00509                 return -2;
00510         case 0:
00511                 (*string_ptr)--;
00512                 return -1;
00513         case '0':
00514         case '1':
00515         case '2':
00516         case '3':
00517         case '4':
00518         case '5':
00519         case '6':
00520         case '7':
00521                 i = c - '0';
00522                 count = 0;
00523                 while (++count < 3) {
00524                         if ((c = *(*string_ptr)++) >= '0' && c <= '7') {
00525                                 i *= 8;
00526                                 i += c - '0';
00527                         } else {
00528                                 (*string_ptr)--;
00529                                 break;
00530                         }
00531                 }
00532                 return i;
00533         case 'x':
00534                 if (do_lint) {
00535                         static int didwarn = FALSE;
00536 
00537                         if (! didwarn) {
00538                                 didwarn = TRUE;
00539                                 lintwarn(_("POSIX does not allow `\\x' escapes"));
00540                         }
00541                 }
00542                 if (do_posix)
00543                         return ('x');
00544                 if (! ISXDIGIT((*string_ptr)[0])) {
00545                         warning(_("no hex digits in `\\x' escape sequence"));
00546                         return ('x');
00547                 }
00548                 i = 0;
00549                 for (;;) {
00550                         /* do outside test to avoid multiple side effects */
00551                         c = *(*string_ptr)++;
00552                         if (ISXDIGIT(c)) {
00553                                 i *= 16;
00554                                 if (ISDIGIT(c))
00555                                         i += c - '0';
00556                                 else if (ISUPPER(c))
00557                                         i += c - 'A' + 10;
00558                                 else
00559                                         i += c - 'a' + 10;
00560                         } else {
00561                                 (*string_ptr)--;
00562                                 break;
00563                         }
00564                 }
00565                 return i;
00566         case '\\':
00567         case '"':
00568                 return c;
00569         default:
00570         {
00571                 static short warned[256];
00572                 unsigned char uc = (unsigned char) c;
00573 
00574                 /* N.B.: use unsigned char here to avoid Latin-1 problems */
00575 
00576                 if (! warned[uc]) {
00577                         warned[uc] = TRUE;
00578 
00579                         warning(_("escape sequence `\\%c' treated as plain `%c'"), uc, uc);
00580                 }
00581         }
00582                 return c;
00583         }
00584 }

NODE* r_dupnode NODE n  ) 
 

Definition at line 245 of file node.c.

References emalloc, FIELD, exp_node::flags, getnode, LONG_MAX, MALLOC, memcpy, Node_ahash, Node_val, PERM, STRCUR, TEMP, and exp_node::type.

00246 {
00247         register NODE *r;
00248 
00249 #ifndef DUPNODE_MACRO
00250         if ((n->flags & TEMP) != 0) {
00251                 n->flags &= ~TEMP;
00252                 n->flags |= MALLOC;
00253                 return n;
00254         }
00255         if ((n->flags & PERM) != 0)
00256                 return n;
00257 #endif
00258         if ((n->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) {
00259                 if (n->stref < LONG_MAX)
00260                         n->stref++;
00261                 else
00262                         n->flags |= PERM;
00263                 return n;
00264         } else if ((n->flags & MALLOC) != 0 && n->type == Node_ahash) {
00265                 if (n->ahname_ref < LONG_MAX)
00266                         n->ahname_ref++;
00267                 else
00268                         n->flags |= PERM;
00269                 return n;
00270         }
00271         getnode(r);
00272         *r = *n;
00273         r->flags &= ~(PERM|TEMP|FIELD);
00274         r->flags |= MALLOC;
00275         if (n->type == Node_val && (n->flags & STRCUR) != 0) {
00276                 r->stref = 1;
00277                 emalloc(r->stptr, char *, r->stlen + 2, "dupnode");
00278                 memcpy(r->stptr, n->stptr, r->stlen);
00279                 r->stptr[r->stlen] = '\0';
00280         } else if (n->type == Node_ahash && (n->flags & MALLOC) != 0) {
00281                 r->ahname_ref = 1;
00282                 emalloc(r->ahname_str, char *, r->ahname_len + 2, "dupnode");
00283                 memcpy(r->ahname_str, n->ahname_str, r->ahname_len);
00284                 r->ahname_str[r->ahname_len] = '\0';
00285         }
00286         return r;
00287 }

AWKNUM r_force_number register NODE n  ) 
 

Definition at line 31 of file node.c.

References _, AWKNUM, cant_happen, do_lint, do_non_decimal_data, do_traditional, errno, ISALPHA, ISDIGIT, isnondecimal, ISSPACE, lintwarn, MAYBE_NUM, Node_val, nondec2awknum(), NULL, NUMBER, and NUMCUR.

00032 {
00033         register char *cp;
00034         register char *cpend;
00035         char save;
00036         char *ptr;
00037         unsigned int newflags;
00038         extern double strtod();
00039 
00040 #ifdef GAWKDEBUG
00041         if (n == NULL)
00042                 cant_happen();
00043         if (n->type != Node_val)
00044                 cant_happen();
00045         if (n->flags == 0)
00046                 cant_happen();
00047         if (n->flags & NUMCUR)
00048                 return n->numbr;
00049 #endif
00050 
00051         /* all the conditionals are an attempt to avoid the expensive strtod */
00052 
00053         n->numbr = 0.0;
00054         n->flags |= NUMCUR;
00055 
00056         if (n->stlen == 0) {
00057                 if (0 && do_lint)
00058                         lintwarn(_("can't convert string to float"));
00059                 return 0.0;
00060         }
00061 
00062         cp = n->stptr;
00063         if (ISALPHA(*cp)) {
00064                 if (0 && do_lint)
00065                         lintwarn(_("can't convert string to float"));
00066                 return 0.0;
00067         }
00068 
00069         cpend = cp + n->stlen;
00070         while (cp < cpend && ISSPACE(*cp))
00071                 cp++;
00072         if (cp == cpend || ISALPHA(*cp)) {
00073                 if (0 && do_lint)
00074                         lintwarn(_("can't convert string to float"));
00075                 return 0.0;
00076         }
00077 
00078         if (n->flags & MAYBE_NUM) {
00079                 newflags = NUMBER;
00080                 n->flags &= ~MAYBE_NUM;
00081         } else
00082                 newflags = 0;
00083         if (cpend - cp == 1) {
00084                 if (ISDIGIT(*cp)) {
00085                         n->numbr = (AWKNUM)(*cp - '0');
00086                         n->flags |= newflags;
00087                 } else if (0 && do_lint)
00088                         lintwarn(_("can't convert string to float"));
00089                 return n->numbr;
00090         }
00091 
00092         if (do_non_decimal_data) {
00093                 errno = 0;
00094                 if (! do_traditional && isnondecimal(cp)) {
00095                         n->numbr = nondec2awknum(cp, cpend - cp);
00096                         goto finish;
00097                 }
00098         }
00099 
00100         errno = 0;
00101         save = *cpend;
00102         *cpend = '\0';
00103         n->numbr = (AWKNUM) strtod((const char *) cp, &ptr);
00104 
00105         /* POSIX says trailing space is OK for NUMBER */
00106         while (ISSPACE(*ptr))
00107                 ptr++;
00108         *cpend = save;
00109 finish:
00110         /* the >= should be ==, but for SunOS 3.5 strtod() */
00111         if (errno == 0 && ptr >= cpend) {
00112                 n->flags |= newflags;
00113         } else {
00114                 if (0 && do_lint && ptr < cpend)
00115                         lintwarn(_("can't convert string to float"));
00116                 errno = 0;
00117         }
00118 
00119         return n->numbr;
00120 }

NODE* r_force_string register NODE s  ) 
 

Definition at line 219 of file node.c.

References cant_happen, CONVFMT, CONVFMTidx, format_val(), Node_val, NULL, and STRCUR.

Referenced by r_tree_eval().

00220 {
00221         NODE *ret;
00222 #ifdef GAWKDEBUG
00223         if (s == NULL)
00224                 cant_happen();
00225         if (s->type != Node_val)
00226                 cant_happen();
00227         if (s->stref <= 0)
00228                 cant_happen();
00229         if ((s->flags & STRCUR) != 0
00230             && (s->stfmt == -1 || s->stfmt == CONVFMTidx))
00231                 return s;
00232 #endif
00233 
00234         ret = format_val(CONVFMT, CONVFMTidx, s);
00235         return ret;
00236 }

NODE* tmp_string char *  s,
size_t  len
 

Definition at line 377 of file node.c.

References exp_node::flags, make_string, and TEMP.

Referenced by do_bindtextdomain(), do_chr(), do_dcgettext(), do_dcngettext(), do_fork(), do_match(), do_readfile(), do_stat(), do_strftime(), do_substr(), do_tolower(), do_toupper(), format_val(), load_environ(), load_procinfo(), pty_vs_pipe(), and update_PROCINFO().

00378 {
00379         register NODE *r;
00380 
00381         r = make_string(s, len);
00382         r->flags |= TEMP;
00383         return r;
00384 }

void unref register NODE tmp  ) 
 

Definition at line 437 of file node.c.

References FIELD, free(), freenode, MALLOC, Node_ahash, NULL, PERM, STRCUR, and TEMP.

Referenced by arg_assign(), assign_val(), assoc_clear(), assoc_sort_inplace(), cmdline_fs(), do_close(), do_delete(), do_delete_loop(), do_ext(), do_getline(), do_match(), do_print(), do_split(), format_tree(), interpret(), iop_close(), nextfile(), op_assign(), pop_fcall(), pop_forloop(), r_get_lhs(), r_tree_eval(), re_update(), rebuild_record(), release_all_vars(), reset_record(), set_FS(), set_NF(), set_record(), set_RS(), sub_common(), and update_ERRNO().

00438 {
00439         if (tmp == NULL)
00440                 return;
00441         if ((tmp->flags & PERM) != 0)
00442                 return;
00443         tmp->flags &= ~TEMP;
00444         if ((tmp->flags & MALLOC) != 0) {
00445                 if (tmp->type == Node_ahash) {
00446                         if (tmp->ahname_ref > 1) {
00447                                 tmp->ahname_ref--;
00448                                 return;
00449                         }
00450                         free(tmp->ahname_str);
00451                 } else if ((tmp->flags & STRCUR) != 0) {
00452                         if (tmp->stref > 1) {
00453                                 tmp->stref--;
00454                                 return;
00455                         }
00456                         free(tmp->stptr);
00457                 }
00458                 freenode(tmp);
00459                 return;
00460         }
00461         if ((tmp->flags & FIELD) != 0) {
00462                 freenode(tmp);
00463                 return;
00464         }
00465 }


Variable Documentation

NODE* nextfree = NULL
 

Definition at line 390 of file node.c.

const char* const values[] [static]
 

Initial value:

 {
        "0",
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
}

Definition at line 127 of file node.c.

Referenced by format_val().


© sourcejam.com 2005-2008