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