|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T n
Length: 6310 (0x18a6) Types: TextFile Names: »node.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦6dcdebfcf⟧ »EurOpenD3/gnu/gawk/gawk-2.11.1.tar.Z« └─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦6dcdebfcf⟧ »./gawk-2.11.1.tar.Z« └─⟦3c42ca21a⟧ └─⟦this⟧ »gawk-2.11/node.c«
/* * node.c -- routines for node management */ /* * Copyright (C) 1986, 1988, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "awk.h" extern double strtod(); /* * We can't dereference a variable until after we've given it its new value. * This variable points to the value we have to free up */ NODE *deref; AWKNUM r_force_number(n) NODE *n; { char *ptr; #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 if (n->stlen == 0) n->numbr = 0.0; else if (n->stlen == 1) { if (isdigit(n->stptr[0])) { n->numbr = n->stptr[0] - '0'; n->flags |= NUMERIC; } else n->numbr = 0.0; } else { errno = 0; n->numbr = (AWKNUM) strtod(n->stptr, &ptr); /* the following >= should be ==, but for SunOS 3.5 strtod() */ if (errno == 0 && ptr >= n->stptr + n->stlen) n->flags |= NUMERIC; } n->flags |= NUM; 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 char *values[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", }; #define NVAL (sizeof(values)/sizeof(values[0])) NODE * r_force_string(s) NODE *s; { char buf[128]; char *fmt; long num; char *sp = buf; #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 s->flags |= STR; /* should check validity of user supplied OFMT */ fmt = OFMT_node->var_value->stptr; if ((num = s->numbr) == s->numbr) { /* integral value */ if (num < NVAL && num >= 0) { sp = values[num]; s->stlen = 1; } else { (void) sprintf(sp, "%ld", num); s->stlen = strlen(sp); } } else { (void) sprintf(sp, fmt, s->numbr); s->stlen = strlen(sp); } s->stref = 1; emalloc(s->stptr, char *, s->stlen + 1, "force_string"); memcpy(s->stptr, sp, s->stlen+1); 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; } r = newnode(Node_illegal); *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 + 1, "dupnode"); memcpy(r->stptr, n->stptr, r->stlen+1); } return r; } /* this allocates a node with defined numbr */ NODE * make_number(x) AWKNUM x; { register NODE *r; r = newnode(Node_val); r->numbr = x; r->flags |= (NUM|NUMERIC); r->stref = 0; return r; } /* * This creates temporary nodes. They go away quite quickly, so don't use * them for anything important */ NODE * tmp_number(x) AWKNUM x; { NODE *r; r = make_number(x); r->flags |= TEMP; return r; } /* * Make a string node. */ NODE * make_str_node(s, len, scan) char *s; int len; int scan; { register NODE *r; char *pf; register char *pt; register int c; register char *end; r = newnode(Node_val); emalloc(r->stptr, char *, len + 1, s); memcpy(r->stptr, s, len); r->stptr[len] = '\0'; end = &(r->stptr[len]); if (scan) { /* scan for escape sequences */ for (pf = pt = r->stptr; pf < end;) { c = *pf++; if (c == '\\') { c = parse_escape(&pf); if (c < 0) cant_happen(); *pt++ = c; } else *pt++ = c; } len = pt - 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->flags |= (STR|MALLOC); return r; } /* Read the warning under tmp_number */ NODE * tmp_string(s, len) char *s; int len; { register NODE *r; r = make_string(s, len); r->flags |= TEMP; return r; } #define NODECHUNK 100 static NODE *nextfree = NULL; NODE * newnode(ty) NODETYPE ty; { NODE *it; NODE *np; #ifdef MPROF emalloc(it, NODE *, sizeof(NODE), "newnode"); #else if (nextfree == NULL) { /* get more nodes and initialize list */ emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "newnode"); for (np = nextfree; np < &nextfree[NODECHUNK - 1]; np++) np->nextp = np + 1; np->nextp = NULL; } /* get head of freelist */ it = nextfree; nextfree = nextfree->nextp; #endif it->type = ty; it->flags = MALLOC; #ifdef MEMDEBUG fprintf(stderr, "node: new: %0x\n", it); #endif return it; } void freenode(it) NODE *it; { #ifdef DEBUG NODE *nf; #endif #ifdef MEMDEBUG fprintf(stderr, "node: free: %0x\n", it); #endif #ifdef MPROF free((char *) it); #else #ifdef DEBUG for (nf = nextfree; nf; nf = nf->nextp) if (nf == it) fatal("attempt to free free node"); #endif /* add it to head of freelist */ it->nextp = nextfree; nextfree = it; #endif } #ifdef DEBUG pf() { NODE *nf = nextfree; while (nf != NULL) { fprintf(stderr, "%0x ", nf); nf = nf->nextp; } } #endif void do_deref() { if (deref == NULL) return; if (deref->flags & PERM) { deref = 0; return; } if ((deref->flags & MALLOC) || (deref->flags & TEMP)) { deref->flags &= ~TEMP; if (deref->flags & STR) { if (deref->stref > 1 && deref->stref != 255) { deref->stref--; deref = 0; return; } free(deref->stptr); } freenode(deref); } deref = 0; }