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

📄 parser.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
				USTPUTC(c, out);				break;			case CRP:	/* ')' in arithmetic */				if (parenlevel > 0) {					USTPUTC(c, out);					--parenlevel;				} else {					if (pgetc() == ')') {						if (--arinest == 0) {							USTPUTC(CTLENDARI, out);							syntax = prevsyntax;						} else							USTPUTC(')', out);					} else {						/* 						 * unbalanced parens						 *  (don't 2nd guess - no error)						 */						pungetc();						USTPUTC(')', out);					}				}				break;			case CBQUOTE:	/* '`' */				PARSEBACKQOLD();				break;			case CEOF:				goto endword;		/* exit outer loop */			default:				if (varnest == 0)					goto endword;	/* exit outer loop */				USTPUTC(c, out);			}			c = pgetc_macro();		}	}endword:	if (syntax == ARISYNTAX)		synerror("Missing '))'");	if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)		synerror("Unterminated quoted string");	if (varnest != 0) {		startlinno = plinno;		synerror("Missing '}'");	}	USTPUTC('\0', out);	len = out - stackblock();	out = stackblock();	if (eofmark == NULL) {		if ((c == '>' || c == '<')		 && quotef == 0		 && len <= 2		 && (*out == '\0' || is_digit(*out))) {			PARSEREDIR();			return lasttoken = TREDIR;		} else {			pungetc();		}	}	quoteflag = quotef;	backquotelist = bqlist;	grabstackblock(len);	wordtext = out;	return lasttoken = TWORD;/* end of readtoken routine *//* * Check to see whether we are at the end of the here document.  When this * is called, c is set to the first character of the next input line.  If * we are at the end of the here document, this routine sets the c to PEOF. */checkend: {	if (eofmark) {		if (striptabs) {			while (c == '\t')				c = pgetc();		}		if (c == *eofmark) {			if (pfgets(line, sizeof line) != NULL) {				register char *p, *q;				p = line;				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);				if (*p == '\n' && *q == '\0') {					c = PEOF;					plinno++;					needprompt = doprompt;				} else {					pushstring(line, strlen(line), NULL);				}			}		}	}	goto checkend_return;}/* * Parse a redirection operator.  The variable "out" points to a string * specifying the fd to be redirected.  The variable "c" contains the * first character of the redirection operator. */parseredir: {	char fd = *out;	union node *np;	np = (union node *)stalloc(sizeof (struct nfile));	if (c == '>') {		np->nfile.fd = 1;		c = pgetc();		if (c == '>')			np->type = NAPPEND;		else if (c == '&')			np->type = NTOFD;		else {			np->type = NTO;			pungetc();		}	} else {	/* c == '<' */		np->nfile.fd = 0;		c = pgetc();		if (c == '<') {			if (sizeof (struct nfile) != sizeof (struct nhere)) {				np = (union node *)stalloc(sizeof (struct nhere));				np->nfile.fd = 0;			}			np->type = NHERE;			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));			heredoc->here = np;			if ((c = pgetc()) == '-') {				heredoc->striptabs = 1;			} else {				heredoc->striptabs = 0;				pungetc();			}		} else if (c == '&')			np->type = NFROMFD;		else {			np->type = NFROM;			pungetc();		}	}	if (fd != '\0')		np->nfile.fd = digit_val(fd);	redirnode = np;	goto parseredir_return;}/* * Parse a substitution.  At this point, we have read the dollar sign * and nothing else. */parsesub: {	int subtype;	int typeloc;	int flags;	char *p;#ifndef GDB_HACK	static const char types[] = "}-+?=";#endif	c = pgetc();	if (c != '(' && c != '{' && !is_name(c) && !is_special(c)) {		USTPUTC('$', out);		pungetc();	} else if (c == '(') {	/* $(command) or $((arith)) */		if (pgetc() == '(') {			PARSEARITH();		} else {			pungetc();			PARSEBACKQNEW();		}	} else {		USTPUTC(CTLVAR, out);		typeloc = out - stackblock();		USTPUTC(VSNORMAL, out);		subtype = VSNORMAL;		if (c == '{') {			c = pgetc();			subtype = 0;		}		if (is_name(c)) {			do {				STPUTC(c, out);				c = pgetc();			} while (is_in_name(c));		} else {			if (! is_special(c))badsub:				synerror("Bad substitution");			USTPUTC(c, out);			c = pgetc();		}		STPUTC('=', out);		flags = 0;		if (subtype == 0) {			if (c == ':') {				flags = VSNUL;				c = pgetc();			}			p = strchr(types, c);			if (p == NULL)				goto badsub;			subtype = p - types + VSNORMAL;		} else {			pungetc();		}		if (dblquote || arinest)			flags |= VSQUOTE;		*(stackblock() + typeloc) = subtype | flags;		if (subtype != VSNORMAL)			varnest++;	}	goto parsesub_return;}/* * Called to parse command substitutions.  Newstyle is set if the command * is enclosed inside $(...); nlpp is a pointer to the head of the linked * list of commands (passed by reference), and savelen is the number of * characters on the top of the stack which must be preserved. */parsebackq: {	struct nodelist **nlpp;	int savepbq;	union node *n;	char *volatile str;	struct jmploc jmploc;	struct jmploc *volatile savehandler;	int savelen;	savepbq = parsebackquote;	if (setjmp(jmploc.loc)) {		if (str)			ckfree(str);		parsebackquote = 0;		handler = savehandler;		longjmp(handler->loc, 1);	}	INTOFF;	str = NULL;	savelen = out - stackblock();	if (savelen > 0) {		str = ckmalloc(savelen);		bcopy(stackblock(), str, savelen);	}	savehandler = handler;	handler = &jmploc;	INTON;        if (oldstyle) {                /* We must read until the closing backquote, giving special                   treatment to some slashes, and then push the string and                   reread it as input, interpreting it normally.  */                register char *out;                register c;                int savelen;                char *str;                 STARTSTACKSTR(out);                while ((c = pgetc ()) != '`') {                       if (c == '\\') {                                c = pgetc ();                                if (c != '\\' && c != '`' && c != '$'                                    && (!dblquote || c != '"'))                                        STPUTC('\\', out);                       }                       STPUTC(c, out);                }                STPUTC('\0', out);                savelen = out - stackblock();                if (savelen > 0) {                        str = ckmalloc(savelen);                        bcopy(stackblock(), str, savelen);                }                setinputstring(str, 1);        }	nlpp = &bqlist;	while (*nlpp)		nlpp = &(*nlpp)->next;	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));	(*nlpp)->next = NULL;	parsebackquote = oldstyle;	n = list(0);        if (!oldstyle && (readtoken() != TRP))                synexpect(TRP);	(*nlpp)->n = n;        /* Start reading from old file again.  */        if (oldstyle)                popfile();	while (stackblocksize() <= savelen)		growstackblock();	STARTSTACKSTR(out);	if (str) {		bcopy(str, out, savelen);		STADJUST(savelen, out);		INTOFF;		ckfree(str);		str = NULL;		INTON;	}	parsebackquote = savepbq;	handler = savehandler;	if (arinest || dblquote)		USTPUTC(CTLBACKQ | CTLQUOTE, out);	else		USTPUTC(CTLBACKQ, out);	if (oldstyle)		goto parsebackq_oldreturn;	else		goto parsebackq_newreturn;}/* * Parse an arithmetic expansion (indicate start of one and set state) */parsearith: {	if (++arinest == 1) {		prevsyntax = syntax;		syntax = ARISYNTAX;		USTPUTC(CTLARI, out);	} else {		/*		 * we collapse embedded arithmetic expansion to		 * parenthesis, which should be equivalent		 */		USTPUTC('(', out);	}	goto parsearith_return;}} /* end of readtoken */#ifdef mkinitRESET {	tokpushback = 0;	checkkwd = 0;}#endif/* * Returns true if the text contains nothing to expand (no dollar signs * or backquotes). */STATIC intnoexpand(text)	char *text;	{	register char *p;	register char c;	p = text;	while ((c = *p++) != '\0') {		if (c == CTLESC)			p++;		else if (BASESYNTAX[c] == CCTL)			return 0;	}	return 1;}/* * Return true if the argument is a legal variable name (a letter or * underscore followed by zero or more letters, underscores, and digits). */intgoodname(name)	char *name;	{	register char *p;	p = name;	if (! is_name(*p))		return 0;	while (*++p) {		if (! is_in_name(*p))			return 0;	}	return 1;}/* * Called when an unexpected token is read during the parse.  The argument * is the token that is expected, or -1 if more than one type of token can * occur at this point. */STATIC voidsynexpect(token) {	char msg[64];	if (token >= 0) {		fmtstr(msg, 64, "%s unexpected (expecting %s)",			tokname[lasttoken], tokname[token]);	} else {		fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);	}	synerror(msg);}STATIC voidsynerror(msg)	char *msg;	{	if (commandname)		outfmt(&errout, "%s: %d: ", commandname, startlinno);	outfmt(&errout, "Syntax error: %s\n", msg);	error((char *)NULL);}STATIC voidsetprompt(which)	int which;	{	whichprompt = which;	if (!el)		out2str(getprompt(NULL));}/* * called by editline -- any expansions to the prompt *    should be added here. */char *getprompt(unused)	void *unused;	{	switch (whichprompt) {	case 0:		return "";	case 1:		return ps1val();	case 2:		return ps2val();	default:		return "<internal prompt error>";	}}

⌨️ 快捷键说明

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