diff options
Diffstat (limited to 'gnu/usr.bin/awk/node.c')
-rw-r--r-- | gnu/usr.bin/awk/node.c | 463 |
1 files changed, 0 insertions, 463 deletions
diff --git a/gnu/usr.bin/awk/node.c b/gnu/usr.bin/awk/node.c deleted file mode 100644 index 748028b..0000000 --- a/gnu/usr.bin/awk/node.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * node.c -- routines for node management - */ - -/* - * Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993 the Free Software Foundation, Inc. - * - * This file is part of GAWK, the GNU implementation of the - * AWK Progamming Language. - * - * GAWK is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GAWK is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GAWK; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "awk.h" - -extern double strtod(); - -AWKNUM -r_force_number(n) -register NODE *n; -{ - register char *cp; - register char *cpend; - char save; - char *ptr; - unsigned int newflags; - -#ifdef DEBUG - if (n == NULL) - cant_happen(); - if (n->type != Node_val) - cant_happen(); - if(n->flags == 0) - cant_happen(); - if (n->flags & NUM) - return n->numbr; -#endif - - /* all the conditionals are an attempt to avoid the expensive strtod */ - - n->numbr = 0.0; - n->flags |= NUM; - - if (n->stlen == 0) - return 0.0; - - cp = n->stptr; - if (isalpha(*cp)) - return 0.0; - - cpend = cp + n->stlen; - while (cp < cpend && isspace(*cp)) - cp++; - if (cp == cpend || isalpha(*cp)) - return 0.0; - - if (n->flags & MAYBE_NUM) { - newflags = NUMBER; - n->flags &= ~MAYBE_NUM; - } else - newflags = 0; - if (cpend - cp == 1) { - if (isdigit(*cp)) { - n->numbr = (AWKNUM)(*cp - '0'); - n->flags |= newflags; - } - return n->numbr; - } - - errno = 0; - save = *cpend; - *cpend = '\0'; - n->numbr = (AWKNUM) strtod((const char *)cp, &ptr); - - /* POSIX says trailing space is OK for NUMBER */ - while (isspace(*ptr)) - ptr++; - *cpend = save; - /* the >= should be ==, but for SunOS 3.5 strtod() */ - if (errno == 0 && ptr >= cpend) - n->flags |= newflags; - else - errno = 0; - - return n->numbr; -} - -/* - * the following lookup table is used as an optimization in force_string - * (more complicated) variations on this theme didn't seem to pay off, but - * systematic testing might be in order at some point - */ -static const char *values[] = { - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", -}; -#define NVAL (sizeof(values)/sizeof(values[0])) - -NODE * -r_force_string(s) -register NODE *s; -{ - char buf[128]; - register char *sp = buf; - double val; - -#ifdef DEBUG - if (s == NULL) cant_happen(); - if (s->type != Node_val) cant_happen(); - if (s->flags & STR) return s; - if (!(s->flags & NUM)) cant_happen(); - if (s->stref != 0) ; /*cant_happen();*/ -#endif - - /* not an integral value, or out of range */ - if ((val = double_to_int(s->numbr)) != s->numbr - || val < LONG_MIN || val > LONG_MAX) { -#ifdef GFMT_WORKAROUND - NODE *dummy, *r; - unsigned short oflags; - extern NODE *format_tree P((const char *, int, NODE *)); - extern NODE **fmt_list; /* declared in eval.c */ - - /* create dummy node for a sole use of format_tree */ - getnode(dummy); - dummy->lnode = s; - dummy->rnode = NULL; - oflags = s->flags; - s->flags |= PERM; /* prevent from freeing by format_tree() */ - r = format_tree(CONVFMT, fmt_list[CONVFMTidx]->stlen, dummy); - s->flags = oflags; - s->stfmt = (char)CONVFMTidx; - s->stlen = r->stlen; - s->stptr = r->stptr; - freenode(r); /* Do not free_temp(r)! We want */ - freenode(dummy); /* to keep s->stptr == r->stpr. */ - - goto no_malloc; -#else - /* - * no need for a "replacement" formatting by gawk, - * just use sprintf - */ - sprintf(sp, CONVFMT, s->numbr); - s->stlen = strlen(sp); - s->stfmt = (char)CONVFMTidx; -#endif /* GFMT_WORKAROUND */ - } else { - /* integral value */ - /* force conversion to long only once */ - register long num = (long) val; - if (num < NVAL && num >= 0) { - sp = (char *) values[num]; - s->stlen = 1; - } else { - (void) sprintf(sp, "%ld", num); - s->stlen = strlen(sp); - } - s->stfmt = -1; - } - emalloc(s->stptr, char *, s->stlen + 2, "force_string"); - memcpy(s->stptr, sp, s->stlen+1); -no_malloc: - s->stref = 1; - s->flags |= STR; - return s; -} - -/* - * Duplicate a node. (For strings, "duplicate" means crank up the - * reference count.) - */ -NODE * -dupnode(n) -NODE *n; -{ - register NODE *r; - - if (n->flags & TEMP) { - n->flags &= ~TEMP; - n->flags |= MALLOC; - return n; - } - if ((n->flags & (MALLOC|STR)) == (MALLOC|STR)) { - if (n->stref < 255) - n->stref++; - return n; - } - getnode(r); - *r = *n; - r->flags &= ~(PERM|TEMP); - r->flags |= MALLOC; - if (n->type == Node_val && (n->flags & STR)) { - r->stref = 1; - emalloc(r->stptr, char *, r->stlen + 2, "dupnode"); - memcpy(r->stptr, n->stptr, r->stlen); - r->stptr[r->stlen] = '\0'; - } - return r; -} - -/* this allocates a node with defined numbr */ -NODE * -mk_number(x, flags) -AWKNUM x; -unsigned int flags; -{ - register NODE *r; - - getnode(r); - r->type = Node_val; - r->numbr = x; - r->flags = flags; -#ifdef DEBUG - r->stref = 1; - r->stptr = 0; - r->stlen = 0; -#endif - return r; -} - -/* - * Make a string node. - */ -NODE * -make_str_node(s, len, flags) -char *s; -size_t len; -int flags; -{ - register NODE *r; - - getnode(r); - r->type = Node_val; - r->flags = (STRING|STR|MALLOC); - if (flags & ALREADY_MALLOCED) - r->stptr = s; - else { - emalloc(r->stptr, char *, len + 2, s); - memcpy(r->stptr, s, len); - } - r->stptr[len] = '\0'; - - if (flags & SCAN) { /* scan for escape sequences */ - char *pf; - register char *ptm; - register int c; - register char *end; - - end = &(r->stptr[len]); - for (pf = ptm = r->stptr; pf < end;) { - c = *pf++; - if (c == '\\') { - c = parse_escape(&pf); - if (c < 0) { - if (do_lint) - warning("backslash at end of string"); - c = '\\'; - } - *ptm++ = c; - } else - *ptm++ = c; - } - len = ptm - r->stptr; - erealloc(r->stptr, char *, len + 1, "make_str_node"); - r->stptr[len] = '\0'; - r->flags |= PERM; - } - r->stlen = len; - r->stref = 1; - r->stfmt = -1; - - return r; -} - -NODE * -tmp_string(s, len) -char *s; -size_t len; -{ - register NODE *r; - - r = make_string(s, len); - r->flags |= TEMP; - return r; -} - - -#define NODECHUNK 100 - -NODE *nextfree = NULL; - -NODE * -more_nodes() -{ - register NODE *np; - - /* get more nodes and initialize list */ - emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "newnode"); - for (np = nextfree; np < &nextfree[NODECHUNK - 1]; np++) { - np->flags = 0; - np->nextp = np + 1; - } - np->nextp = NULL; - np = nextfree; - nextfree = nextfree->nextp; - return np; -} - -#ifdef DEBUG -void -freenode(it) -NODE *it; -{ -#ifdef MPROF - it->stref = 0; - free((char *) it); -#else /* not MPROF */ - /* add it to head of freelist */ - it->nextp = nextfree; - nextfree = it; -#endif /* not MPROF */ -} -#endif /* DEBUG */ - -void -unref(tmp) -register NODE *tmp; -{ - if (tmp == NULL) - return; - if (tmp->flags & PERM) - return; - if (tmp->flags & (MALLOC|TEMP)) { - tmp->flags &= ~TEMP; - if (tmp->flags & STR) { - if (tmp->stref > 1) { - if (tmp->stref != 255) - tmp->stref--; - return; - } - free(tmp->stptr); - } - freenode(tmp); - } -} - -/* - * Parse a C escape sequence. STRING_PTR points to a variable containing a - * pointer to the string to parse. That pointer is updated past the - * characters we use. The value of the escape sequence is returned. - * - * A negative value means the sequence \ newline was seen, which is supposed to - * be equivalent to nothing at all. - * - * If \ is followed by a null character, we return a negative value and leave - * the string pointer pointing at the null character. - * - * If \ is followed by 000, we return 0 and leave the string pointer after the - * zeros. A value of 0 does not mean end of string. - * - * Posix doesn't allow \x. - */ - -int -parse_escape(string_ptr) -char **string_ptr; -{ - register int c = *(*string_ptr)++; - register int i; - register int count; - - switch (c) { - case 'a': - return BELL; - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'v': - return '\v'; - case '\n': - return -2; - case 0: - (*string_ptr)--; - return -1; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - i = c - '0'; - count = 0; - while (++count < 3) { - if ((c = *(*string_ptr)++) >= '0' && c <= '7') { - i *= 8; - i += c - '0'; - } else { - (*string_ptr)--; - break; - } - } - return i; - case 'x': - if (do_lint) { - static int didwarn; - - if (! didwarn) { - didwarn = 1; - warning("Posix does not allow \"\\x\" escapes"); - } - } - if (do_posix) - return ('x'); - i = 0; - while (1) { - if (isxdigit((c = *(*string_ptr)++))) { - i *= 16; - if (isdigit(c)) - i += c - '0'; - else if (isupper(c)) - i += c - 'A' + 10; - else - i += c - 'a' + 10; - } else { - (*string_ptr)--; - break; - } - } - return i; - default: - return c; - } -} |