plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

input.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 }