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

📄 parser.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	*rpp = NULL;	if (redir) {		if (n1->type != NSUBSHELL) {			n2 = (union node *)stalloc(sizeof (struct nredir));			n2->type = NREDIR;			n2->nredir.n = n1;			n1 = n2;		}		n1->nredir.redirect = redir;	}	return n1;}STATIC union node *simplecmd(rpp, redir) 	union node **rpp, *redir;	{	union node *args, **app;	union node **orig_rpp = rpp;	union node *n;	/* If we don't have any redirections already, then we must reset */	/* rpp to be the address of the local redir variable.  */	if (redir == 0)		rpp = &redir;	args = NULL;	app = &args;	/* 	 * We save the incoming value, because we need this for shell	 * functions.  There can not be a redirect or an argument between	 * the function name and the open parenthesis.  	 */	orig_rpp = rpp;	for (;;) {		if (readtoken() == TWORD) {			n = (union node *)stalloc(sizeof (struct narg));			n->type = NARG;			n->narg.text = wordtext;			n->narg.backquote = backquotelist;			*app = n;			app = &n->narg.next;		} else if (lasttoken == TREDIR) {			*rpp = n = redirnode;			rpp = &n->nfile.next;			parsefname();	/* read name of redirection file */		} else if (lasttoken == TLP && app == &args->narg.next					    && rpp == orig_rpp) {			/* We have a function */			if (readtoken() != TRP)				synexpect(TRP);#ifdef notdef			if (! goodname(n->narg.text))				synerror("Bad function name");#endif			n->type = NDEFUN;			n->narg.next = command();			return n;		} else {			tokpushback++;			break;		}	}	*app = NULL;	*rpp = NULL;	n = (union node *)stalloc(sizeof (struct ncmd));	n->type = NCMD;	n->ncmd.backgnd = 0;	n->ncmd.args = args;	n->ncmd.redirect = redir;	return n;}STATIC voidparsefname() {	union node *n = redirnode;	if (readtoken() != TWORD)		synexpect(-1);	if (n->type == NHERE) {		struct heredoc *here = heredoc;		struct heredoc *p;		int i;		if (quoteflag == 0)			n->type = NXHERE;		TRACE(("Here document %d\n", n->type));		if (here->striptabs) {			while (*wordtext == '\t')				wordtext++;		}		if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)			synerror("Illegal eof marker for << redirection");		rmescapes(wordtext);		here->eofmark = wordtext;		here->next = NULL;		if (heredoclist == NULL)			heredoclist = here;		else {			for (p = heredoclist ; p->next ; p = p->next);			p->next = here;		}	} else if (n->type == NTOFD || n->type == NFROMFD) {		if (is_digit(wordtext[0]))			n->ndup.dupfd = digit_val(wordtext[0]);		else if (wordtext[0] == '-')			n->ndup.dupfd = -1;		else			goto bad;		if (wordtext[1] != '\0') {bad:			synerror("Bad fd number");		}	} else {		n->nfile.fname = (union node *)stalloc(sizeof (struct narg));		n = n->nfile.fname;		n->type = NARG;		n->narg.next = NULL;		n->narg.text = wordtext;		n->narg.backquote = backquotelist;	}}/* * Input any here documents. */STATIC voidparseheredoc() {	struct heredoc *here;	union node *n;	while (heredoclist) {		here = heredoclist;		heredoclist = here->next;		if (needprompt) {			setprompt(2);			needprompt = 0;		}		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,				here->eofmark, here->striptabs);		n = (union node *)stalloc(sizeof (struct narg));		n->narg.type = NARG;		n->narg.next = NULL;		n->narg.text = wordtext;		n->narg.backquote = backquotelist;		here->here->nhere.doc = n;	}}STATIC intpeektoken() {	int t;	t = readtoken();	tokpushback++;	return (t);}STATIC int xxreadtoken();STATIC intreadtoken() {	int t;	int savecheckkwd = checkkwd;	struct alias *ap;#ifdef DEBUG	int alreadyseen = tokpushback;#endif		top:	t = xxreadtoken();	if (checkkwd) {		/*		 * eat newlines		 */		if (checkkwd == 2) {			checkkwd = 0;			while (t == TNL) {				parseheredoc();				t = xxreadtoken();			}		} else			checkkwd = 0;		/*		 * check for keywords and aliases		 */		if (t == TWORD && !quoteflag) {			register char * const *pp, *s;			for (pp = (char **)parsekwd; *pp; pp++) {				if (**pp == *wordtext && equal(*pp, wordtext)) {					lasttoken = t = pp - parsekwd + KWDOFFSET;					TRACE(("keyword %s recognized\n", tokname[t]));					goto out;				}			}			if (ap = lookupalias(wordtext, 1)) {				pushstring(ap->val, strlen(ap->val), ap);				checkkwd = savecheckkwd;				goto top;			}		}out:		checkkwd = 0;	}#ifdef DEBUG	if (!alreadyseen)	    TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));	else	    TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));#endif	return (t);}/* * Read the next input token. * If the token is a word, we set backquotelist to the list of cmds in *	backquotes.  We set quoteflag to true if any part of the word was *	quoted. * If the token is TREDIR, then we set redirnode to a structure containing *	the redirection. * In all cases, the variable startlinno is set to the number of the line *	on which the token starts. * * [Change comment:  here documents and internal procedures] * [Readtoken shouldn't have any arguments.  Perhaps we should make the *  word parsing code into a separate routine.  In this case, readtoken *  doesn't need to have any internal procedures, but parseword does. *  We could also make parseoperator in essence the main routine, and *  have parseword (readtoken1?) handle both words and redirection.] */#define RETURN(token)	return lasttoken = tokenSTATIC intxxreadtoken() {	register c;	if (tokpushback) {		tokpushback = 0;		return lasttoken;	}	if (needprompt) {		setprompt(2);		needprompt = 0;	}	startlinno = plinno;	for (;;) {	/* until token or start of word found */		c = pgetc_macro();		if (c == ' ' || c == '\t')			continue;		/* quick check for white space first */		switch (c) {		case ' ': case '\t':			continue;		case '#':			while ((c = pgetc()) != '\n' && c != PEOF);			pungetc();			continue;		case '\\':			if (pgetc() == '\n') {				startlinno = ++plinno;				if (doprompt)					setprompt(2);				else					setprompt(0);				continue;			}			pungetc();			goto breakloop;		case '\n':			plinno++;			needprompt = doprompt;			RETURN(TNL);		case PEOF:			RETURN(TEOF);		case '&':			if (pgetc() == '&')				RETURN(TAND);			pungetc();			RETURN(TBACKGND);		case '|':			if (pgetc() == '|')				RETURN(TOR);			pungetc();			RETURN(TPIPE);		case ';':			if (pgetc() == ';')				RETURN(TENDCASE);			pungetc();			RETURN(TSEMI);		case '(':			RETURN(TLP);		case ')':			RETURN(TRP);		default:			goto breakloop;		}	}breakloop:	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);#undef RETURN}/* * If eofmark is NULL, read a word or a redirection symbol.  If eofmark * is not NULL, read a here document.  In the latter case, eofmark is the * word which marks the end of the document and striptabs is true if * leading tabs should be stripped from the document.  The argument firstc * is the first character of the input token or document. * * Because C does not have internal subroutines, I have simulated them * using goto's to implement the subroutine linkage.  The following macros * will run code that appears at the end of readtoken1. */#define CHECKEND()	{goto checkend; checkend_return:;}#define PARSEREDIR()	{goto parseredir; parseredir_return:;}#define PARSESUB()	{goto parsesub; parsesub_return:;}#define PARSEBACKQOLD()	{oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}#define	PARSEARITH()	{goto parsearith; parsearith_return:;}STATIC intreadtoken1(firstc, syntax, eofmark, striptabs)	int firstc;	char const *syntax;	char *eofmark;	int striptabs;	{	register c = firstc;	register char *out;	int len;	char line[EOFMARKLEN + 1];	struct nodelist *bqlist;	int quotef;	int dblquote;	int varnest;	/* levels of variables expansion */	int arinest;	/* levels of arithmetic expansion */	int parenlevel;	/* levels of parens in arithmetic */	int oldstyle;	char const *prevsyntax;	/* syntax before arithmetic */	startlinno = plinno;	dblquote = 0;	if (syntax == DQSYNTAX)		dblquote = 1;	quotef = 0;	bqlist = NULL;	varnest = 0;	arinest = 0;	parenlevel = 0;	STARTSTACKSTR(out);	loop: {	/* for each line, until end of word */#if ATTY		if (c == '\034' && doprompt		 && attyset() && ! equal(termval(), "emacs")) {			attyline();			if (syntax == BASESYNTAX)				return readtoken();			c = pgetc();			goto loop;		}#endif		CHECKEND();	/* set c to PEOF if at end of here document */		for (;;) {	/* until end of line or end of word */			CHECKSTRSPACE(3, out);	/* permit 3 calls to USTPUTC */			if (parsebackquote && c == '\\') {				c = pgetc();	/* XXX - compat with old /bin/sh */				if (c != '\\' && c != '`' && c != '$') {					pungetc();					c = '\\';				}			}			switch(syntax[c]) {			case CNL:	/* '\n' */				if (syntax == BASESYNTAX)					goto endword;	/* exit outer loop */				USTPUTC(c, out);				plinno++;				if (doprompt)					setprompt(2);				else					setprompt(0);				c = pgetc();				goto loop;		/* continue outer loop */			case CWORD:				USTPUTC(c, out);				break;			case CCTL:				if (eofmark == NULL || dblquote)					USTPUTC(CTLESC, out);				USTPUTC(c, out);				break;			case CBACK:	/* backslash */				c = pgetc();				if (c == PEOF) {					USTPUTC('\\', out);					pungetc();				} else if (c == '\n') {					if (doprompt)						setprompt(2);					else						setprompt(0);				} else {					if (dblquote && c != '\\' && c != '`' && c != '$'							 && (c != '"' || eofmark != NULL))						USTPUTC('\\', out);					if (SQSYNTAX[c] == CCTL)						USTPUTC(CTLESC, out);					USTPUTC(c, out);					quotef++;				}				break;			case CSQUOTE:				syntax = SQSYNTAX;				break;			case CDQUOTE:				syntax = DQSYNTAX;				dblquote = 1;				break;			case CENDQUOTE:				if (eofmark) {					USTPUTC(c, out);				} else {					if (arinest)						syntax = ARISYNTAX;					else						syntax = BASESYNTAX;					quotef++;					dblquote = 0;				}				break;			case CVAR:	/* '$' */				PARSESUB();		/* parse substitution */				break;			case CENDVAR:	/* '}' */				if (varnest > 0) {					varnest--;					USTPUTC(CTLENDVAR, out);				} else {					USTPUTC(c, out);				}				break;			case CLP:	/* '(' in arithmetic */				parenlevel++;

⌨️ 快捷键说明

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