]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cb/cb.c
fix ref822 again: remove uniqarray(), fix case with many entries in 'n'.
[plan9front.git] / sys / src / cmd / cb / cb.c
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 }