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

📄 builtin.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * builtin.c - Builtin functions and various utility procedures  *//*  * 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"#ifndef SRANDOM_PROTOextern void srandom P((int seed));#endif#ifndef linuxextern char *initstate P((unsigned seed, char *state, int n));extern char *setstate P((char *state));extern long random P((void));#endifextern NODE **fields_arr;extern int output_is_tty;static NODE *sub_common P((NODE *tree, int global));#ifdef GFMT_WORKAROUNDchar *gfmt P((double g, int prec, char *buf));#endif#ifdef _CRAY/* Work around a problem in conversion of doubles to exact integers. */#include <float.h>#define Floor(n) floor((n) * (1.0 + DBL_EPSILON))#define Ceil(n) ceil((n) * (1.0 + DBL_EPSILON))/* Force the standard C compiler to use the library math functions. */extern double exp(double);double (*Exp)() = exp;#define exp(x) (*Exp)(x)extern double log(double);double (*Log)() = log;#define log(x) (*Log)(x)#else#define Floor(n) floor(n)#define Ceil(n) ceil(n)#endifstatic voidefwrite(ptr, size, count, fp, from, rp, flush)void *ptr;unsigned size, count;FILE *fp;char *from;struct redirect *rp;int flush;{	errno = 0;	if (fwrite(ptr, size, count, fp) != count)		goto wrerror;	if (flush	  && ((fp == stdout && output_is_tty)	   || (rp && (rp->flag & RED_NOBUF)))) {		fflush(fp);		if (ferror(fp))			goto wrerror;	}	return;  wrerror:	fatal("%s to \"%s\" failed (%s)", from,		rp ? rp->value : "standard output",		errno ? strerror(errno) : "reason unknown");}/* Builtin functions */NODE *do_exp(tree)NODE *tree;{	NODE *tmp;	double d, res;#ifndef exp	double exp P((double));#endif	tmp= tree_eval(tree->lnode);	d = force_number(tmp);	free_temp(tmp);	errno = 0;	res = exp(d);	if (errno == ERANGE)		warning("exp argument %g is out of range", d);	return tmp_number((AWKNUM) res);}NODE *do_index(tree)NODE *tree;{	NODE *s1, *s2;	register char *p1, *p2;	register int l1, l2;	long ret;	s1 = tree_eval(tree->lnode);	s2 = tree_eval(tree->rnode->lnode);	force_string(s1);	force_string(s2);	p1 = s1->stptr;	p2 = s2->stptr;	l1 = s1->stlen;	l2 = s2->stlen;	ret = 0;	if (IGNORECASE) {		while (l1) {			if (l2 > l1)				break;			if (casetable[(int)*p1] == casetable[(int)*p2]			    && (l2 == 1 || strncasecmp(p1, p2, l2) == 0)) {				ret = 1 + s1->stlen - l1;				break;			}			l1--;			p1++;		}	} else {		while (l1) {			if (l2 > l1)				break;			if (*p1 == *p2			    && (l2 == 1 || STREQN(p1, p2, l2))) {				ret = 1 + s1->stlen - l1;				break;			}			l1--;			p1++;		}	}	free_temp(s1);	free_temp(s2);	return tmp_number((AWKNUM) ret);}NODE *do_int(tree)NODE *tree;{	NODE *tmp;	double floor P((double));	double ceil P((double));	double d;	tmp = tree_eval(tree->lnode);	d = force_number(tmp);	if (d >= 0)		d = Floor(d);	else		d = Ceil(d);	free_temp(tmp);	return tmp_number((AWKNUM) d);}NODE *do_length(tree)NODE *tree;{	NODE *tmp;	int len;	tmp = tree_eval(tree->lnode);	len = force_string(tmp)->stlen;	free_temp(tmp);	return tmp_number((AWKNUM) len);}NODE *do_log(tree)NODE *tree;{	NODE *tmp;#ifndef log	double log P((double));#endif	double d, arg;	tmp = tree_eval(tree->lnode);	arg = (double) force_number(tmp);	if (arg < 0.0)		warning("log called with negative argument %g", arg);	d = log(arg);	free_temp(tmp);	return tmp_number((AWKNUM) d);}/* %e and %f formats are not properly implemented.  Someone should fix them *//* Actually, this whole thing should be reimplemented. */NODE *do_sprintf(tree)NODE *tree;{#define bchunk(s,l) if(l) {\    while((l)>ofre) {\      erealloc(obuf, char *, osiz*2, "do_sprintf");\      ofre+=osiz;\      osiz*=2;\    }\    memcpy(obuf+olen,s,(l));\    olen+=(l);\    ofre-=(l);\  }	/* Is there space for something L big in the buffer? */#define chksize(l)  if((l)>ofre) {\    erealloc(obuf, char *, osiz*2, "do_sprintf");\    ofre+=osiz;\    osiz*=2;\  }	/*	 * Get the next arg to be formatted.  If we've run out of args,	 * return "" (Null string) 	 */#define parse_next_arg() {\  if(!carg) { toofew = 1; break; }\  else {\	arg=tree_eval(carg->lnode);\	carg=carg->rnode;\  }\ }	NODE *r;	int toofew = 0;	char *obuf;	int osiz, ofre, olen;	static char chbuf[] = "0123456789abcdef";	static char sp[] = " ";	char *s0, *s1;	int n0;	NODE *sfmt, *arg;	register NODE *carg;	long fw, prec, lj, alt, big;	long *cur;	long val;#ifdef sun386		/* Can't cast unsigned (int/long) from ptr->value */	long tmp_uval;	/* on 386i 4.0.1 C compiler -- it just hangs */#endif	unsigned long uval;	int sgn;	int base;	char cpbuf[30];		/* if we have numbers bigger than 30 */	char *cend = &cpbuf[30];/* chars, we lose, but seems unlikely */	char *cp;	char *fill;	double tmpval;	char *pr_str;	int ucasehex = 0;	char signchar = 0;	int len;	emalloc(obuf, char *, 120, "do_sprintf");	osiz = 120;	ofre = osiz - 1;	olen = 0;	sfmt = tree_eval(tree->lnode);	sfmt = force_string(sfmt);	carg = tree->rnode;	for (s0 = s1 = sfmt->stptr, n0 = sfmt->stlen; n0-- > 0;) {		if (*s1 != '%') {			s1++;			continue;		}		bchunk(s0, s1 - s0);		s0 = s1;		cur = &fw;		fw = 0;		prec = 0;		lj = alt = big = 0;		fill = sp;		cp = cend;		s1++;retry:		--n0;		switch (*s1++) {		case '%':			bchunk("%", 1);			s0 = s1;			break;		case '0':			if (fill != sp || lj)				goto lose;			if (cur == &fw)				fill = "0";	/* FALL through */		case '1':		case '2':		case '3':		case '4':		case '5':		case '6':		case '7':		case '8':		case '9':			if (cur == 0)				goto lose;			*cur = s1[-1] - '0';			while (n0 > 0 && *s1 >= '0' && *s1 <= '9') {				--n0;				*cur = *cur * 10 + *s1++ - '0';			}			goto retry;		case '*':			if (cur == 0)				goto lose;			parse_next_arg();			*cur = force_number(arg);			free_temp(arg);			goto retry;		case ' ':		/* print ' ' or '-' */		case '+':		/* print '+' or '-' */			signchar = *(s1-1);			goto retry;		case '-':			if (lj || fill != sp)				goto lose;			lj++;			goto retry;		case '.':			if (cur != &fw)				goto lose;			cur = &prec;			goto retry;		case '#':			if (alt)				goto lose;			alt++;			goto retry;		case 'l':			if (big)				goto lose;			big++;			goto retry;		case 'c':			parse_next_arg();			if (arg->flags & NUMBER) {#ifdef sun386				tmp_uval = arg->numbr; 				uval= (unsigned long) tmp_uval;#else				uval = (unsigned long) arg->numbr;#endif				cpbuf[0] = uval;				prec = 1;				pr_str = cpbuf;				goto dopr_string;			}			if (! prec)				prec = 1;			else if (prec > arg->stlen)				prec = arg->stlen;			pr_str = arg->stptr;			goto dopr_string;		case 's':			parse_next_arg();			arg = force_string(arg);			if (!prec || prec > arg->stlen)				prec = arg->stlen;			pr_str = arg->stptr;	dopr_string:			if (fw > prec && !lj) {				while (fw > prec) {					bchunk(sp, 1);					fw--;				}			}			bchunk(pr_str, (int) prec);			if (fw > prec) {				while (fw > prec) {					bchunk(sp, 1);					fw--;				}			}			s0 = s1;			free_temp(arg);			break;		case 'd':		case 'i':			parse_next_arg();			val = (long) force_number(arg);			free_temp(arg);			if (val < 0) {				sgn = 1;				val = -val;			} else				sgn = 0;			do {				*--cp = '0' + val % 10;				val /= 10;			} while (val);			if (sgn)				*--cp = '-';			else if (signchar)				*--cp = signchar;			if (prec > fw)				fw = prec;			prec = cend - cp;			if (fw > prec && !lj) {				if (fill != sp && (*cp == '-' || signchar)) {					bchunk(cp, 1);					cp++;					prec--;					fw--;				}				while (fw > prec) {					bchunk(fill, 1);					fw--;				}			}			bchunk(cp, (int) prec);			if (fw > prec) {				while (fw > prec) {					bchunk(fill, 1);					fw--;				}			}			s0 = s1;			break;		case 'u':			base = 10;			goto pr_unsigned;		case 'o':			base = 8;			goto pr_unsigned;		case 'X':			ucasehex = 1;		case 'x':			base = 16;			goto pr_unsigned;	pr_unsigned:			parse_next_arg();			uval = (unsigned long) force_number(arg);			free_temp(arg);			do {				*--cp = chbuf[uval % base];				if (ucasehex && isalpha(*cp))					*cp = toupper(*cp);				uval /= base;			} while (uval);			if (alt && (base == 8 || base == 16)) {				if (base == 16) {					if (ucasehex)						*--cp = 'X';					else						*--cp = 'x';				}				*--cp = '0';			}			prec = cend - cp;			if (fw > prec && !lj) {				while (fw > prec) {					bchunk(fill, 1);					fw--;				}			}			bchunk(cp, (int) prec);			if (fw > prec) {				while (fw > prec) {					bchunk(fill, 1);					fw--;				}			}			s0 = s1;			break;		case 'g':			parse_next_arg();			tmpval = force_number(arg);			free_temp(arg);			chksize(fw + prec + 9);	/* 9==slop */			cp = cpbuf;			*cp++ = '%';			if (lj)				*cp++ = '-';			if (fill != sp)				*cp++ = '0';#ifndef GFMT_WORKAROUND			if (cur != &fw) {				(void) strcpy(cp, "*.*g");				(void) sprintf(obuf + olen, cpbuf, (int) fw, (int) prec, (double) tmpval);			} else {				(void) strcpy(cp, "*g");				(void) sprintf(obuf + olen, cpbuf, (int) fw, (double) tmpval);			}#else	/* GFMT_WORKAROUND */		      {			char *gptr, gbuf[120];#define DEFAULT_G_PRECISION 6			if (fw + prec + 9 > sizeof gbuf) {	/* 9==slop */				emalloc(gptr, char *, fw+prec+9, "do_sprintf(gfmt)");			} else				gptr = gbuf;			(void) gfmt((double) tmpval, cur != &fw ?				    (int) prec : DEFAULT_G_PRECISION, gptr);			*cp++ = '*',  *cp++ = 's',  *cp = '\0';			(void) sprintf(obuf + olen, cpbuf, (int) fw, gptr);			if (fill != sp && *gptr == ' ') {				char *p = gptr;				do { *p++ = '0'; } while (*p == ' ');			}			if (gptr != gbuf) free(gptr);		      }#endif	/* GFMT_WORKAROUND */			len = strlen(obuf + olen);			ofre -= len;			olen += len;			s0 = s1;			break;		case 'f':			parse_next_arg();			tmpval = force_number(arg);			free_temp(arg);			chksize(fw + prec + 9);	/* 9==slop */			cp = cpbuf;			*cp++ = '%';			if (lj)				*cp++ = '-';			if (fill != sp)				*cp++ = '0';			if (cur != &fw) {				(void) strcpy(cp, "*.*f");				(void) sprintf(obuf + olen, cpbuf, (int) fw, (int) prec, (double) tmpval);			} else {				(void) strcpy(cp, "*f");				(void) sprintf(obuf + olen, cpbuf, (int) fw, (double) tmpval);			}			len = strlen(obuf + olen);			ofre -= len;			olen += len;			s0 = s1;			break;		case 'e':			parse_next_arg();			tmpval = force_number(arg);

⌨️ 快捷键说明

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