summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/awk/node.c
diff options
context:
space:
mode:
authorsvn2git <svn2git@FreeBSD.org>1994-07-01 08:00:00 +0000
committersvn2git <svn2git@FreeBSD.org>1994-07-01 08:00:00 +0000
commit5e0e9b99dc3fc0ecd49d929db0d57c784b66f481 (patch)
treee779b5a6edddbb949b7990751b12d6f25304ba86 /gnu/usr.bin/awk/node.c
parenta16f65c7d117419bd266c28a1901ef129a337569 (diff)
Diffstat (limited to 'gnu/usr.bin/awk/node.c')
-rw-r--r--gnu/usr.bin/awk/node.c68
1 files changed, 51 insertions, 17 deletions
diff --git a/gnu/usr.bin/awk/node.c b/gnu/usr.bin/awk/node.c
index 65ecb0ed1723..dca4ad191b9f 100644
--- a/gnu/usr.bin/awk/node.c
+++ b/gnu/usr.bin/awk/node.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991, 1992 the Free Software Foundation, Inc.
+ * 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.
@@ -35,7 +35,7 @@ register NODE *n;
register char *cpend;
char save;
char *ptr;
- unsigned int newflags = 0;
+ unsigned int newflags;
#ifdef DEBUG
if (n == NULL)
@@ -69,7 +69,8 @@ register NODE *n;
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');
@@ -101,7 +102,7 @@ register NODE *n;
* (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[] = {
+static const char *values[] = {
"0",
"1",
"2",
@@ -121,7 +122,7 @@ register NODE *s;
{
char buf[128];
register char *sp = buf;
- register long num = 0;
+ double val;
#ifdef DEBUG
if (s == NULL) cant_happen();
@@ -131,26 +132,56 @@ register NODE *s;
if (s->stref != 0) ; /*cant_happen();*/
#endif
- /* avoids floating point exception in DOS*/
- if ( s->numbr <= LONG_MAX && s->numbr >= -LONG_MAX)
- num = (long)s->numbr;
- if ((AWKNUM) num == s->numbr) { /* integral value */
+ /* 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 = values[num];
+ sp = (char *) values[num];
s->stlen = 1;
} else {
(void) sprintf(sp, "%ld", num);
s->stlen = strlen(sp);
}
s->stfmt = -1;
- } else {
- (void) sprintf(sp, CONVFMT, s->numbr);
- s->stlen = strlen(sp);
- s->stfmt = (char)CONVFMTidx;
}
- s->stref = 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;
}
@@ -182,7 +213,8 @@ NODE *n;
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+1);
+ memcpy(r->stptr, n->stptr, r->stlen);
+ r->stptr[r->stlen] = '\0';
}
return r;
}
@@ -285,8 +317,10 @@ more_nodes()
/* get more nodes and initialize list */
emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "newnode");
- for (np = nextfree; np < &nextfree[NODECHUNK - 1]; np++)
+ for (np = nextfree; np < &nextfree[NODECHUNK - 1]; np++) {
+ np->flags = 0;
np->nextp = np + 1;
+ }
np->nextp = NULL;
np = nextfree;
nextfree = nextfree->nextp;