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

📄 input.c

📁 早期freebsd实现
💻 C
字号:
/* input.c: i/o routines for files and pseudo-files (strings) */#include <errno.h>#include <setjmp.h>#include "rc.h"#include "jbwrap.h"/*   NB: character unget is supported for up to two characters, but NOT   in the case of EOF. Since EOF does not fit in a char, it is easiest   to support only one unget of EOF.*/typedef struct Input {	inputtype t;	char *ibuf;	int fd, index, read, lineno, last;	bool saved, eofread;} Input;#define BUFSIZE ((size_t) 256)char *prompt, *prompt2;bool rcrc;static int dead(void);static int fdgchar(void);static int stringgchar(void);static void history(void);static void ugdead(int);static void pushcommon(void);static char *inbuf;static size_t istacksize, chars_out, chars_in;static bool eofread = FALSE, save_lineno = TRUE;static Input *istack, *itop;static char *histstr;static int histfd;static int (*realgchar)(void);static void (*realugchar)(int);int last;extern int gchar() {	if (eofread) {		eofread = FALSE;		return last = EOF;	}	return (*realgchar)();}extern void ugchar(int c) {	(*realugchar)(c);}static int dead() {	return last = EOF;}static void ugdead(int c) {	return;}static void ugalive(int c) {	if (c == EOF)		eofread = TRUE;	else		inbuf[--chars_out] = c;}/* get the next character from a string. */static int stringgchar() {	return last = (inbuf[chars_out] == '\0' ? EOF : inbuf[chars_out++]);}/* signal-safe readline wrapper *//*   read a character from a file-descriptor. If GNU readline is defined, add a newline and doctor   the buffer to look like a regular fdgchar buffer.*/static int fdgchar() {	if (chars_out >= chars_in + 2) { /* has the buffer been exhausted? if so, replenish it */		while (1) {			long /*ssize_t*/ r = rc_read(istack->fd, inbuf + 2, BUFSIZE);			if (r < 0) {				if (errno == EINTR)					continue; /* Suppose it was interrupted by a signal */				uerror("read");				rc_exit(1);			}			chars_in = (size_t) r;			break;		}		if (chars_in == 0)			return last = EOF;		chars_out = 2;		if (dashvee)			writeall(2, inbuf + 2, chars_in);		history();	}	return last = inbuf[chars_out++];}/* set up the input stack, and put a "dead" input at the bottom, so that yyparse will always read eof */extern void initinput() {	istack = itop = ealloc(istacksize = 256 * sizeof (Input));	istack->t = iFd;	istack->fd = -1;	realugchar = ugalive;}/* push an input source onto the stack. set up a new input buffer, and set gchar() */static void pushcommon() {	size_t idiff;	istack->index = chars_out;	istack->read = chars_in;	istack->ibuf = inbuf;	istack->lineno = lineno;	istack->saved = save_lineno;	istack->last = last;	istack->eofread = eofread;	istack++;	idiff = istack - itop;	if (idiff >= istacksize / sizeof (Input)) {		itop = erealloc(itop, istacksize *= 2);		istack = itop + idiff;	}	realugchar = ugalive;	chars_out = 2;	chars_in = 0;}extern void pushfd(int fd) {	pushcommon();	istack->t = iFd;	save_lineno = TRUE;	istack->fd = fd;	realgchar = fdgchar;	inbuf = ealloc(BUFSIZE + 2);	lineno = 1;}extern void pushstring(char **a, bool save) {	pushcommon();	istack->t = iString;	save_lineno = save;	inbuf = mprint("..%A", a);	realgchar = stringgchar;	if (save_lineno)		lineno = 1;	else		--lineno;}/* remove an input source from the stack. restore the right kind of getchar (string,fd) etc. */extern void popinput() {	if (istack->t == iFd)		close(istack->fd);	efree(inbuf);	--istack;	realgchar = (istack->t == iString ? stringgchar : fdgchar);	if (istack->fd == -1) { /* top of input stack */		realgchar = dead;		realugchar = ugdead;	}	last = istack->last;	eofread = istack->eofread;	inbuf = istack->ibuf;	chars_out = istack->index;	chars_in = istack->read;	if (save_lineno)		lineno = istack->lineno;	else		lineno++;	save_lineno = istack->saved;}/* flush input characters upto newline. Used by scanerror() */extern void flushu() {	int c;	if (last == '\n' || last == EOF)		return;	while ((c = gchar()) != '\n' && c != EOF)		; /* skip to newline */	if (c == EOF)		ugchar(c);}/* the wrapper loop in rc: prompt for commands until EOF, calling yyparse and walk() */extern Node *doit(bool execit) {	bool eof;	Jbwrap j;	Estack e1, e2;	Edata jerror;	if (dashen)		execit = FALSE;	setjmp(j.j);	jerror.jb = &j;	except(eError, jerror, &e1);	for (eof = FALSE; !eof;) {		Edata block;		block.b = newblock();		except(eArena, block, &e2);		SIGCHK;		if (dashell) {			char *fname[3];			fname[1] = concat(varlookup("home"), word("/.rcrc", NULL))->w;			fname[2] = NULL;			rcrc = TRUE;			dashell = FALSE;			b_dot(fname);		}		if (interactive) {			List *s;			if (!dashen && fnlookup("prompt") != NULL) {				static char *arglist[] = { "prompt", NULL };				funcall(arglist);			}			if ((s = varlookup("prompt")) != NULL) {				fprint(2, "%s", s->w);				prompt2 = (s->n == NULL ? "" : s->n->w);			}		}		inityy();		if (yyparse() == 1 && execit)			rc_raise(eError);		eof = (last == EOF); /* "last" can be clobbered during a walk() */		if (parsetree != NULL) {			if (execit)				walk(parsetree, TRUE);			else if (dashex && dashen)				fprint(2, "%T\n", parsetree);		}		unexcept(); /* eArena */	}	popinput();	unexcept(); /* eError */	return parsetree;}/* parse a function imported from the environment */extern Node *parseline(char *extdef) {	int i = interactive;	char *in[2];	Node *fun;	in[0] = extdef;	in[1] = NULL;	interactive = FALSE;	pushstring(in, TRUE);	fun = doit(FALSE);	interactive = i;	return fun;}/* write last command out to a file. Check to see if $history has changed, also */static void history() {	List *histlist;	size_t a;	if (!interactive)		return;	if ((histlist = varlookup("history")) == NULL) {		if (histstr != NULL) {			efree(histstr);			close(histfd);			histstr = NULL;		}		return;	}	if (histstr == NULL || !streq(histstr, histlist->w)) { /* open new file */		if (histstr != NULL) {			efree(histstr);			close(histfd);		}		histstr = ecpy(histlist->w);		histfd = rc_open(histstr, rAppend);		if (histfd < 0) {			uerror(histstr);			efree(histstr);			histstr = NULL;			varrm("history", FALSE);		}	}	/*	   Small unix hack: since read() reads only up to a newline	   from a terminal, then presumably this write() will write at	   most only one input line at a time.	*/	for (a = 2; a < chars_in + 2; a++) { /* skip empty lines and comments in history. */		if (inbuf[a] == '#' || inbuf[a] == '\n')			return;		if (inbuf[a] != ' ' && inbuf[a] != '\t')			break;	}	writeall(histfd, inbuf + 2, chars_in);}/* close file descriptors after a fork() */extern void closefds() {	Input *i;	if (histstr != NULL) {			/* Close an open history file */		close(histfd);		histstr = NULL;			/* But prevent re-closing of the same file-descriptor */	}	for (i = istack; i != itop; --i)	/* close open scripts */		if (i->t == iFd && i->fd > 2) {			close(i->fd);			i->fd = -1;		}}

⌨️ 快捷键说明

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