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

📄 lex.c

📁 一个开放源代码的 AT&T 的 Korn Shell 的复制品, 支持大多数 ksh89 的特性。
💻 C
📖 第 1 页 / 共 2 页
字号:
			return c;		  case '(':  /*)*/#ifdef KSH			if ((c2 = getsc()) == '(') /*)*/				/* XXX need to handle ((...); (...)) */				c = MDPAREN;			else				ungetsc(c2);#endif /* KSH */			return c;		  /*(*/		  case ')':			return c;		}	}	*wp++ = EOS;		/* terminate word */	yylval.cp = Xclose(ws, wp);	if (state == SWORD#ifdef KSH		|| state == SLETPAREN#endif /* KSH */		)	/* ONEWORD? */		return LWORD;	ungetsc(c);		/* unget terminator */	/* copy word to unprefixed string ident */	for (sp = yylval.cp, dp = ident; dp < ident+IDENT && (c = *sp++) == CHAR; )		*dp++ = *sp++;	/* Make sure the ident array stays '\0' paded */	memset(dp, 0, (ident+IDENT) - dp + 1);	if (c != EOS)		*ident = '\0';	/* word is not unquoted */	if (*ident != '\0' && (cf&(KEYWORD|ALIAS))) {		struct tbl *p;		int h = hash(ident);		/* { */		if ((cf & KEYWORD) && (p = tsearch(&keywords, ident, h))		    && (!(cf & ESACONLY) || p->val.i == ESAC || p->val.i == '}'))		{			afree(yylval.cp, ATEMP);			return p->val.i;		}		if ((cf & ALIAS) && (p = tsearch(&aliases, ident, h))		    && (p->flag & ISSET))		{			register Source *s;			for (s = source; s->type == SALIAS; s = s->next)				if (s->u.tblp == p)					return LWORD;			/* push alias expansion */			s = pushs(SALIAS, source->areap);			s->start = s->str = p->val.s;			s->u.tblp = p;			s->next = source;			source = s;			afree(yylval.cp, ATEMP);			goto Again;		}	}	return LWORD;}static voidgethere(){	register struct ioword **p;	for (p = heres; p < herep; p++)		readhere(*p);	herep = heres;}/* * read "<<word" text into temp file */static voidreadhere(iop)	struct ioword *iop;{	register int c;	char *volatile eof;	char *eofp;	int skiptabs;	XString xs;	char *xp;	int xpos;	eof = evalstr(iop->delim, 0);	if (!(iop->flag & IOEVAL))		ignore_backslash_newline++;	Xinit(xs, xp, 256, ATEMP);	for (;;) {		eofp = eof;		skiptabs = iop->flag & IOSKIP;		xpos = Xsavepos(xs, xp);		while ((c = getsc()) != 0) {			if (skiptabs) {				if (c == '\t')					continue;				skiptabs = 0;			}			if (c != *eofp)				break;			Xcheck(xs, xp);			Xput(xs, xp, c);			eofp++;		}		/* Allow EOF here so commands with out trailing newlines		 * will work (eg, ksh -c '...', $(...), etc).		 */		if (*eofp == '\0' && (c == 0 || c == '\n')) {			xp = Xrestpos(xs, xp, xpos);			break;		}		ungetsc(c);		while ((c = getsc()) != '\n') {			if (c == 0)				yyerror("here document `%s' unclosed\n", eof);			Xcheck(xs, xp);			Xput(xs, xp, c);		}		Xcheck(xs, xp);		Xput(xs, xp, c);	}	Xput(xs, xp, '\0');	iop->heredoc = Xclose(xs, xp);	if (!(iop->flag & IOEVAL))		ignore_backslash_newline--;}void#ifdef HAVE_PROTOTYPESyyerror(const char *fmt, ...)#elseyyerror(fmt, va_alist)	const char *fmt;	va_dcl#endif{	va_list va;	/* pop aliases and re-reads */	while (source->type == SALIAS || source->type == SREREAD)		source = source->next;	source->str = null;	/* zap pending input */	error_prefix(TRUE);	SH_VA_START(va, fmt);	shf_vfprintf(shl_out, fmt, va);	va_end(va);	errorf(null);}/* * input for yylex with alias expansion */Source *pushs(type, areap)	int type;	Area *areap;{	register Source *s;	s = (Source *) alloc(sizeof(Source), areap);	s->type = type;	s->str = null;	s->start = NULL;	s->line = 0;	s->errline = 0;	s->file = NULL;	s->flags = 0;	s->next = NULL;	s->areap = areap;	if (type == SFILE || type == SSTDIN) {		char *dummy;		Xinit(s->xs, dummy, 256, s->areap);	} else		memset(&s->xs, 0, sizeof(s->xs));	return s;}static intgetsc__(){	register Source *s = source;	register int c;	while ((c = *s->str++) == 0) {		s->str = NULL;		/* return 0 for EOF by default */		switch (s->type) {		  case SEOF:			s->str = null;			return 0;		  case SSTDIN:		  case SFILE:			getsc_line(s);			break;		  case SWSTR:			break;		  case SSTRING:			break;		  case SWORDS:			s->start = s->str = *s->u.strv++;			s->type = SWORDSEP;			break;		  case SWORDSEP:			if (*s->u.strv == NULL) {				s->start = s->str = newline;				s->type = SEOF;			} else {				s->start = s->str = space;				s->type = SWORDS;			}			break;		  case SALIAS:			if (s->flags & SF_ALIASEND) {				/* pass on an unused SF_ALIAS flag */				source = s->next;				source->flags |= s->flags & SF_ALIAS;				s = source;			} else if (*s->u.tblp->val.s				 && isspace(strchr(s->u.tblp->val.s, 0)[-1]))			{				source = s = s->next;	/* pop source stack */				/* Note that this alias ended with a space,				 * enabling alias expansion on the following				 * word.				 */				s->flags |= SF_ALIAS;			} else {				/* At this point, we need to keep the current				 * alias in the source list so recursive				 * aliases can be detected and we also need				 * to return the next character.  Do this				 * by temporarily popping the alias to get				 * the next character and then put it back				 * in the source list with the SF_ALIASEND				 * flag set.				 */				source = s->next;	/* pop source stack */				source->flags |= s->flags & SF_ALIAS;				c = getsc__();				if (c) {					s->flags |= SF_ALIASEND;					s->ugbuf[0] = c; s->ugbuf[1] = '\0';					s->start = s->str = s->ugbuf;					s->next = source;					source = s;				} else {					s = source;					/* avoid reading eof twice */					s->str = NULL;					break;				}			}			continue;		  case SREREAD:			if (s->start != s->ugbuf) /* yuck */				afree(s->u.freeme, ATEMP);			source = s = s->next;			continue;		}		if (s->str == NULL) {			s->type = SEOF;			s->start = s->str = null;			return '\0';		}		if (s->flags & SF_ECHO) {			shf_puts(s->str, shl_out);			shf_flush(shl_out);		}	}	return c;}static voidgetsc_line(s)	Source *s;{	char *xp = Xstring(s->xs, xp);	int interactive = Flag(FTALKING) && s->type == SSTDIN;	int have_tty = interactive && (s->flags & SF_TTY);	/* Done here to ensure nothing odd happens when a timeout occurs */	XcheckN(s->xs, xp, LINE);	*xp = '\0';	s->start = s->str = xp;#ifdef KSH	if (have_tty && ksh_tmout) {		ksh_tmout_state = TMOUT_READING;		alarm(ksh_tmout);	}#endif /* KSH */#ifdef EDIT	if (have_tty && (0# ifdef VI			 || Flag(FVI)# endif /* VI */# ifdef EMACS			 || Flag(FEMACS) || Flag(FGMACS)# endif /* EMACS */		))	{		int nread;		nread = x_read(xp, LINE);		if (nread < 0)	/* read error */			nread = 0;		xp[nread] = '\0';		xp += nread;	}	else#endif /* EDIT */	{		if (interactive) {			pprompt(prompt, 0);		} else			s->line++;		while (1) {			char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf);			if (!p && shf_error(s->u.shf)			    && shf_errno(s->u.shf) == EINTR)			{				shf_clearerr(s->u.shf);				if (trap)					runtraps(0);				continue;			}			if (!p || (xp = p, xp[-1] == '\n'))				break;			/* double buffer size */			xp++; /* move past null so doubling works... */			XcheckN(s->xs, xp, Xlength(s->xs, xp));			xp--; /* ...and move back again */		}		/* flush any unwanted input so other programs/builtins		 * can read it.  Not very optimal, but less error prone		 * than flushing else where, dealing with redirections,		 * etc..		 * todo: reduce size of shf buffer (~128?) if SSTDIN		 */		if (s->type == SSTDIN)			shf_flush(s->u.shf);	}	/* XXX: temporary kludge to restore source after a	 * trap may have been executed.	 */	source = s;#ifdef KSH	if (have_tty && ksh_tmout)	{		ksh_tmout_state = TMOUT_EXECUTING;		alarm(0);	}#endif /* KSH */	s->start = s->str = Xstring(s->xs, xp);	strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));	/* Note: if input is all nulls, this is not eof */	if (Xlength(s->xs, xp) == 0) { /* EOF */		if (s->type == SFILE)			shf_fdclose(s->u.shf);		s->str = NULL;	} else if (interactive) {#ifdef HISTORY		char *p = Xstring(s->xs, xp);		if (cur_prompt == PS1)			while (*p && ctype(*p, C_IFS) && ctype(*p, C_IFSWS))				p++;		if (*p) {# ifdef EASY_HISTORY			if (cur_prompt == PS2)				histappend(Xstring(s->xs, xp), 1);			else# endif /* EASY_HISTORY */			{				s->line++;				histsave(s->line, s->str, 1);			}		}#endif /* HISTORY */	}	if (interactive)		set_prompt(PS2, (Source *) 0);}voidset_prompt(to, s)	int to;	Source *s;{	cur_prompt = to;	switch (to) {	case PS1: /* command */#ifdef KSH		/* Substitute ! and !! here, before substitutions are done		 * so ! in expanded variables are not expanded.		 * NOTE: this is not what at&t ksh does (it does it after		 * substitutions, POSIX doesn't say which is to be done.		 */		{			struct shf *shf;			char *ps1;			Area *saved_atemp;			ps1 = str_val(global("PS1"));			shf = shf_sopen((char *) 0, strlen(ps1) * 2,				SHF_WR | SHF_DYNAMIC, (struct shf *) 0);			while (*ps1) {				if (*ps1 != '!' || *++ps1 == '!')					shf_putchar(*ps1++, shf);				else					shf_fprintf(shf, "%d",						s ? s->line + 1 : 0);			}			ps1 = shf_sclose(shf);			saved_atemp = ATEMP;			newenv(E_ERRH);			if (ksh_sigsetjmp(e->jbuf, 0)) {				prompt = safe_prompt;				/* Don't print an error - assume it has already				 * been printed.  Reason is we may have forked				 * to run a command and the child may be				 * unwinding its stack through this code as it				 * exits.				 */			} else				prompt = str_save(substitute(ps1, 0),						 saved_atemp);			quitenv();		}#else /* KSH */		prompt = str_val(global("PS1"));#endif /* KSH */		break;	case PS2: /* command continuation */		prompt = str_val(global("PS2"));		break;	}}/* See also related routine, promptlen() in edit.c */voidpprompt(cp, ntruncate)	const char *cp;	int ntruncate;{#if 0	char nbuf[32];	int c;	while (*cp != 0) {		if (*cp != '!')			c = *cp++;		else if (*++cp == '!')			c = *cp++;		else {			int len;			char *p;			shf_snprintf(p = nbuf, sizeof(nbuf), "%d",				source->line + 1);			len = strlen(nbuf);			if (ntruncate) {				if (ntruncate >= len) {					ntruncate -= len;					continue;				}				p += ntruncate;				len -= ntruncate;				ntruncate = 0;			}			shf_write(p, len, shl_out);			continue;		}		if (ntruncate)			--ntruncate;		else			shf_putc(c, shl_out);	}#endif /* 0 */	shf_puts(cp + ntruncate, shl_out);	shf_flush(shl_out);}/* Read the variable part of a ${...} expression (ie, up to but not including * the :[-+?=#%] or close-brace. */static char *get_brace_var(wsp, wp)	XString *wsp;	char *wp;{	enum parse_state {			   PS_INITIAL, PS_SAW_HASH, PS_IDENT,			   PS_NUMBER, PS_VAR1, PS_END			 }		state;	char c;	state = PS_INITIAL;	while (1) {		c = getsc();		/* State machine to figure out where the variable part ends. */		switch (state) {		  case PS_INITIAL:			if (c == '#') {				state = PS_SAW_HASH;				break;			}			/* fall through.. */		  case PS_SAW_HASH:			if (letter(c))				state = PS_IDENT;			else if (digit(c))				state = PS_NUMBER;			else if (ctype(c, C_VAR1))				state = PS_VAR1;			else				state = PS_END;			break;		  case PS_IDENT:			if (!letnum(c)) {				state = PS_END;				if (c == '[') {					char *tmp, *p;					if (!arraysub(&tmp))						yyerror("missing ]\n");					*wp++ = c;					for (p = tmp; *p; ) {						Xcheck(*wsp, wp);						*wp++ = *p++;					}					afree(tmp, ATEMP);					c = getsc(); /* the ] */				}			}			break;		  case PS_NUMBER:			if (!digit(c))				state = PS_END;			break;		  case PS_VAR1:			state = PS_END;			break;		  case PS_END: /* keep gcc happy */			break;		}		if (state == PS_END) {			*wp++ = '\0';	/* end of variable part */			ungetsc(c);			break;		}		Xcheck(*wsp, wp);		*wp++ = c;	}	return wp;}/* * Save an array subscript - returns true if matching bracket found, false * if eof or newline was found. * (Returned string double null terminated) */static intarraysub(strp)	char **strp;{	XString ws;	char	*wp;	char	c;	int 	depth = 1;	/* we are just past the initial [ */	Xinit(ws, wp, 32, ATEMP);	do {		c = getsc();		Xcheck(ws, wp);		*wp++ = c;		if (c == '[')			depth++;		else if (c == ']')			depth--;	} while (depth > 0 && c && c != '\n');	*wp++ = '\0';	*strp = Xclose(ws, wp);	return depth == 0 ? 1 : 0;}/* Unget a char: handles case when we are already at the start of the buffer */static const char *ungetsc(c)	int c;{	if (backslash_skip)		backslash_skip--;	/* Don't unget eof... */	if (source->str == null && c == '\0')		return source->str;	if (source->str > source->start)		source->str--;	else {		Source *s;		s = pushs(SREREAD, source->areap);		s->ugbuf[0] = c; s->ugbuf[1] = '\0';		s->start = s->str = s->ugbuf;		s->next = source;		source = s;	}	return source->str;}/* Called to get a char that isn't a \newline sequence. */static intgetsc_bn ARGS((void)){	int c, c2;	if (ignore_backslash_newline)		return getsc_();	if (backslash_skip == 1) {		backslash_skip = 2;		return getsc_();	}	backslash_skip = 0;	while (1) {		c = getsc_();		if (c == '\\') {			if ((c2 = getsc_()) == '\n')				/* ignore the \newline; get the next char... */				continue;			ungetsc(c2);			backslash_skip = 1;		}		return c;	}}static Lex_state *push_state_(si, old_end)	State_info *si;	Lex_state *old_end;{	Lex_state	*new = alloc(sizeof(Lex_state) * STATE_BSIZE, ATEMP);	new[0].ls_info.base = old_end;	si->base = &new[0];	si->end = &new[STATE_BSIZE];	return &new[1];}static Lex_state *pop_state_(si, old_end)	State_info *si;	Lex_state *old_end;{	Lex_state *old_base = si->base;	si->base = old_end->ls_info.base - STATE_BSIZE;	si->end = old_end->ls_info.base;	afree(old_base, ATEMP);	return si->base + STATE_BSIZE - 1;;}

⌨️ 快捷键说明

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