tinput.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tinput.c (3140B)
       ---
            1 /*
            2  * Read input files.
            3  */
            4 #include "a.h"
            5 
            6 typedef struct Istack Istack;
            7 struct Istack
            8 {
            9         Rune unget[3];
           10         int nunget;
           11         Biobuf *b;
           12         Rune *p;
           13         Rune *ep;
           14         Rune *s;
           15         int lineno;
           16         Rune *name;
           17         Istack *next;
           18         void (*fn)(void);
           19 };
           20 
           21 Istack *istack;
           22 Istack *ibottom;
           23 
           24 static void
           25 setname(void)
           26 {
           27         Rune *r, *p;
           28 
           29         if(istack == nil || istack->name == nil)
           30                 return;
           31         _nr(L(".F"), istack->name);
           32         r = erunestrdup(istack->name);
           33         p = runestrchr(r, '.');
           34         if(p)
           35                 *p = 0;
           36         _nr(L(".B"), r);
           37         free(r);
           38 }
           39 
           40 static void
           41 ipush(Istack *is)
           42 {
           43         if(istack == nil)
           44                 ibottom = is;
           45         else
           46                 is->next = istack;
           47         istack = is;
           48         setname();
           49 }
           50 
           51 static void
           52 iqueue(Istack *is)
           53 {
           54         if(ibottom == nil){
           55                 istack = is;
           56                 setname();
           57         }else
           58                 ibottom->next = is;
           59         ibottom = is;
           60 }
           61 
           62 int
           63 _inputfile(Rune *s, void (*push)(Istack*))
           64 {
           65         Istack *is;
           66         Biobuf *b;
           67         char *t;
           68 
           69         t = esmprint("%S", s);
           70         if((b = Bopen(t, OREAD)) == nil){
           71                 free(t);
           72                 fprint(2, "%s: open %S: %r\n", argv0, s);
           73                 return -1;
           74         }
           75         free(t);
           76         is = emalloc(sizeof *is);
           77         is->b = b;
           78         is->name = erunestrdup(s);
           79         is->lineno = 1;
           80         push(is);
           81         return 0;
           82 }
           83 
           84 int
           85 pushinputfile(Rune *s)
           86 {
           87         return _inputfile(s, ipush);
           88 }
           89 
           90 int
           91 queueinputfile(Rune *s)
           92 {
           93         return _inputfile(s, iqueue);
           94 }
           95 
           96 int
           97 _inputstdin(void (*push)(Istack*))
           98 {
           99         Biobuf *b;
          100         Istack *is;
          101 
          102         if((b = Bopen("/dev/null", OREAD)) == nil){
          103                 fprint(2, "%s: open /dev/null: %r\n", argv0);
          104                 return -1;
          105         }
          106         dup(0, b->fid);
          107         is = emalloc(sizeof *is);
          108         is->b = b;
          109         is->name = erunestrdup(L("stdin"));
          110         is->lineno = 1;
          111         push(is);
          112         return 0;
          113 }
          114 
          115 int
          116 pushstdin(void)
          117 {
          118         return _inputstdin(ipush);
          119 }
          120 
          121 int
          122 queuestdin(void)
          123 {
          124         return _inputstdin(iqueue);
          125 }
          126 
          127 void
          128 _inputstring(Rune *s, void (*push)(Istack*))
          129 {
          130         Istack *is;
          131 
          132         is = emalloc(sizeof *is);
          133         is->s = erunestrdup(s);
          134         is->p = is->s;
          135         is->ep = is->p+runestrlen(is->p);
          136         push(is);
          137 }
          138 
          139 void
          140 pushinputstring(Rune *s)
          141 {
          142         _inputstring(s, ipush);
          143 }
          144 
          145 
          146 void
          147 inputnotify(void (*fn)(void))
          148 {
          149         if(istack)
          150                 istack->fn = fn;
          151 }
          152 
          153 int
          154 popinput(void)
          155 {
          156         Istack *is;
          157 
          158         is = istack;
          159         if(is == nil)
          160                 return 0;
          161 
          162         istack = istack->next;
          163         if(is->b)
          164                 Bterm(is->b);
          165         free(is->s);
          166         free(is->name);
          167         if(is->fn)
          168                 is->fn();
          169         free(is);
          170         setname();
          171         return 1;
          172 }
          173 
          174 int
          175 getrune(void)
          176 {
          177         Rune r;
          178         int c;
          179 
          180 top:
          181         if(istack == nil)
          182                 return -1;
          183         if(istack->nunget)
          184                 return istack->unget[--istack->nunget];
          185         else if(istack->p){
          186                 if(istack->p >= istack->ep){
          187                         popinput();
          188                         goto top;
          189                 }
          190                 r = *istack->p++;
          191         }else if(istack->b){
          192                 if((c = Bgetrune(istack->b)) < 0){
          193                         popinput();
          194                         goto top;
          195                 }
          196                 r = c;
          197         }else{
          198                 r = 0;
          199                 sysfatal("getrune - can't happen");
          200         }
          201         if(r == '\n')
          202                 istack->lineno++;
          203         return r;
          204 }
          205 
          206 void
          207 ungetrune(Rune r)
          208 {
          209         if(istack == nil || istack->nunget >= nelem(istack->unget))
          210                 pushinputstring(L(""));
          211         istack->unget[istack->nunget++] = r;
          212 }
          213 
          214 int
          215 linefmt(Fmt *f)
          216 {
          217         Istack *is;
          218 
          219         for(is=istack; is && !is->b; is=is->next)
          220                 ;
          221         if(is)
          222                 return fmtprint(f, "%S:%d", is->name, is->lineno);
          223         else
          224                 return fmtprint(f, "<no input>");
          225 }
          226 
          227 void
          228 setlinenumber(Rune *s, int n)
          229 {
          230         Istack *is;
          231 
          232         for(is=istack; is && !is->name; is=is->next)
          233                 ;
          234         if(is){
          235                 if(s){
          236                         free(is->name);
          237                         is->name = erunestrdup(s);
          238                 }
          239                 is->lineno = n;
          240         }
          241 }