123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- /*
- * 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 void
- setname(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 void
- ipush(Istack *is)
- {
- if(istack == nil)
- ibottom = is;
- else
- is->next = istack;
- istack = is;
- setname();
- }
- static void
- iqueue(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;
- }
- int
- pushinputfile(Rune *s)
- {
- return _inputfile(s, ipush);
- }
- int
- queueinputfile(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;
- }
- int
- pushstdin(void)
- {
- return _inputstdin(ipush);
- }
- int
- queuestdin(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);
- }
- void
- pushinputstring(Rune *s)
- {
- _inputstring(s, ipush);
- }
- void
- inputnotify(void (*fn)(void))
- {
- if(istack)
- istack->fn = fn;
- }
- int
- popinput(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;
- }
- int
- getrune(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;
- }
- void
- ungetrune(Rune r)
- {
- if(istack == nil || istack->nunget >= nelem(istack->unget))
- pushinputstring(L(""));
- istack->unget[istack->nunget++] = r;
- }
- int
- linefmt(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>");
- }
- void
- setlinenumber(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;
- }
- }
|