⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 node.c

📁 早期freebsd实现
💻 C
字号:
/* * 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. */#include "awk.h"extern double strtod();AWKNUMr_force_number(n)register NODE *n;{	register char *cp;	register char *cpend;	char save;	char *ptr;	unsigned int newflags = 0;#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;	}	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 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;	register long num = 0;#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        /* 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 */		if (num < NVAL && num >= 0) {			sp = 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);	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+1);	}	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	100NODE *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->nextp = np + 1;	np->nextp = NULL;	np = nextfree;	nextfree = nextfree->nextp;	return np;}#ifdef DEBUGvoidfreenode(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 */voidunref(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. */intparse_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;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -