]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/lex/sub1.c
mothra: fix alt display resizing, filter control characters in panel entries, use...
[plan9front.git] / sys / src / cmd / lex / sub1.c
1 # include "ldefs.h"
2 uchar *
3 getl(uchar *p)  /* return next line of input, throw away trailing '\n' */
4         /* returns 0 if eof is had immediately */
5 {
6         int c;
7         uchar *s, *t;
8
9         t = s = p;
10         while(((c = gch()) != 0) && c != '\n')
11                 *t++ = c;
12         *t = 0;
13         if(c == 0 && s == t) return((uchar *)0);
14         prev = '\n';
15         pres = '\n';
16         return(s);
17 }
18
19 void
20 printerr(char *type, char *fmt, va_list argl)
21 {
22         char buf[1024];
23
24         if(!eof)fprint(errorf,"%s:%d  ", yyfile, yyline);
25         fprint(errorf,"(%s) ", type);
26         vseprint(buf, buf+sizeof(buf), fmt, argl);
27         fprint(errorf, "%s\n", buf);
28 }
29
30
31 void
32 error(char *s,...)
33 {
34         va_list argl;
35
36         va_start(argl, s);
37         printerr("Error", s, argl);
38         va_end(argl);
39 # ifdef DEBUG
40         if(debug && sect != ENDSECTION) {
41                 sect1dump();
42                 sect2dump();
43         }
44 # endif
45         if(
46 # ifdef DEBUG
47                 debug ||
48 # endif
49                 report == 1) statistics();
50         exits("error"); /* error return code */
51 }
52
53 void
54 warning(char *s,...)
55 {
56         va_list argl;
57
58         va_start(argl, s);
59         printerr("Warning", s, argl);
60         va_end(argl);
61         Bflush(&fout);
62 }
63
64 void
65 lgate(void)
66 {
67         int fd;
68
69         if (lgatflg) return;
70         lgatflg=1;
71         if(foutopen == 0){
72                 fd = create("lex.yy.c", OWRITE, 0666);
73                 if(fd < 0)
74                         error("Can't open lex.yy.c: %r");
75                 Binit(&fout, fd, OWRITE);
76                 foutopen = 1;
77                 }
78         phead1();
79 }
80
81 void
82 cclinter(int sw)
83 {
84                 /* sw = 1 ==> ccl */
85         int i, j, k;
86         int m;
87         if(!sw){                /* is NCCL */
88                 for(i=1;i<NCH;i++)
89                         symbol[i] ^= 1;                 /* reverse value */
90         }
91         for(i=1;i<NCH;i++)
92                 if(symbol[i]) break;
93         if(i >= NCH) return;
94         i = cindex[i];
95         /* see if ccl is already in our table */
96         j = 0;
97         if(i){
98                 for(j=1;j<NCH;j++){
99                         if((symbol[j] && cindex[j] != i) ||
100                            (!symbol[j] && cindex[j] == i)) break;
101                 }
102         }
103         if(j >= NCH) return;            /* already in */
104         m = 0;
105         k = 0;
106         for(i=1;i<NCH;i++)
107                 if(symbol[i]){
108                         if(!cindex[i]){
109                                 cindex[i] = ccount;
110                                 symbol[i] = 0;
111                                 m = 1;
112                         } else k = 1;
113                 }
114                         /* m == 1 implies last value of ccount has been used */
115         if(m)ccount++;
116         if(k == 0) return;      /* is now in as ccount wholly */
117         /* intersection must be computed */
118         for(i=1;i<NCH;i++){
119                 if(symbol[i]){
120                         m = 0;
121                         j = cindex[i];  /* will be non-zero */
122                         for(k=1;k<NCH;k++){
123                                 if(cindex[k] == j){
124                                         if(symbol[k]) symbol[k] = 0;
125                                         else {
126                                                 cindex[k] = ccount;
127                                                 m = 1;
128                                         }
129                                 }
130                         }
131                         if(m)ccount++;
132                 }
133         }
134 }
135
136 int
137 usescape(int c)
138 {
139         int d;
140         switch(c){
141         case 'n': c = '\n'; break;
142         case 'r': c = '\r'; break;
143         case 't': c = '\t'; break;
144         case 'b': c = '\b'; break;
145         case 'f': c = 014; break;               /* form feed for ascii */
146         case '0': case '1': case '2': case '3':
147         case '4': case '5': case '6': case '7':
148                 c -= '0';
149                 while('0' <= (d=gch()) && d <= '7'){
150                         c = c * 8 + (d-'0');
151                         if(!('0' <= peek && peek <= '7')) break;
152                         }
153                 break;
154         }
155         return(c);
156 }
157
158 int
159 lookup(uchar *s, uchar **t)
160 {
161         int i;
162         i = 0;
163         while(*t){
164                 if(strcmp((char *)s, *(char **)t) == 0)
165                         return(i);
166                 i++;
167                 t++;
168         }
169         return(-1);
170 }
171
172 int
173 cpyact(void)
174 { /* copy C action to the next ; or closing } */
175         int brac, c, mth;
176         int savline, sw;
177         char *savfile;
178
179         brac = 0;
180         sw = TRUE;
181         savline = 0;
182         savfile = "?";
183
184 while(!eof){
185         c = gch();
186 swt:
187         switch( c ){
188
189 case '|':       if(brac == 0 && sw == TRUE){
190                         if(peek == '|')gch();           /* eat up an extra '|' */
191                         return(0);
192                 }
193                 break;
194
195 case ';':
196                 if( brac == 0 ){
197                         Bputc(&fout, c);
198                         Bputc(&fout, '\n');
199                         return(1);
200                 }
201                 break;
202
203 case '{':
204                 brac++;
205                 savline=yyline;
206                 savfile=yyfile;
207                 break;
208
209 case '}':
210                 brac--;
211                 if( brac == 0 ){
212                         Bputc(&fout, c);
213                         Bputc(&fout, '\n');
214                         return(1);
215                 }
216                 break;
217
218 case '/':       /* look for comments */
219                 Bputc(&fout, c);
220                 c = gch();
221                 if( c != '*' ) goto swt;
222
223                 /* it really is a comment */
224
225                 Bputc(&fout, c);
226                 savline=yyline;
227                 savfile=yyfile;
228                 while( c=gch() ){
229                         if( c=='*' ){
230                                 Bputc(&fout, c);
231                                 if( (c=gch()) == '/' ) goto loop;
232                         }
233                         Bputc(&fout, c);
234                 }
235                 yyline=savline;
236                 yyfile=savfile;
237                 error( "EOF inside comment" );
238
239 case '\'':      /* character constant */
240                 mth = '\'';
241                 goto string;
242
243 case '"':       /* character string */
244                 mth = '"';
245
246         string:
247
248                 Bputc(&fout, c);
249                 while( c=gch() ){
250                         if( c=='\\' ){
251                                 Bputc(&fout, c);
252                                 c=gch();
253                         }
254                         else if( c==mth ) goto loop;
255                         Bputc(&fout, c);
256                         if (c == '\n') {
257                                 yyline--;
258                                 error( "Non-terminated string or character constant");
259                         }
260                 }
261                 error( "EOF in string or character constant" );
262
263 case '\0':
264                 yyline = savline;
265                 yyfile = savfile;
266                 error("Action does not terminate");
267 default:
268                 break;          /* usual character */
269                 }
270 loop:
271         if(c != ' ' && c != '\t' && c != '\n') sw = FALSE;
272         Bputc(&fout, c);
273         }
274         error("Premature EOF");
275         return(0);
276 }
277
278 int
279 gch(void){
280         int c;
281         prev = pres;
282         c = pres = peek;
283         peek = pushptr > pushc ? *--pushptr : Bgetc(fin);
284         if(peek == Beof && sargc > 1){
285                 Bterm(fin);
286                 yyfile = sargv[fptr++];
287                 fin = Bopen(yyfile,OREAD);
288                 if(fin == 0)
289                         error("%s - cannot open file: %r",yyfile);
290                 peek = Bgetc(fin);
291                 sargc--;
292                 sargv++;
293         }
294         if(c == Beof) {
295                 eof = TRUE;
296                 Bterm(fin);
297                 fin = 0;
298                 return(0);
299         }
300         if(c == '\n')yyline++;
301         return(c);
302 }
303
304 int
305 mn2(int a, int d, int c)
306 {
307         name[tptr] = a;
308         left[tptr] = d;
309         right[tptr] = c;
310         parent[tptr] = 0;
311         nullstr[tptr] = 0;
312         switch(a){
313         case RSTR:
314                 parent[d] = tptr;
315                 break;
316         case BAR:
317         case RNEWE:
318                 if(nullstr[d] || nullstr[c]) nullstr[tptr] = TRUE;
319                 parent[d] = parent[c] = tptr;
320                 break;
321         case RCAT:
322         case DIV:
323                 if(nullstr[d] && nullstr[c])nullstr[tptr] = TRUE;
324                 parent[d] = parent[c] = tptr;
325                 break;
326         case RSCON:
327                 parent[d] = tptr;
328                 nullstr[tptr] = nullstr[d];
329                 break;
330 # ifdef DEBUG
331         default:
332                 warning("bad switch mn2 %d %d",a,d);
333                 break;
334 # endif
335                 }
336         if(tptr > treesize)
337                 error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
338         return(tptr++);
339 }
340
341 int
342 mnp(int a, void *p)
343 {
344         name[tptr] = a;
345         left[tptr] = 0;
346         parent[tptr] = 0;
347         nullstr[tptr] = 0;
348         ptr[tptr] = p;
349         switch(a){
350         case RCCL:
351         case RNCCL:
352                 if(strlen(p) == 0) nullstr[tptr] = TRUE;
353                 break;
354         default:
355                 error("bad switch mnp %d %P", a, p);
356                 break;
357         }
358         if(tptr > treesize)
359                 error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
360         return(tptr++);
361 }
362
363 int
364 mn1(int a, int d)
365 {
366         name[tptr] = a;
367         left[tptr] = d;
368         parent[tptr] = 0;
369         nullstr[tptr] = 0;
370         switch(a){
371         case STAR:
372         case QUEST:
373                 nullstr[tptr] = TRUE;
374                 parent[d] = tptr;
375                 break;
376         case PLUS:
377         case CARAT:
378                 nullstr[tptr] = nullstr[d];
379                 parent[d] = tptr;
380                 break;
381         case S2FINAL:
382                 nullstr[tptr] = TRUE;
383                 break;
384 # ifdef DEBUG
385         case FINAL:
386         case S1FINAL:
387                 break;
388         default:
389                 warning("bad switch mn1 %d %d",a,d);
390                 break;
391 # endif
392         }
393         if(tptr > treesize)
394                 error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
395         return(tptr++);
396 }
397
398 int
399 mn0(int a)
400 {
401         name[tptr] = a;
402         parent[tptr] = 0;
403         nullstr[tptr] = 0;
404         if(a >= NCH) switch(a){
405         case RNULLS: nullstr[tptr] = TRUE; break;
406 # ifdef DEBUG
407         default:
408                 warning("bad switch mn0 %d",a);
409                 break;
410 # endif
411         }
412         if(tptr > treesize)
413                 error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
414         return(tptr++);
415 }
416
417 void
418 munputc(int p)
419 {
420         *pushptr++ = peek;              /* watch out for this */
421         peek = p;
422         if(pushptr >= pushc+TOKENSIZE)
423                 error("Too many characters pushed");
424 }
425
426 void
427 munputs(uchar *p)
428 {
429         int i,j;
430         *pushptr++ = peek;
431         peek = p[0];
432         i = strlen((char*)p);
433         for(j = i-1; j>=1; j--)
434                 *pushptr++ = p[j];
435         if(pushptr >= pushc+TOKENSIZE)
436                 error("Too many characters pushed");
437 }
438
439 int
440 dupl(int n)
441 {
442         /* duplicate the subtree whose root is n, return ptr to it */
443         int i;
444
445         i = name[n];
446         if(i < NCH) return(mn0(i));
447         switch(i){
448         case RNULLS:
449                 return(mn0(i));
450         case RCCL: case RNCCL:
451                 return(mnp(i,ptr[n]));
452         case FINAL: case S1FINAL: case S2FINAL:
453                 return(mn1(i,left[n]));
454         case STAR: case QUEST: case PLUS: case CARAT:
455                 return(mn1(i,dupl(left[n])));
456         case RSTR: case RSCON:
457                 return(mn2(i,dupl(left[n]),right[n]));
458         case BAR: case RNEWE: case RCAT: case DIV:
459                 return(mn2(i,dupl(left[n]),dupl(right[n])));
460 # ifdef DEBUG
461         default:
462                 warning("bad switch dupl %d",n);
463 # endif
464         }
465         return(0);
466 }
467
468 # ifdef DEBUG
469 void
470 allprint(int c)
471 {
472         if(c < 0)
473                 c += 256;       /* signed char */
474         switch(c){
475                 case 014:
476                         print("\\f");
477                         charc++;
478                         break;
479                 case '\n':
480                         print("\\n");
481                         charc++;
482                         break;
483                 case '\t':
484                         print("\\t");
485                         charc++;
486                         break;
487                 case '\b':
488                         print("\\b");
489                         charc++;
490                         break;
491                 case ' ':
492                         print("\\\bb");
493                         break;
494                 default:
495                         if(!isprint(c)){
496                                 print("\\%-3o",c);
497                                 charc += 3;
498                         } else 
499                                 print("%c", c);
500                         break;
501         }
502         charc++;
503 }
504
505 void
506 strpt(uchar *s)
507 {
508         charc = 0;
509         while(*s){
510                 allprint(*s++);
511                 if(charc > LINESIZE){
512                         charc = 0;
513                         print("\n\t");
514                 }
515         }
516 }
517
518 void
519 sect1dump(void)
520 {
521         int i;
522
523         print("Sect 1:\n");
524         if(def[0]){
525                 print("str      trans\n");
526                 i = -1;
527                 while(def[++i])
528                         print("%s\t%s\n",def[i],subs[i]);
529         }
530         if(sname[0]){
531                 print("start names\n");
532                 i = -1;
533                 while(sname[++i])
534                         print("%s\n",sname[i]);
535         }
536 }
537
538 void
539 sect2dump(void)
540 {
541         print("Sect 2:\n");
542         treedump();
543 }
544
545 void
546 treedump(void)
547 {
548         int t;
549         uchar *p;
550         print("treedump %d nodes:\n",tptr);
551         for(t=0;t<tptr;t++){
552                 print("%4d ",t);
553                 parent[t] ? print("p=%4d",parent[t]) : print("      ");
554                 print("  ");
555                 if(name[t] < NCH)
556                                 allprint(name[t]);
557                 else switch(name[t]){
558                         case RSTR:
559                                 print("%d ",left[t]);
560                                 allprint(right[t]);
561                                 break;
562                         case RCCL:
563                                 print("ccl ");
564                                 allprint(ptr[t]);
565                                 break;
566                         case RNCCL:
567                                 print("nccl ");
568                                 allprint(ptr[t]);
569                                 break;
570                         case DIV:
571                                 print("/ %d %d",left[t],right[t]);
572                                 break;
573                         case BAR:
574                                 print("| %d %d",left[t],right[t]);
575                                 break;
576                         case RCAT:
577                                 print("cat %d %d",left[t],right[t]);
578                                 break;
579                         case PLUS:
580                                 print("+ %d",left[t]);
581                                 break;
582                         case STAR:
583                                 print("* %d",left[t]);
584                                 break;
585                         case CARAT:
586                                 print("^ %d",left[t]);
587                                 break;
588                         case QUEST:
589                                 print("? %d",left[t]);
590                                 break;
591                         case RNULLS:
592                                 print("nullstring");
593                                 break;
594                         case FINAL:
595                                 print("final %d",left[t]);
596                                 break;
597                         case S1FINAL:
598                                 print("s1final %d",left[t]);    
599                                 break;
600                         case S2FINAL:
601                                 print("s2final %d",left[t]);
602                                 break;
603                         case RNEWE:
604                                 print("new %d %d",left[t],right[t]);
605                                 break;
606                         case RSCON:
607                                 p = (uchar *)right[t];
608                                 print("start %s",sname[*p++-1]);
609                                 while(*p)
610                                         print(", %s",sname[*p++-1]);
611                                 print(" %d",left[t]);
612                                 break;
613                         default:
614                                 print("unknown %d %d %d",name[t],left[t],right[t]);
615                                 break;
616                 }
617                 if(nullstr[t])print("\t(null poss.)");
618                 print("\n");
619         }
620 }
621 # endif