xref: /plan9/sys/src/cmd/cb/cb.c (revision ef7141bf6fd20bbc1132dfd69c9dfe3c339b3089)
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