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

📄 run.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************Copyright (C) AT&T 1993All Rights ReservedPermission to use, copy, modify, and distribute this software andits documentation for any purpose and without fee is herebygranted, provided that the above copyright notice appear in allcopies and that both that the copyright notice and thispermission notice and warranty disclaimer appear in supportingdocumentation, and that the name of AT&T or any of its entitiesnot be used in advertising or publicity pertaining todistribution of the software without specific, written priorpermission.AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANYSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGESWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHERIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OFTHIS SOFTWARE.****************************************************************/#define tempfree(x)	if (istemp(x)) tfree(x); else#define DEBUG#include <stdio.h>#include <ctype.h>#include <setjmp.h>#include <math.h>#include <string.h>#include <stdlib.h>#include <time.h>#include "awk.h"#include "y.tab.h"#ifdef _NFILE#ifndef FOPEN_MAX#define FOPEN_MAX _NFILE#endif#endif#ifndef	FOPEN_MAX#define	FOPEN_MAX	40	/* max number of open files */#endif#ifndef RAND_MAX#define RAND_MAX	32767	/* all that ansi guarantees */#endifjmp_buf env;/* an attempt to go a bit faster: *//* #define	execute(p)	(isvalue(p) ? (Cell *)((p)->narg[0]) : r_execute(p)) */#define	execute(p) r_execute(p)#define	getfval(p)	(((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))#define	getsval(p)	(((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))#define PA2NUM	29	/* max number of pat,pat patterns allowed */int	paircnt;		/* number of them in use */int	pairstack[PA2NUM];	/* state of each pat,pat */Node	*winner = NULL;	/* root of parse tree */Cell	*tmps;		/* free temporary cells for execution */static Cell	truecell	={ OBOOL, BTRUE, 0, 0, 1.0, NUM };Cell	*true	= &truecell;static Cell	falsecell	={ OBOOL, BFALSE, 0, 0, 0.0, NUM };Cell	*false	= &falsecell;static Cell	breakcell	={ OJUMP, JBREAK, 0, 0, 0.0, NUM };Cell	*jbreak	= &breakcell;static Cell	contcell	={ OJUMP, JCONT, 0, 0, 0.0, NUM };Cell	*jcont	= &contcell;static Cell	nextcell	={ OJUMP, JNEXT, 0, 0, 0.0, NUM };Cell	*jnext	= &nextcell;static Cell	exitcell	={ OJUMP, JEXIT, 0, 0, 0.0, NUM };Cell	*jexit	= &exitcell;static Cell	retcell		={ OJUMP, JRET, 0, 0, 0.0, NUM };Cell	*jret	= &retcell;static Cell	tempcell	={ OCELL, CTEMP, 0, 0, 0.0, NUM };Node	*curnode = NULL;	/* the node being executed, for debugging */void run(Node *a)	/* execution of parse tree starts here */{	execute(a);	closeall();}Cell *r_execute(Node *u)	/* execute a node of the parse tree */{	register Cell *(*proc)(Node **, int);	register Cell *x;	register Node *a;	if (u == NULL)		return(true);	for (a = u; ; a = a->nnext) {		curnode = a;		if (isvalue(a)) {			x = (Cell *) (a->narg[0]);			if ((x->tval & FLD) && !donefld)				fldbld();			else if ((x->tval & REC) && !donerec)				recbld();			return(x);		}		if (notlegal(a->nobj))	/* probably a Cell* but too risky to print */			ERROR "illegal statement" FATAL;		proc = proctab[a->nobj-FIRSTTOKEN];		x = (*proc)(a->narg, a->nobj);		if ((x->tval & FLD) && !donefld)			fldbld();		else if ((x->tval & REC) && !donerec)			recbld();		if (isexpr(a))			return(x);		if (isjump(x))			return(x);		if (a->nnext == NULL)			return(x);		tempfree(x);	}}Cell *program(Node **a, int n)	/* execute an awk program */{				/* a[0] = BEGIN, a[1] = body, a[2] = END */	register Cell *x;	if (setjmp(env) != 0)		goto ex;	if (a[0]) {		/* BEGIN */		x = execute(a[0]);		if (isexit(x))			return(true);		if (isjump(x))			ERROR "illegal break, continue or next from BEGIN" FATAL;		tempfree(x);	}  loop:	if (a[1] || a[2])		while (getrec(record) > 0) {			x = execute(a[1]);			if (isexit(x))				break;			tempfree(x);		}  ex:	if (setjmp(env) != 0)	/* handles exit within END */		goto ex1;	if (a[2]) {		/* END */		x = execute(a[2]);		if (isbreak(x) || isnext(x) || iscont(x))			ERROR "illegal break, next, or continue from END" FATAL;		tempfree(x);	}  ex1:	return(true);}struct Frame {	/* stack frame for awk function calls */	int nargs;	/* number of arguments in this call */	Cell *fcncell;	/* pointer to Cell for function */	Cell **args;	/* pointer to array of arguments after execute */	Cell *retval;	/* return value */};#define	NARGS	50	/* max args in a call */struct Frame *frame = NULL;	/* base of stack frames; dynamically allocated */int	nframe = 0;		/* number of frames allocated */struct Frame *fp = NULL;	/* frame pointer. bottom level unused */Cell *call(Node **a, int n)	/* function call.  very kludgy and fragile */{	static Cell newcopycell = { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE };	int i, ncall, ndef;	Node *x;	Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn;	uchar *s;	fcn = execute(a[0]);	/* the function itself */	s = fcn->nval;	if (!isfunc(fcn))		ERROR "calling undefined function %s", s FATAL;	if (frame == NULL) {		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));		if (frame == NULL)			ERROR "out of space for stack frames calling %s", s FATAL;	}	for (ncall = 0, x = a[1]; x != NULL; x = x->nnext)	/* args in call */		ncall++;	ndef = (int) fcn->fval;			/* args in defn */	dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame) );	if (ncall > ndef)		ERROR "function %s called with %d args, uses only %d",			s, ncall, ndef WARNING;	if (ncall + ndef > NARGS)		ERROR "function %s has %d arguments, limit %d", s, ncall+ndef, NARGS FATAL;	for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {	/* get call args */		dprintf( ("evaluate args[%d], fp=%d:\n", i, fp-frame) );		y = execute(x);		oargs[i] = y;		dprintf( ("args[%d]: %s %f <%s>, t=%o\n",			   i, y->nval, y->fval, isarr(y) ? "(array)" : (char*) y->sval, y->tval) );		if (isfunc(y))			ERROR "can't use function %s as argument in %s", y->nval, s FATAL;		if (isarr(y))			args[i] = y;	/* arrays by ref */		else			args[i] = copycell(y);		tempfree(y);	}	for ( ; i < ndef; i++) {	/* add null args for ones not provided */		args[i] = gettemp();		*args[i] = newcopycell;	}	fp++;	/* now ok to up frame */	if (fp >= frame + nframe) {		int dfp = fp - frame;	/* old index */		frame = (struct Frame *)			realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));		if (frame == NULL)			ERROR "out of space for stack frames in %s", s FATAL;		fp = frame + dfp;	}	fp->fcncell = fcn;	fp->args = args;	fp->nargs = ndef;	/* number defined with (excess are locals) */	fp->retval = gettemp();	dprintf( ("start exec of %s, fp=%d\n", s, fp-frame) );	y = execute((Node *)(fcn->sval));	/* execute body */	dprintf( ("finished exec of %s, fp=%d\n", s, fp-frame) );	for (i = 0; i < ndef; i++) {		Cell *t = fp->args[i];		if (isarr(t)) {			if (t->csub == CCOPY) {				if (i >= ncall) {					freesymtab(t);					t->csub = CTEMP;				} else {					oargs[i]->tval = t->tval;					oargs[i]->tval &= ~(STR|NUM|DONTFREE);					oargs[i]->sval = t->sval;					tempfree(t);				}			}		} else if (t != y) {	/* kludge to prevent freeing twice */			t->csub = CTEMP;			tempfree(t);		}	}	tempfree(fcn);	if (isexit(y) || isnext(y))		return y;	tempfree(y);		/* this can free twice! */	z = fp->retval;			/* return value */	dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );	fp--;	return(z);}Cell *copycell(Cell *x)	/* make a copy of a cell in a temp */{	Cell *y;	y = gettemp();	y->csub = CCOPY;	/* prevents freeing until call is over */	y->nval = x->nval;	y->sval = x->sval ? tostring(x->sval) : NULL;	y->fval = x->fval;	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */							/* is DONTFREE right? */	return y;}Cell *arg(Node **a, int n)	/* nth argument of a function */{	n = (int) a[0];	/* argument number, counting from 0 */	dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );	if (n+1 > fp->nargs)		ERROR "argument #%d of function %s was not supplied",			n+1, fp->fcncell->nval FATAL;	return fp->args[n];}Cell *jump(Node **a, int n)	/* break, continue, next, continue, return */{	register Cell *y;	switch (n) {	case EXIT:		if (a[0] != NULL) {			y = execute(a[0]);			errorflag = getfval(y);			tempfree(y);		}		longjmp(env, 1);	case RETURN:		if (a[0] != NULL) {			y = execute(a[0]);			if ((y->tval & (STR|NUM)) == (STR|NUM)) {				setsval(fp->retval, getsval(y));				fp->retval->fval = getfval(y);				fp->retval->tval |= NUM;			}			else if (y->tval & STR)				setsval(fp->retval, getsval(y));			else if (y->tval & NUM)				setfval(fp->retval, getfval(y));			else		/* can't happen */				ERROR "bad type variable %d", y->tval FATAL;			tempfree(y);		}		return(jret);	case NEXT:		return(jnext);	case BREAK:		return(jbreak);	case CONTINUE:		return(jcont);	default:	/* can't happen */		ERROR "illegal jump type %d", n FATAL;	}	return 0;	/* not reached */}Cell *getline(Node **a, int n)	/* get next line from specific input */{		/* a[0] is variable, a[1] is operator, a[2] is filename */	register Cell *r, *x;	uchar buf[RECSIZE];	FILE *fp;	fflush(stdout);	/* in case someone is waiting for a prompt */	r = gettemp();	if (a[1] != NULL) {		/* getline < file */		x = execute(a[2]);		/* filename */		if ((int) a[1] == '|')	/* input pipe */			a[1] = (Node *) LE;	/* arbitrary flag */		fp = openfile((int) a[1], getsval(x));		tempfree(x);		if (fp == NULL)			n = -1;		else			n = readrec(buf, sizeof(buf), fp);		if (n <= 0) {			;		} else if (a[0] != NULL) {	/* getline var <file */			setsval(execute(a[0]), buf);		} else {			/* getline <file */			if (!(recloc->tval & DONTFREE))				xfree(recloc->sval);			strcpy(record, buf);			recloc->sval = record;			recloc->tval = REC | STR | DONTFREE;			if (is_a_number(recloc->sval)) {				recloc->fval = atof(recloc->sval);				recloc->tval |= NUM;			}			donerec = 1; donefld = 0;		}	} else {			/* bare getline; use current input */		if (a[0] == NULL)	/* getline */			n = getrec(record);		else {			/* getline var */			n = getrec(buf);			setsval(execute(a[0]), buf);		}	}	setfval(r, (Awkfloat) n);	return r;}Cell *getnf(Node **a, int n)	/* get NF */{	if (donefld == 0)		fldbld();	return (Cell *) a[0];}Cell *array(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */{	register Cell *x, *y, *z;	register uchar *s;	register Node *np;	uchar buf[RECSIZE];	x = execute(a[0]);	/* Cell* for symbol table */	buf[0] = 0;	for (np = a[1]; np; np = np->nnext) {		y = execute(np);	/* subscript */		s = getsval(y);		strcat(buf, s);		if (np->nnext)			strcat(buf, *SUBSEP);		tempfree(y);	}	if (!isarr(x)) {		dprintf( ("making %s into an array\n", x->nval) );		if (freeable(x))			xfree(x->sval);		x->tval &= ~(STR|NUM|DONTFREE);		x->tval |= ARR;		x->sval = (uchar *) makesymtab(NSYMTAB);	}	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);	z->ctype = OCELL;	z->csub = CVAR;	tempfree(x);	return(z);}Cell *adelete(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */{	Cell *x, *y;	Node *np;	uchar buf[RECSIZE], *s;	x = execute(a[0]);	/* Cell* for symbol table */	if (!isarr(x))		return true;	buf[0] = 0;	for (np = a[1]; np; np = np->nnext) {		y = execute(np);	/* subscript */		s = getsval(y);		strcat(buf, s);		if (np->nnext)			strcat(buf, *SUBSEP);		tempfree(y);	}	freeelem(x, buf);	tempfree(x);	return true;}Cell *intest(Node **a, int n)	/* a[0] is index (list), a[1] is symtab */{	register Cell *x, *ap, *k;	Node *p;	char buf[RECSIZE];	uchar *s;	ap = execute(a[1]);	/* array name */	if (!isarr(ap)) {		dprintf( ("making %s into an array\n", ap->nval) );		if (freeable(ap))			xfree(ap->sval);		ap->tval &= ~(STR|NUM|DONTFREE);		ap->tval |= ARR;		ap->sval = (uchar *) makesymtab(NSYMTAB);	}	buf[0] = 0;	for (p = a[0]; p; p = p->nnext) {		x = execute(p);	/* expr */		s = getsval(x);		strcat(buf, s);		tempfree(x);		if (p->nnext)			strcat(buf, *SUBSEP);	}	k = lookup(buf, (Array *) ap->sval);	tempfree(ap);	if (k == NULL)		return(false);	else		return(true);}Cell *matchop(Node **a, int n)	/* ~ and match() */{	register Cell *x, *y;	register uchar *s, *t;	register int i;	fa *pfa;	int (*mf)(fa *, uchar *) = match, mode = 0;	if (n == MATCHFCN) {		mf = pmatch;		mode = 1;	}	x = execute(a[1]);	/* a[1] = target text */	s = getsval(x);	if (a[0] == 0)		/* a[1] == 0: already-compiled reg expr */		i = (*mf)((fa *) a[2], s);	else {		y = execute(a[2]);	/* a[2] = regular expr */		t = getsval(y);		pfa = makedfa(t, mode);		i = (*mf)(pfa, s);		tempfree(y);	}	tempfree(x);	if (n == MATCHFCN) {		int start = patbeg - s + 1;		if (patlen < 0)			start = 0;		setfval(rstartloc, (Awkfloat) start);		setfval(rlengthloc, (Awkfloat) patlen);		x = gettemp();		x->tval = NUM;		x->fval = start;		return x;	} else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0)		return(true);	else		return(false);}Cell *boolop(Node **a, int n)	/* a[0] || a[1], a[0] && a[1], !a[0] */{	register Cell *x, *y;	register int i;	x = execute(a[0]);	i = istrue(x);	tempfree(x);	switch (n) {	case BOR:		if (i) return(true);		y = execute(a[1]);		i = istrue(y);		tempfree(y);		if (i) return(true);		else return(false);	case AND:		if ( !i ) return(false);		y = execute(a[1]);		i = istrue(y);		tempfree(y);		if (i) return(true);		else return(false);	case NOT:		if (i) return(false);		else return(true);	default:	/* can't happen */		ERROR "unknown boolean operator %d", n FATAL;	}	return 0;	/*NOTREACHED*/}Cell *relop(Node **a, int n)	/* a[0 < a[1], etc. */{	register int i;	register Cell *x, *y;	Awkfloat j;	x = execute(a[0]);	y = execute(a[1]);	if (x->tval&NUM && y->tval&NUM) {		j = x->fval - y->fval;		i = j<0? -1: (j>0? 1: 0);	} else {		i = strcmp(getsval(x), getsval(y));	}	tempfree(x);	tempfree(y);	switch (n) {	case LT:	if (i<0) return(true);			else return(false);	case LE:	if (i<=0) return(true);			else return(false);	case NE:	if (i!=0) return(true);			else return(false);	case EQ:	if (i == 0) return(true);			else return(false);	case GE:	if (i>=0) return(true);			else return(false);	case GT:	if (i>0) return(true);			else return(false);	default:	/* can't happen */		ERROR "unknown relational operator %d", n FATAL;	}	return 0;	/*NOTREACHED*/}

⌨️ 快捷键说明

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