Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include "cb.h"
5
#include "cbtype.h"
6
 
7
static void
8
usage(void)
9
{
10
	fprint(2, "usage: cb [-sj] [-l width]\n");
11
	exits("usage");
12
}
13
 
14
void
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
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
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
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
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
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
626
resetdo(void){
627
	if(docurly[dolevel] == NO)
628
		clev->pdepth = dopdepth[dolevel];
629
	if(--dolevel < 0)dolevel = 0;
630
}
631
void
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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 *
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
1005
copy(char *s)
1006
{
1007
	while(*s != '\0')putch(*s++,NO);
1008
}
1009
void
1010
clearif(struct indent *cl)
1011
{
1012
	int i;
1013
	for(i=0;i<IFLEVEL-1;i++)cl->ifc[i] = 0;
1014
}
1015
char 
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
1036
error(char *s)
1037
{
1038
	fprint(2,"saw EOF while looking for %s\n",s);
1039
	exits("boom");
1040
}