henesyinit from p9fce6d0435 years agoHistory
1757 lines · 37.7 KB · C
RawDownload
/*Copyright (c) 1989 AT&T	All Rights Reserved THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. The copyright notice above does not evidence anyactual or intended publication of such source code.*/ #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 <libv.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 */#endif jmp_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 (isnumber(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;	void *p; 	x = execute(a[1]);	/* a[1] = target text */	s = getsval(x);	if (a[0] == 0)		/* a[1] == 0: already-compiled reg expr */		p = (void *) a[2];	else {		y = execute(a[2]);	/* a[2] = regular expr */		t = getsval(y);		p = compre(t);		tempfree(y);	}	if (n == MATCHFCN)		i = pmatch(p, s, s);	else		i = match(p, s, s);	tempfree(x);	if (n == MATCHFCN) {		int start = patbeg - s + 1;		if (patlen < 0)			start = 0;		setfval(rstartloc, (Awkfloat) start);		setfval(rlengthloc, (Awkfloat) countposn(patbeg, 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);

Lines 1–500 of 1757.