plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

cb.c (18472B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <bio.h>
      4 #include "cb.h"
      5 #include "cbtype.h"
      6 
      7 void
      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
     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
    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
    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
    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
    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
    621 resetdo(void){
    622 	if(docurly[dolevel] == NO)
    623 		clev->pdepth = dopdepth[dolevel];
    624 	if(--dolevel < 0)dolevel = 0;
    625 }
    626 void
    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
    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
    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
    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
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
    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 *
    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
   1000 copy(char *s)
   1001 {
   1002 	while(*s != '\0')putch(*s++,NO);
   1003 }
   1004 void
   1005 clearif(struct indent *cl)
   1006 {
   1007 	int i;
   1008 	for(i=0;i<IFLEVEL-1;i++)cl->ifc[i] = 0;
   1009 }
   1010 char
   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
   1031 error(char *s)
   1032 {
   1033 	fprint(2,"saw EOF while looking for %s\n",s);
   1034 	exits("boom");
   1035 }