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

📄 run.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************Copyright (C) Lucent Technologies 1997All 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 Lucent Technologies or any ofits entities not be used in advertising or publicity pertainingto distribution of the software without specific, written priorpermission.LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.IN NO EVENT SHALL LUCENT 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 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"#define tempfree(x)	if (istemp(x)) tfree(x); else/*#undef tempfreevoid tempfree(Cell *p) {	if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {		WARNING("bad csub %d in Cell %d %s",			p->csub, p->ctype, p->sval);	}	if (istemp(p))		tfree(p);}*/#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;extern	int	pairstack[];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	nextfilecell	={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };Cell	*jnextfile	= &nextfilecell;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, NUM|STR|DONTFREE };Node	*curnode = NULL;	/* the node being executed, for debugging *//* buffer memory management */int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,	char *whatrtn)/* pbuf:    address of pointer to buffer being managed * psiz:    address of buffer size variable * minlen:  minimum length of buffer needed * quantum: buffer size quantum * pbptr:   address of movable pointer into buffer, or 0 if none * whatrtn: name of the calling routine if failure should cause fatal error * * return   0 for realloc failure, !=0 for success */{	if (minlen > *psiz) {		char *tbuf;		int rminlen = quantum ? minlen % quantum : 0;		int boff = pbptr ? *pbptr - *pbuf : 0;		/* round up to next multiple of quantum */		if (rminlen)			minlen += quantum - rminlen;		tbuf = (char *) realloc(*pbuf, minlen);		if (tbuf == NULL) {			if (whatrtn)				FATAL("out of memory in %s", whatrtn);			return 0;		}		*pbuf = tbuf;		*psiz = minlen;		if (pbptr)			*pbptr = tbuf + boff;	}	return 1;}void run(Node *a)	/* execution of parse tree starts here */{	extern void stdinit(void);	stdinit();	execute(a);	closeall();}Cell *execute(Node *u)	/* execute a node of the parse tree */{	int nobj;	Cell *(*proc)(Node **, int);	Cell *x;	Node *a;	if (u == NULL)		return(True);	for (a = u; ; a = a->nnext) {		curnode = a;		if (isvalue(a)) {			x = (Cell *) (a->narg[0]);			if (isfld(x) && !donefld)				fldbld();			else if (isrec(x) && !donerec)				recbld();			return(x);		}		nobj = a->nobj;		if (notlegal(nobj))	/* probably a Cell* but too risky to print */			FATAL("illegal statement");		proc = proctab[nobj-FIRSTTOKEN];		x = (*proc)(a->narg, nobj);		if (isfld(x) && !donefld)			fldbld();		else if (isrec(x) && !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 */	Cell *x;	if (setjmp(env) != 0)		goto ex;	if (a[0]) {		/* BEGIN */		x = execute(a[0]);		if (isexit(x))			return(True);		if (isjump(x))			FATAL("illegal break, continue, next or nextfile from BEGIN");		tempfree(x);	}	if (a[1] || a[2])		while (getrec(&record, &recsize, 1) > 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))			FATAL("illegal break, continue, next or nextfile from END");		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, "", 0.0, NUM|STR|DONTFREE };	int i, ncall, ndef;	Node *x;	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */	Cell *y, *z, *fcn;	char *s;	fcn = execute(a[0]);	/* the function itself */	s = fcn->nval;	if (!isfcn(fcn))		FATAL("calling undefined function %s", s);	if (frame == NULL) {		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));		if (frame == NULL)			FATAL("out of space for stack frames calling %s", s);	}	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, (int) (fp-frame)) );	if (ncall > ndef)		WARNING("function %s called with %d args, uses only %d",			s, ncall, ndef);	if (ncall + ndef > NARGS)		FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);	for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {	/* get call args */		   dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (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)" : y->sval, y->tval) );		if (isfcn(y))			FATAL("can't use function %s as argument in %s", y->nval, s);		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)			FATAL("out of space for stack frames in %s", s);		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, (int) (fp-frame)) );	y = execute((Node *)(fcn->sval));	/* execute body */	   dprintf( ("finished exec of %s, fp=%d\n", s, (int) (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;					tempfree(t);				} 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) || isnextfile(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;	/* BUG? */	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 = ptoi(a[0]);	/* argument number, counting from 0 */	   dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );	if (n+1 > fp->nargs)		FATAL("argument #%d of function %s was not supplied",			n+1, fp->fcncell->nval);	return fp->args[n];}Cell *jump(Node **a, int n)	/* break, continue, next, nextfile, return */{	Cell *y;	switch (n) {	case EXIT:		if (a[0] != NULL) {			y = execute(a[0]);			errorflag = (int) 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 */				FATAL("bad type variable %d", y->tval);			tempfree(y);		}		return(jret);	case NEXT:		return(jnext);	case NEXTFILE:		nextfile();		return(jnextfile);	case BREAK:		return(jbreak);	case CONTINUE:		return(jcont);	default:	/* can't happen */		FATAL("illegal jump type %d", n);	}	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 */	Cell *r, *x;	extern Cell **fldtab;	FILE *fp;	char *buf;	int bufsize = recsize;	int mode;	if ((buf = (char *) malloc(bufsize)) == NULL)		FATAL("out of memory in getline");	fflush(stdout);	/* in case someone is waiting for a prompt */	r = gettemp();	if (a[1] != NULL) {		/* getline < file */		x = execute(a[2]);		/* filename */		mode = ptoi(a[1]);		if (mode == '|')		/* input pipe */			mode = LE;	/* arbitrary flag */		fp = openfile(mode, getsval(x));		tempfree(x);		if (fp == NULL)			n = -1;		else			n = readrec(&buf, &bufsize, fp);		if (n <= 0) {			;		} else if (a[0] != NULL) {	/* getline var <file */			x = execute(a[0]);			setsval(x, buf);			tempfree(x);		} else {			/* getline <file */			setsval(fldtab[0], buf);			if (is_number(fldtab[0]->sval)) {				fldtab[0]->fval = atof(fldtab[0]->sval);				fldtab[0]->tval |= NUM;			}		}	} else {			/* bare getline; use current input */		if (a[0] == NULL)	/* getline */			n = getrec(&record, &recsize, 1);		else {			/* getline var */			n = getrec(&buf, &bufsize, 0);			x = execute(a[0]);			setsval(x, buf);			tempfree(x);		}	}	setfval(r, (Awkfloat) n);	free(buf);	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 */{	Cell *x, *y, *z;	char *s;	Node *np;	char *buf;	int bufsz = recsize;	int nsub = strlen(*SUBSEP);	if ((buf = (char *) malloc(bufsz)) == NULL)		FATAL("out of memory in array");	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);		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))			FATAL("out of memory for %s[%s...]", x->nval, buf);		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 = (char *) makesymtab(NSYMTAB);	}	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);	z->ctype = OCELL;	z->csub = CVAR;	tempfree(x);	free(buf);	return(z);}Cell *awkdelete(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */{	Cell *x, *y;	Node *np;	char *s;	int nsub = strlen(*SUBSEP);	x = execute(a[0]);	/* Cell* for symbol table */	if (!isarr(x))		return True;	if (a[1] == 0) {	/* delete the elements, not the table */		freesymtab(x);		x->tval &= ~STR;		x->tval |= ARR;		x->sval = (char *) makesymtab(NSYMTAB);	} else {		int bufsz = recsize;		char *buf;		if ((buf = (char *) malloc(bufsz)) == NULL)			FATAL("out of memory in adelete");		buf[0] = 0;		for (np = a[1]; np; np = np->nnext) {			y = execute(np);	/* subscript */			s = getsval(y);			if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))				FATAL("out of memory deleting %s[%s...]", x->nval, buf);			strcat(buf, s);				if (np->nnext)				strcat(buf, *SUBSEP);			tempfree(y);		}		freeelem(x, buf);		free(buf);	}	tempfree(x);	return True;}Cell *intest(Node **a, int n)	/* a[0] is index (list), a[1] is symtab */{	Cell *x, *ap, *k;	Node *p;	char *buf;	char *s;	int bufsz = recsize;	int nsub = strlen(*SUBSEP);	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 = (char *) makesymtab(NSYMTAB);	}	if ((buf = (char *) malloc(bufsz)) == NULL) {		FATAL("out of memory in intest");	}	buf[0] = 0;	for (p = a[0]; p; p = p->nnext) {		x = execute(p);	/* expr */		s = getsval(x);		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))			FATAL("out of memory deleting %s[%s...]", x->nval, buf);		strcat(buf, s);		tempfree(x);		if (p->nnext)			strcat(buf, *SUBSEP);	}	k = lookup(buf, (Array *) ap->sval);	tempfree(ap);	free(buf);	if (k == NULL)		return(False);	else		return(True);}Cell *matchop(Node **a, int n)	/* ~ and match() */{	Cell *x, *y;	char *s, *t;	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 = countposn(s, 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);}Cell *boolop(Node **a, int n)	/* a[0] || a[1], a[0] && a[1], !a[0] */{	Cell *x, *y;	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 */		FATAL("unknown boolean operator %d", n);	}	return 0;	/*NOTREACHED*/}Cell *relop(Node **a, int n)	/* a[0 < a[1], etc. */

⌨️ 快捷键说明

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