1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "cb.h"
5 #include "cbtype.h"
6
7 static void
usage(void)8 usage(void)
9 {
10 fprint(2, "usage: cb [-sj] [-l width]\n");
11 exits("usage");
12 }
13
14 void
main(int argc,char * argv[])15 main(int argc, char *argv[])
16 {
17 Biobuf stdin, stdout;
18
19 ARGBEGIN{
20 case 'j':
21 join = 1;
22 break;
23 case 'l':
24 maxleng = atoi(EARGF(usage()));
25 maxtabs = maxleng/TABLENG - 2;
26 maxleng -= (maxleng + 5)/10;
27 break;
28 case 's':
29 strict = 1;
30 break;
31 default:
32 usage();
33 }ARGEND
34
35 Binit(&stdout, 1, OWRITE);
36 output = &stdout;
37 if (argc <= 0){
38 Binit(&stdin, 0, OREAD);
39 input = &stdin;
40 work();
41 Bterm(input);
42 } else {
43 while (argc-- > 0){
44 if ((input = Bopen(*argv, OREAD)) == 0)
45 sysfatal("can't open input file %s: %r", *argv);
46 work();
47 Bterm(input);
48 argv++;
49 }
50 }
51 exits(0);
52 }
53 void
work(void)54 work(void)
55 {
56 int c, cc;
57 struct keyw *lptr;
58 char *pt;
59 int ct;
60
61 while ((c = getch()) != Beof){
62 switch (c){
63 case '{':
64 if ((lptr = lookup(lastlook,p)) != 0){
65 if (lptr->type == ELSE)gotelse();
66 else if(lptr->type == DO)gotdo();
67 else if(lptr->type == STRUCT)structlev++;
68 }
69 if(++clev >= &ind[CLEVEL-1]){
70 fprint(2,"too many levels of curly brackets\n");
71 clev = &ind[CLEVEL-1];
72 }
73 clev->pdepth = 0;
74 clev->tabs = (clev-1)->tabs;
75 clearif(clev);
76 if(strict && clev->tabs > 0)
77 putspace(' ',NO);
78 putch(c,NO);
79 getnl();
80 if(keyflag == DATADEF){
81 OUT;
82 }
83 else {
84 OUTK;
85 }
86 clev->tabs++;
87 pt = getnext(0); /* to handle initialized structures */
88 if(*pt == '{'){ /* hide one level of {} */
89 while((c=getch()) != '{')
90 if(c == Beof)error("{");
91 putch(c,NO);
92 if(strict){
93 putch(' ',NO);
94 eatspace();
95 }
96 keyflag = SINIT;
97 }
98 continue;
99 case '}':
100 pt = getnext(0); /* to handle initialized structures */
101 if(*pt == ','){
102 if(strict){
103 putspace(' ',NO);
104 eatspace();
105 }
106 putch(c,NO);
107 putch(*pt,NO);
108 *pt = '\0';
109 ct = getnl();
110 pt = getnext(0);
111 if(*pt == '{'){
112 OUT;
113 while((cc = getch()) != '{')
114 if(cc == Beof)error("}");
115 putch(cc,NO);
116 if(strict){
117 putch(' ',NO);
118 eatspace();
119 }
120 getnext(0);
121 continue;
122 }
123 else if(strict || ct){
124 OUT;
125 }
126 continue;
127 }
128 else if(keyflag == SINIT && *pt == '}'){
129 if(strict)
130 putspace(' ',NO);
131 putch(c,NO);
132 getnl();
133 OUT;
134 keyflag = DATADEF;
135 *pt = '\0';
136 pt = getnext(0);
137 }
138 outs(clev->tabs);
139 if(--clev < ind)clev = ind;
140 ptabs(clev->tabs);
141 putch(c,NO);
142 lbegin = 0;
143 lptr=lookup(pt,lastplace+1);
144 c = *pt;
145 if(*pt == ';' || *pt == ','){
146 putch(*pt,NO);
147 *pt = '\0';
148 lastplace=pt;
149 }
150 ct = getnl();
151 if((dolevel && clev->tabs <= dotabs[dolevel]) || (structlev )
152 || (lptr != 0 &&lptr->type == ELSE&& clev->pdepth == 0)){
153 if(c == ';'){
154 OUTK;
155 }
156 else if(strict || (lptr != 0 && lptr->type == ELSE && ct == 0)){
157 putspace(' ',NO);
158 eatspace();
159 }
160 else if(lptr != 0 && lptr->type == ELSE){
161 OUTK;
162 }
163 if(structlev){
164 structlev--;
165 keyflag = DATADEF;
166 }
167 }
168 else {
169 OUTK;
170 if(strict && clev->tabs == 0){
171 if((c=getch()) != '\n'){
172 Bputc(output, '\n');
173 Bputc(output, '\n');
174 unget(c);
175 }
176 else {
177 lineno++;
178 Bputc(output, '\n');
179 if((c=getch()) != '\n')unget(c);
180 else lineno++;
181 Bputc(output, '\n');
182 }
183 }
184 }
185 if(lptr != 0 && lptr->type == ELSE && clev->pdepth != 0){
186 UNBUMP;
187 }
188 if(lptr == 0 || lptr->type != ELSE){
189 clev->iflev = 0;
190 if(dolevel && docurly[dolevel] == NO && clev->tabs == dotabs[dolevel]+1)
191 clev->tabs--;
192 else if(clev->pdepth != 0){
193 UNBUMP;
194 }
195 }
196 continue;
197 case '(':
198 paren++;
199 if ((lptr = lookup(lastlook,p)) != 0){
200 if(!(lptr->type == TYPE || lptr->type == STRUCT))keyflag=KEYWORD;
201 if (strict){
202 putspace(lptr->punc,NO);
203 opflag = 1;
204 }
205 putch(c,NO);
206 if (lptr->type == IF)gotif();
207 }
208 else {
209 putch(c,NO);
210 lastlook = p;
211 opflag = 1;
212 }
213 continue;
214 case ')':
215 if(--paren < 0)paren = 0;
216 putch(c,NO);
217 if((lptr = lookup(lastlook,p)) != 0){
218 if(lptr->type == TYPE || lptr->type == STRUCT)
219 opflag = 1;
220 }
221 else if(keyflag == DATADEF)opflag = 1;
222 else opflag = 0;
223 outs(clev->tabs);
224 pt = getnext(1);
225 if ((ct = getnl()) == 1 && !strict){
226 if(dolevel && clev->tabs <= dotabs[dolevel])
227 resetdo();
228 if(clev->tabs > 0 && (paren != 0 || keyflag == 0)){
229 if(join){
230 eatspace();
231 putch(' ',YES);
232 continue;
233 } else {
234 OUT;
235 split = 1;
236 continue;
237 }
238 }
239 else if(clev->tabs > 0 && *pt != '{'){
240 BUMP;
241 }
242 OUTK;
243 }
244 else if(strict){
245 if(clev->tabs == 0){
246 if(*pt != ';' && *pt != ',' && *pt != '(' && *pt != '['){
247 OUTK;
248 }
249 }
250 else {
251 if(keyflag == KEYWORD && paren == 0){
252 if(dolevel && clev->tabs <= dotabs[dolevel]){
253 resetdo();
254 eatspace();
255 continue;
256 }
257 if(*pt != '{'){
258 BUMP;
259 OUTK;
260 }
261 else {
262 *pt='\0';
263 eatspace();
264 unget('{');
265 }
266 }
267 else if(ct){
268 if(paren){
269 if(join){
270 eatspace();
271 } else {
272 split = 1;
273 OUT;
274 }
275 }
276 else {
277 OUTK;
278 }
279 }
280 }
281 }
282 else if(dolevel && clev->tabs <= dotabs[dolevel])
283 resetdo();
284 continue;
285 case ' ':
286 case '\t':
287 if ((lptr = lookup(lastlook,p)) != 0){
288 if(!(lptr->type==TYPE||lptr->type==STRUCT))
289 keyflag = KEYWORD;
290 else if(paren == 0)keyflag = DATADEF;
291 if(strict){
292 if(lptr->type != ELSE){
293 if(lptr->type == TYPE){
294 if(paren != 0)putch(' ',YES);
295 }
296 else
297 putch(lptr->punc,NO);
298 eatspace();
299 }
300 }
301 else putch(c,YES);
302 switch(lptr->type){
303 case CASE:
304 outs(clev->tabs-1);
305 continue;
306 case ELSE:
307 pt = getnext(1);
308 eatspace();
309 if((cc = getch()) == '\n' && !strict){
310 unget(cc);
311 }
312 else {
313 unget(cc);
314 if(checkif(pt))continue;
315 }
316 gotelse();
317 if(strict) unget(c);
318 if(getnl() == 1 && !strict){
319 OUTK;
320 if(*pt != '{'){
321 BUMP;
322 }
323 }
324 else if(strict){
325 if(*pt != '{'){
326 OUTK;
327 BUMP;
328 }
329 }
330 continue;
331 case IF:
332 gotif();
333 continue;
334 case DO:
335 gotdo();
336 pt = getnext(1);
337 if(*pt != '{'){
338 eatallsp();
339 OUTK;
340 docurly[dolevel] = NO;
341 dopdepth[dolevel] = clev->pdepth;
342 clev->pdepth = 0;
343 clev->tabs++;
344 }
345 continue;
346 case TYPE:
347 if(paren)continue;
348 if(!strict)continue;
349 gottype(lptr);
350 continue;
351 case STRUCT:
352 gotstruct();
353 continue;
354 }
355 }
356 else if (lbegin == 0 || p > string)
357 if(strict)
358 putch(c,NO);
359 else putch(c,YES);
360 continue;
361 case ';':
362 putch(c,NO);
363 if(paren != 0){
364 if(strict){
365 putch(' ',YES);
366 eatspace();
367 }
368 opflag = 1;
369 continue;
370 }
371 outs(clev->tabs);
372 pt = getnext(0);
373 lptr=lookup(pt,lastplace+1);
374 if(lptr == 0 || lptr->type != ELSE){
375 clev->iflev = 0;
376 if(clev->pdepth != 0){
377 UNBUMP;
378 }
379 if(dolevel && docurly[dolevel] == NO && clev->tabs <= dotabs[dolevel]+1)
380 clev->tabs--;
381 /*
382 else if(clev->pdepth != 0){
383 UNBUMP;
384 }
385 */
386 }
387 getnl();
388 OUTK;
389 continue;
390 case '\n':
391 if ((lptr = lookup(lastlook,p)) != 0){
392 pt = getnext(1);
393 if (lptr->type == ELSE){
394 if(strict)
395 if(checkif(pt))continue;
396 gotelse();
397 OUTK;
398 if(*pt != '{'){
399 BUMP;
400 }
401 }
402 else if(lptr->type == DO){
403 OUTK;
404 gotdo();
405 if(*pt != '{'){
406 docurly[dolevel] = NO;
407 dopdepth[dolevel] = clev->pdepth;
408 clev->pdepth = 0;
409 clev->tabs++;
410 }
411 }
412 else {
413 OUTK;
414 if(lptr->type == STRUCT)gotstruct();
415 }
416 }
417 else if(p == string)Bputc(output, '\n');
418 else {
419 if(clev->tabs > 0 &&(paren != 0 || keyflag == 0)){
420 if(join){
421 putch(' ',YES);
422 eatspace();
423 continue;
424 } else {
425 OUT;
426 split = 1;
427 continue;
428 }
429 }
430 else if(keyflag == KEYWORD){
431 OUTK;
432 continue;
433 }
434 OUT;
435 }
436 continue;
437 case '"':
438 case '\'':
439 putch(c,NO);
440 while ((cc = getch()) != c){
441 if(cc == Beof)
442 error("\" or '");
443 putch(cc,NO);
444 if (cc == '\\'){
445 putch(getch(),NO);
446 }
447 if (cc == '\n'){
448 outs(clev->tabs);
449 lbegin = 1;
450 count = 0;
451 }
452 }
453 putch(cc,NO);
454 opflag=0;
455 if (getnl() == 1){
456 unget('\n');
457 }
458 continue;
459 case '\\':
460 putch(c,NO);
461 putch(getch(),NO);
462 continue;
463 case '?':
464 question = 1;
465 gotop(c);
466 continue;
467 case ':':
468 if ((cc = getch()) == ':') {
469 putch(c,NO);
470 putch(cc,NO);
471 continue;
472 }
473 unget(cc);
474 if (question == 1){
475 question = 0;
476 gotop(c);
477 continue;
478 }
479 putch(c,NO);
480 if(structlev)continue;
481 if ((lptr = lookup(lastlook,p)) != 0){
482 if (lptr->type == CASE)outs(clev->tabs - 1);
483 }
484 else {
485 lbegin = 0;
486 outs(clev->tabs);
487 }
488 getnl();
489 OUTK;
490 continue;
491 case '/':
492 if ((cc = getch()) == '/') {
493 putch(c,NO);
494 putch(cc,NO);
495 cpp_comment(YES);
496 OUT;
497 lastlook = 0;
498 continue;
499 }
500 else if (cc != '*') {
501 unget(cc);
502 gotop(c);
503 continue;
504 }
505 putch(c,NO);
506 putch(cc,NO);
507 cc = comment(YES);
508 if(getnl() == 1){
509 if(cc == 0){
510 OUT;
511 }
512 else {
513 outs(0);
514 Bputc(output, '\n');
515 lbegin = 1;
516 count = 0;
517 }
518 lastlook = 0;
519 }
520 continue;
521 case '[':
522 putch(c,NO);
523 ct = 0;
524 while((c = getch()) != ']' || ct > 0){
525 if(c == Beof)error("]");
526 putch(c,NO);
527 if(c == '[')ct++;
528 if(c == ']')ct--;
529 }
530 putch(c,NO);
531 continue;
532 case '#':
533 putch(c,NO);
534 while ((cc = getch()) != '\n'){
535 if(cc == Beof)error("newline");
536 if (cc == '\\'){
537 putch(cc,NO);
538 cc = getch();
539 }
540 putch(cc,NO);
541 }
542 putch(cc,NO);
543 lbegin = 0;
544 outs(clev->tabs);
545 lbegin = 1;
546 count = 0;
547 continue;
548 default:
549 if (c == ','){
550 opflag = 1;
551 putch(c,YES);
552 if (strict){
553 if ((cc = getch()) != ' ')unget(cc);
554 if(cc != '\n')putch(' ',YES);
555 }
556 }
557 else if(isop(c))gotop(c);
558 else {
559 if(isalnum(c) && lastlook == 0)lastlook = p;
560 if(isdigit(c)){
561 putch(c,NO);
562 while(isdigit(c=Bgetc(input))||c == '.')putch(c,NO);
563 if(c == 'e'){
564 putch(c,NO);
565 c = Bgetc(input);
566 putch(c, NO);
567 while(isdigit(c=Bgetc(input)))putch(c,NO);
568 }
569 Bungetc(input);
570 }
571 else putch(c,NO);
572 if(keyflag != DATADEF)opflag = 0;
573 }
574 }
575 }
576 }
577 void
gotif(void)578 gotif(void){
579 outs(clev->tabs);
580 if(++clev->iflev >= IFLEVEL-1){
581 fprint(2,"too many levels of if %d\n",clev->iflev );
582 clev->iflev = IFLEVEL-1;
583 }
584 clev->ifc[clev->iflev] = clev->tabs;
585 clev->spdepth[clev->iflev] = clev->pdepth;
586 }
587 void
gotelse(void)588 gotelse(void){
589 clev->tabs = clev->ifc[clev->iflev];
590 clev->pdepth = clev->spdepth[clev->iflev];
591 if(--(clev->iflev) < 0)clev->iflev = 0;
592 }
593 int
checkif(char * pt)594 checkif(char *pt)
595 {
596 struct keyw *lptr;
597 int cc;
598 if((lptr=lookup(pt,lastplace+1))!= 0){
599 if(lptr->type == IF){
600 if(strict)putch(' ',YES);
601 copy(lptr->name);
602 *pt='\0';
603 lastplace = pt;
604 if(strict){
605 putch(lptr->punc,NO);
606 eatallsp();
607 }
608 clev->tabs = clev->ifc[clev->iflev];
609 clev->pdepth = clev->spdepth[clev->iflev];
610 keyflag = KEYWORD;
611 return(1);
612 }
613 }
614 return(0);
615 }
616 void
gotdo(void)617 gotdo(void){
618 if(++dolevel >= DOLEVEL-1){
619 fprint(2,"too many levels of do %d\n",dolevel);
620 dolevel = DOLEVEL-1;
621 }
622 dotabs[dolevel] = clev->tabs;
623 docurly[dolevel] = YES;
624 }
625 void
resetdo(void)626 resetdo(void){
627 if(docurly[dolevel] == NO)
628 clev->pdepth = dopdepth[dolevel];
629 if(--dolevel < 0)dolevel = 0;
630 }
631 void
gottype(struct keyw * lptr)632 gottype(struct keyw *lptr)
633 {
634 char *pt;
635 struct keyw *tlptr;
636 int c;
637 while(1){
638 pt = getnext(1);
639 if((tlptr=lookup(pt,lastplace+1))!=0){
640 putch(' ',YES);
641 copy(tlptr->name);
642 *pt='\0';
643 lastplace = pt;
644 if(tlptr->type == STRUCT){
645 putch(tlptr->punc,YES);
646 gotstruct();
647 break;
648 }
649 lptr=tlptr;
650 continue;
651 }
652 else{
653 putch(lptr->punc,NO);
654 while((c=getch())== ' ' || c == '\t');
655 unget(c);
656 break;
657 }
658 }
659 }
660 void
gotstruct(void)661 gotstruct(void){
662 int c;
663 int cc;
664 char *pt;
665 while((c=getch()) == ' ' || c == '\t')
666 if(!strict)putch(c,NO);
667 if(c == '{'){
668 structlev++;
669 unget(c);
670 return;
671 }
672 if(isalpha(c)){
673 putch(c,NO);
674 while(isalnum(c=getch()))putch(c,NO);
675 }
676 unget(c);
677 pt = getnext(1);
678 if(*pt == '{')structlev++;
679 if(strict){
680 eatallsp();
681 putch(' ',NO);
682 }
683 }
684 void
gotop(int c)685 gotop(int c)
686 {
687 char optmp[OPLENGTH];
688 char *op_ptr;
689 struct op *s_op;
690 char *a, *b;
691 op_ptr = optmp;
692 *op_ptr++ = c;
693 while (isop(( *op_ptr = getch())))op_ptr++;
694 if(!strict)unget(*op_ptr);
695 else if (*op_ptr != ' ')unget( *op_ptr);
696 *op_ptr = '\0';
697 s_op = op;
698 b = optmp;
699 while ((a = s_op->name) != 0){
700 op_ptr = b;
701 while ((*op_ptr == *a) && (*op_ptr != '\0')){
702 a++;
703 op_ptr++;
704 }
705 if (*a == '\0'){
706 keep(s_op);
707 opflag = s_op->setop;
708 if (*op_ptr != '\0'){
709 b = op_ptr;
710 s_op = op;
711 continue;
712 }
713 else break;
714 }
715 else s_op++;
716 }
717 }
718 void
keep(struct op * o)719 keep(struct op *o)
720 {
721 char *s;
722 int ok;
723 if(o->blanks == NEVER)ok = NO;
724 else ok = YES;
725 if (strict && ((o->blanks & ALWAYS)
726 || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0)))
727 putspace(' ',YES);
728 for(s=o->name; *s != '\0'; s++){
729 if(*(s+1) == '\0')putch(*s,ok);
730 else
731 putch(*s,NO);
732 }
733 if (strict && ((o->blanks & ALWAYS)
734 || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0))) putch(' ',YES);
735 }
736 int
getnl(void)737 getnl(void){
738 int ch;
739 char *savp;
740 int gotcmt;
741 gotcmt = 0;
742 savp = p;
743 while ((ch = getch()) == '\t' || ch == ' ')putch(ch,NO);
744 if (ch == '/'){
745 if ((ch = getch()) == '*'){
746 putch('/',NO);
747 putch('*',NO);
748 comment(NO);
749 ch = getch();
750 gotcmt=1;
751 }
752 else if (ch == '/') {
753 putch('/',NO);
754 putch('/',NO);
755 cpp_comment(NO);
756 ch = getch();
757 gotcmt = 1;
758 }
759 else {
760 if(inswitch)*(++lastplace) = ch;
761 else {
762 inswitch = 1;
763 *lastplace = ch;
764 }
765 unget('/');
766 return(0);
767 }
768 }
769 if(ch == '\n'){
770 if(gotcmt == 0)p=savp;
771 return(1);
772 }
773 unget(ch);
774 return(0);
775 }
776 void
ptabs(int n)777 ptabs(int n){
778 int i;
779 int num;
780 if(n > maxtabs){
781 if(!folded){
782 Bprint(output, "/* code folded from here */\n");
783 folded = 1;
784 }
785 num = n-maxtabs;
786 }
787 else {
788 num = n;
789 if(folded){
790 folded = 0;
791 Bprint(output, "/* unfolding */\n");
792 }
793 }
794 for (i = 0; i < num; i++)Bputc(output, '\t');
795 }
796 void
outs(int n)797 outs(int n){
798 if (p > string){
799 if (lbegin){
800 ptabs(n);
801 lbegin = 0;
802 if (split == 1){
803 split = 0;
804 if (clev->tabs > 0)Bprint(output, "\t");
805 }
806 }
807 *p = '\0';
808 Bprint(output, "%s", string);
809 lastlook = p = string;
810 }
811 else {
812 if (lbegin != 0){
813 lbegin = 0;
814 split = 0;
815 }
816 }
817 }
818 void
putch(char c,int ok)819 putch(char c,int ok)
820 {
821 int cc;
822 if(p < &string[LINE-1]){
823 if(count+TABLENG*clev->tabs >= maxleng && ok && !folded){
824 if(c != ' ')*p++ = c;
825 OUT;
826 split = 1;
827 if((cc=getch()) != '\n')unget(cc);
828 }
829 else {
830 *p++ = c;
831 count++;
832 }
833 }
834 else {
835 outs(clev->tabs);
836 *p++ = c;
837 count = 0;
838 }
839 }
840 struct keyw *
lookup(char * first,char * last)841 lookup(char *first, char *last)
842 {
843 struct keyw *ptr;
844 char *cptr, *ckey, *k;
845
846 if(first == last || first == 0)return(0);
847 cptr = first;
848 while (*cptr == ' ' || *cptr == '\t')cptr++;
849 if(cptr >= last)return(0);
850 ptr = key;
851 while ((ckey = ptr->name) != 0){
852 for (k = cptr; (*ckey == *k && *ckey != '\0'); k++, ckey++);
853 if(*ckey=='\0' && (k==last|| (k<last && !isalnum(*k)))){
854 opflag = 1;
855 lastlook = 0;
856 return(ptr);
857 }
858 ptr++;
859 }
860 return(0);
861 }
862 int
comment(int ok)863 comment(int ok)
864 {
865 int ch;
866 int hitnl;
867
868 hitnl = 0;
869 while ((ch = getch()) != Beof){
870 putch(ch, NO);
871 if (ch == '*'){
872 gotstar:
873 if ((ch = getch()) == '/'){
874 putch(ch,NO);
875 return(hitnl);
876 }
877 putch(ch,NO);
878 if (ch == '*')goto gotstar;
879 }
880 if (ch == '\n'){
881 if(ok && !hitnl){
882 outs(clev->tabs);
883 }
884 else {
885 outs(0);
886 }
887 lbegin = 1;
888 count = 0;
889 hitnl = 1;
890 }
891 }
892 return(hitnl);
893 }
894 int
cpp_comment(int ok)895 cpp_comment(int ok)
896 {
897 int ch;
898 int hitnl;
899
900 hitnl = 0;
901 while ((ch = getch()) != -1) {
902 if (ch == '\n') {
903 if (ok && !hitnl)
904 outs(clev->tabs);
905 else
906 outs(0);
907 lbegin = 1;
908 count = 0;
909 hitnl = 1;
910 break;
911 }
912 putch(ch, NO);
913 }
914 return hitnl;
915 }
916 void
putspace(char ch,int ok)917 putspace(char ch, int ok)
918 {
919 if(p == string)putch(ch,ok);
920 else if (*(p - 1) != ch) putch(ch,ok);
921 }
922 int
getch(void)923 getch(void){
924 char c;
925 if(inswitch){
926 if(next != '\0'){
927 c=next;
928 next = '\0';
929 return(c);
930 }
931 if(tptr <= lastplace){
932 if(*tptr != '\0')return(*tptr++);
933 else if(++tptr <= lastplace)return(*tptr++);
934 }
935 inswitch=0;
936 lastplace = tptr = temp;
937 }
938 return(Bgetc(input));
939 }
940 void
unget(char c)941 unget(char c)
942 {
943 if(inswitch){
944 if(tptr != temp)
945 *(--tptr) = c;
946 else next = c;
947 }
948 else Bungetc(input);
949 }
950 char *
getnext(int must)951 getnext(int must){
952 int c;
953 char *beg;
954 int prect,nlct;
955 prect = nlct = 0;
956 if(tptr > lastplace){
957 tptr = lastplace = temp;
958 err = 0;
959 inswitch = 0;
960 }
961 tp = lastplace;
962 if(inswitch && tptr <= lastplace)
963 if (isalnum(*lastplace)||ispunct(*lastplace)||isop(*lastplace))return(lastplace);
964 space:
965 while(isspace(c=Bgetc(input)))puttmp(c,1);
966 beg = tp;
967 puttmp(c,1);
968 if(c == '/'){
969 if(puttmp(Bgetc(input),1) == '*'){
970 cont:
971 while((c=Bgetc(input)) != '*'){
972 puttmp(c,0);
973 if(must == 0 && c == '\n')
974 if(nlct++ > 2)goto done;
975 }
976 puttmp(c,1);
977 star:
978 if(puttmp((c=Bgetc(input)),1) == '/'){
979 beg = tp;
980 puttmp((c=Bgetc(input)),1);
981 }
982 else if(c == '*')goto star;
983 else goto cont;
984 }
985 else goto done;
986 }
987 if(isspace(c))goto space;
988 if(c == '#' && tp > temp+1 && *(tp-2) == '\n'){
989 if(prect++ > 2)goto done;
990 while(puttmp((c=Bgetc(input)),1) != '\n')
991 if(c == '\\')puttmp(Bgetc(input),1);
992 goto space;
993 }
994 if(isalnum(c)){
995 while(isalnum(c = Bgetc(input)))puttmp(c,1);
996 Bungetc(input);
997 }
998 done:
999 puttmp('\0',1);
1000 lastplace = tp-1;
1001 inswitch = 1;
1002 return(beg);
1003 }
1004 void
copy(char * s)1005 copy(char *s)
1006 {
1007 while(*s != '\0')putch(*s++,NO);
1008 }
1009 void
clearif(struct indent * cl)1010 clearif(struct indent *cl)
1011 {
1012 int i;
1013 for(i=0;i<IFLEVEL-1;i++)cl->ifc[i] = 0;
1014 }
1015 char
puttmp(char c,int keep)1016 puttmp(char c, int keep)
1017 {
1018 if(tp < &temp[TEMP-120])
1019 *tp++ = c;
1020 else {
1021 if(keep){
1022 if(tp >= &temp[TEMP-1]){
1023 fprint(2,"can't look past huge comment - quiting\n");
1024 exits("boom");
1025 }
1026 *tp++ = c;
1027 }
1028 else if(err == 0){
1029 err++;
1030 fprint(2,"truncating long comment\n");
1031 }
1032 }
1033 return(c);
1034 }
1035 void
error(char * s)1036 error(char *s)
1037 {
1038 fprint(2,"saw EOF while looking for %s\n",s);
1039 exits("boom");
1040 }
1041