* node.c -- routines for node management
* Copyright (C) 1986, 1988, 1989, 1991, 1992 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.
unsigned int newflags
= 0;
/* all the conditionals are an attempt to avoid the expensive strtod */
while (cp
< cpend
&& isspace(*cp
))
if (cp
== cpend
|| isalpha(*cp
))
if (n
->flags
& MAYBE_NUM
) {
n
->numbr
= (AWKNUM
)(*cp
- '0');
n
->numbr
= (AWKNUM
) strtod((const char *)cp
, &ptr
);
/* POSIX says trailing space is OK for NUMBER */
/* the >= should be ==, but for SunOS 3.5 strtod() */
if (errno
== 0 && ptr
>= cpend
)
* 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
[] = {
#define NVAL (sizeof(values)/sizeof(values[0]))
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();*/
/* avoids floating point exception in DOS*/
if ( s
->numbr
<= LONG_MAX
&& s
->numbr
>= -LONG_MAX
)
if ((AWKNUM
) num
== s
->numbr
) { /* integral value */
if (num
< NVAL
&& num
>= 0) {
(void) sprintf(sp
, "%ld", num
);
(void) sprintf(sp
, CONVFMT
, s
->numbr
);
s
->stfmt
= (char)CONVFMTidx
;
emalloc(s
->stptr
, char *, s
->stlen
+ 2, "force_string");
memcpy(s
->stptr
, sp
, s
->stlen
+1);
* Duplicate a node. (For strings, "duplicate" means crank up the
if ((n
->flags
& (MALLOC
|STR
)) == (MALLOC
|STR
)) {
r
->flags
&= ~(PERM
|TEMP
);
if (n
->type
== Node_val
&& (n
->flags
& STR
)) {
emalloc(r
->stptr
, char *, r
->stlen
+ 2, "dupnode");
memcpy(r
->stptr
, n
->stptr
, r
->stlen
+1);
/* this allocates a node with defined numbr */
make_str_node(s
, len
, flags
)
r
->flags
= (STRING
|STR
|MALLOC
);
if (flags
& ALREADY_MALLOCED
)
emalloc(r
->stptr
, char *, len
+ 2, s
);
memcpy(r
->stptr
, s
, len
);
if (flags
& SCAN
) { /* scan for escape sequences */
for (pf
= ptm
= r
->stptr
; pf
< end
;) {
warning("backslash at end of string");
erealloc(r
->stptr
, char *, len
+ 1, "make_str_node");
/* get more nodes and initialize list */
emalloc(nextfree
, NODE
*, NODECHUNK
* sizeof(NODE
), "newnode");
for (np
= nextfree
; np
< &nextfree
[NODECHUNK
- 1]; np
++)
nextfree
= nextfree
->nextp
;
/* add it to head of freelist */
if (tmp
->flags
& (MALLOC
|TEMP
)) {
* 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.
register int c
= *(*string_ptr
)++;
if ((c
= *(*string_ptr
)++) >= '0' && c
<= '7') {
warning("Posix does not allow \"\\x\" escapes");
if (isxdigit((c
= *(*string_ptr
)++))) {