241 lines · 3.1 KB · C
RawDownload
/* * Read input files. */#include "a.h" typedef struct Istack Istack;struct Istack{	Rune unget[3];	int nunget;	Biobuf *b;	Rune *p;	Rune *ep;	Rune *s;	int lineno;	Rune *name;	Istack *next;	void (*fn)(void);}; Istack *istack;Istack *ibottom; static voidsetname(void){	Rune *r, *p; 	if(istack == nil || istack->name == nil)		return;	_nr(L(".F"), istack->name);	r = erunestrdup(istack->name);	p = runestrchr(r, '.');	if(p)		*p = 0;	_nr(L(".B"), r);	free(r);} static voidipush(Istack *is){	if(istack == nil)		ibottom = is;	else		is->next = istack;	istack = is;	setname();} static voidiqueue(Istack *is){	if(ibottom == nil){		istack = is;		setname();	}else		ibottom->next = is;	ibottom = is;} int_inputfile(Rune *s, void (*push)(Istack*)){	Istack *is;	Biobuf *b;	char *t;		t = esmprint("%S", s);	if((b = Bopen(t, OREAD)) == nil){		free(t);		fprint(2, "%s: open %S: %r\n", argv0, s);		return -1;	}	free(t);	is = emalloc(sizeof *is);	is->b = b;	is->name = erunestrdup(s);	is->lineno = 1;	push(is);	return 0;} intpushinputfile(Rune *s){	return _inputfile(s, ipush);} intqueueinputfile(Rune *s){	return _inputfile(s, iqueue);} int_inputstdin(void (*push)(Istack*)){		Biobuf *b;	Istack *is; 	if((b = Bopen("/dev/null", OREAD)) == nil){		fprint(2, "%s: open /dev/null: %r\n", argv0);		return -1;	}	dup(0, b->fid);	is = emalloc(sizeof *is);	is->b = b;	is->name = erunestrdup(L("stdin"));	is->lineno = 1;	push(is);	return 0;} intpushstdin(void){	return _inputstdin(ipush);} intqueuestdin(void){	return _inputstdin(iqueue);} void_inputstring(Rune *s, void (*push)(Istack*)){	Istack *is;		is = emalloc(sizeof *is);	is->s = erunestrdup(s);	is->p = is->s;	is->ep = is->p+runestrlen(is->p);	push(is);} voidpushinputstring(Rune *s){	_inputstring(s, ipush);}  voidinputnotify(void (*fn)(void)){	if(istack)		istack->fn = fn;} intpopinput(void){	Istack *is; 	is = istack;	if(is == nil)		return 0; 	istack = istack->next;	if(is->b)		Bterm(is->b);	free(is->s);	free(is->name);	if(is->fn)		is->fn();	free(is);	setname();	return 1;} intgetrune(void){	Rune r;	int c;	top:	if(istack == nil)		return -1;	if(istack->nunget)		return istack->unget[--istack->nunget];	else if(istack->p){		if(istack->p >= istack->ep){			popinput();			goto top;		}		r = *istack->p++;	}else if(istack->b){		if((c = Bgetrune(istack->b)) < 0){			popinput();			goto top;		}		r = c;	}else{		r = 0;		sysfatal("getrune - can't happen");	}	if(r == '\n')		istack->lineno++;		return r;} voidungetrune(Rune r){	if(istack == nil || istack->nunget >= nelem(istack->unget))		pushinputstring(L(""));	istack->unget[istack->nunget++] = r;} intlinefmt(Fmt *f){	Istack *is;		for(is=istack; is && !is->b; is=is->next)		;	if(is)		return fmtprint(f, "%S:%d", is->name, is->lineno);	else		return fmtprint(f, "<no input>");} voidsetlinenumber(Rune *s, int n){	Istack *is;		for(is=istack; is && !is->name; is=is->next)		;	if(is){		if(s){			free(is->name);			is->name = erunestrdup(s);		}		is->lineno = n;	}}