]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cb/cb.c
9bootfat: rename open() to fileinit and make it static as its really a internal funct...
[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 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 {
57         int c, cc;
58         struct keyw *lptr;
59         char *pt;
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 ((cc = getch()) == ':') {
470                                 putch(c,NO);
471                                 putch(cc,NO);
472                                 continue;
473                         }
474                         unget(cc);
475                         if (question == 1){
476                                 question = 0;
477                                 gotop(c);
478                                 continue;
479                         }
480                         putch(c,NO);
481                         if(structlev)continue;
482                         if ((lptr = lookup(lastlook,p)) != 0){
483                                 if (lptr->type == CASE)outs(clev->tabs - 1);
484                         }
485                         else {
486                                 lbegin = 0;
487                                 outs(clev->tabs);
488                         }
489                         getnl();
490                         OUTK;
491                         continue;
492                 case '/':
493                         if ((cc = getch()) == '/') {
494                                 putch(c,NO);
495                                 putch(cc,NO);
496                                 cpp_comment(YES);
497                                 OUT;
498                                 lastlook = 0;
499                                 continue;
500                         }
501                         else if (cc != '*') {
502                                 unget(cc);
503                                 gotop(c);
504                                 continue;
505                         }
506                         putch(c,NO);
507                         putch(cc,NO);
508                         cc = comment(YES);
509                         if(getnl() == 1){
510                                 if(cc == 0){
511                                         OUT;
512                                 }
513                                 else {
514                                         outs(0);
515                                         Bputc(output, '\n');
516                                         lbegin = 1;
517                                         count = 0;
518                                 }
519                                 lastlook = 0;
520                         }
521                         continue;
522                 case '[':
523                         putch(c,NO);
524                         ct = 0;
525                         while((c = getch()) != ']' || ct > 0){
526                                 if(c == Beof)error("]");
527                                 putch(c,NO);
528                                 if(c == '[')ct++;
529                                 if(c == ']')ct--;
530                         }
531                         putch(c,NO);
532                         continue;
533                 case '#':
534                         putch(c,NO);
535                         while ((cc = getch()) != '\n'){
536                                 if(cc == Beof)error("newline");
537                                 if (cc == '\\'){
538                                         putch(cc,NO);
539                                         cc = getch();
540                                 }
541                                 putch(cc,NO);
542                         }
543                         putch(cc,NO);
544                         lbegin = 0;
545                         outs(clev->tabs);
546                         lbegin = 1;
547                         count = 0;
548                         continue;
549                 default:
550                         if (c == ','){
551                                 opflag = 1;
552                                 putch(c,YES);
553                                 if (strict){
554                                         if ((cc = getch()) != ' ')unget(cc);
555                                         if(cc != '\n')putch(' ',YES);
556                                 }
557                         }
558                         else if(isop(c))gotop(c);
559                         else {
560                                 if(isalnum(c) && lastlook == 0)lastlook = p;
561                                 if(isdigit(c)){
562                                         putch(c,NO);
563                                         while(isdigit(c=Bgetc(input))||c == '.')putch(c,NO);
564                                         if(c == 'e'){
565                                                 putch(c,NO);
566                                                 c = Bgetc(input);
567                                                 putch(c, NO);
568                                                 while(isdigit(c=Bgetc(input)))putch(c,NO);
569                                         }
570                                         Bungetc(input);
571                                 }
572                                 else putch(c,NO);
573                                 if(keyflag != DATADEF)opflag = 0;
574                         }
575                 }
576         }
577 }
578 void
579 gotif(void){
580         outs(clev->tabs);
581         if(++clev->iflev >= IFLEVEL-1){
582                 fprint(2,"too many levels of if %d\n",clev->iflev );
583                 clev->iflev = IFLEVEL-1;
584         }
585         clev->ifc[clev->iflev] = clev->tabs;
586         clev->spdepth[clev->iflev] = clev->pdepth;
587 }
588 void
589 gotelse(void){
590         clev->tabs = clev->ifc[clev->iflev];
591         clev->pdepth = clev->spdepth[clev->iflev];
592         if(--(clev->iflev) < 0)clev->iflev = 0;
593 }
594 int
595 checkif(char *pt)
596 {
597         struct keyw *lptr;
598         int cc;
599         if((lptr=lookup(pt,lastplace+1))!= 0){
600                 if(lptr->type == IF){
601                         if(strict)putch(' ',YES);
602                         copy(lptr->name);
603                         *pt='\0';
604                         lastplace = pt;
605                         if(strict){
606                                 putch(lptr->punc,NO);
607                                 eatallsp();
608                         }
609                         clev->tabs = clev->ifc[clev->iflev];
610                         clev->pdepth = clev->spdepth[clev->iflev];
611                         keyflag = KEYWORD;
612                         return(1);
613                 }
614         }
615         return(0);
616 }
617 void
618 gotdo(void){
619         if(++dolevel >= DOLEVEL-1){
620                 fprint(2,"too many levels of do %d\n",dolevel);
621                 dolevel = DOLEVEL-1;
622         }
623         dotabs[dolevel] = clev->tabs;
624         docurly[dolevel] = YES;
625 }
626 void
627 resetdo(void){
628         if(docurly[dolevel] == NO)
629                 clev->pdepth = dopdepth[dolevel];
630         if(--dolevel < 0)dolevel = 0;
631 }
632 void
633 gottype(struct keyw *lptr)
634 {
635         char *pt;
636         struct keyw *tlptr;
637         int c;
638         while(1){
639                 pt = getnext(1);
640                 if((tlptr=lookup(pt,lastplace+1))!=0){
641                         putch(' ',YES);
642                         copy(tlptr->name);
643                         *pt='\0';
644                         lastplace = pt;
645                         if(tlptr->type == STRUCT){
646                                 putch(tlptr->punc,YES);
647                                 gotstruct();
648                                 break;
649                         }
650                         lptr=tlptr;
651                         continue;
652                 }
653                 else{
654                         putch(lptr->punc,NO);
655                         while((c=getch())== ' ' || c == '\t');
656                         unget(c);
657                         break;
658                 }
659         }
660 }
661 void
662 gotstruct(void){
663         int c;
664         int cc;
665         char *pt;
666         while((c=getch()) == ' ' || c == '\t')
667                 if(!strict)putch(c,NO);
668         if(c == '{'){
669                 structlev++;
670                 unget(c);
671                 return;
672         }
673         if(isalpha(c)){
674                 putch(c,NO);
675                 while(isalnum(c=getch()))putch(c,NO);
676         }
677         unget(c);
678         pt = getnext(1);
679         if(*pt == '{')structlev++;
680         if(strict){
681                 eatallsp();
682                 putch(' ',NO);
683         }
684 }
685 void
686 gotop(int c)
687 {
688         char optmp[OPLENGTH];
689         char *op_ptr;
690         struct op *s_op;
691         char *a, *b;
692         op_ptr = optmp;
693         *op_ptr++ = c;
694         while (isop(( *op_ptr = getch())))op_ptr++;
695         if(!strict)unget(*op_ptr);
696         else if (*op_ptr != ' ')unget( *op_ptr);
697         *op_ptr = '\0';
698         s_op = op;
699         b = optmp;
700         while ((a = s_op->name) != 0){
701                 op_ptr = b;
702                 while ((*op_ptr == *a) && (*op_ptr != '\0')){
703                         a++;
704                         op_ptr++;
705                 }
706                 if (*a == '\0'){
707                         keep(s_op);
708                         opflag = s_op->setop;
709                         if (*op_ptr != '\0'){
710                                 b = op_ptr;
711                                 s_op = op;
712                                 continue;
713                         }
714                         else break;
715                 }
716                 else s_op++;
717         }
718 }
719 void
720 keep(struct op *o)
721 {
722         char    *s;
723         int ok;
724         if(o->blanks == NEVER)ok = NO;
725         else ok = YES;
726         if (strict && ((o->blanks & ALWAYS)
727             || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0)))
728                 putspace(' ',YES);
729         for(s=o->name; *s != '\0'; s++){
730                 if(*(s+1) == '\0')putch(*s,ok);
731                 else
732                         putch(*s,NO);
733         }
734         if (strict && ((o->blanks & ALWAYS)
735             || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0))) putch(' ',YES);
736 }
737 int
738 getnl(void){
739         int ch;
740         char *savp;
741         int gotcmt;
742         gotcmt = 0;
743         savp = p;
744         while ((ch = getch()) == '\t' || ch == ' ')putch(ch,NO);
745         if (ch == '/'){
746                 if ((ch = getch()) == '*'){
747                         putch('/',NO);
748                         putch('*',NO);
749                         comment(NO);
750                         ch = getch();
751                         gotcmt=1;
752                 }
753                 else if (ch == '/') {
754                         putch('/',NO);
755                         putch('/',NO);
756                         cpp_comment(NO);
757                         ch = getch();
758                         gotcmt = 1;
759                 }
760                 else {
761                         if(inswitch)*(++lastplace) = ch;
762                         else {
763                                 inswitch = 1;
764                                 *lastplace = ch;
765                         }
766                         unget('/');
767                         return(0);
768                 }
769         }
770         if(ch == '\n'){
771                 if(gotcmt == 0)p=savp;
772                 return(1);
773         }
774         unget(ch);
775         return(0);
776 }
777 void
778 ptabs(int n){
779         int     i;
780         int num;
781         if(n > maxtabs){
782                 if(!folded){
783                         Bprint(output, "/* code folded from here */\n");
784                         folded = 1;
785                 }
786                 num = n-maxtabs;
787         }
788         else {
789                 num = n;
790                 if(folded){
791                         folded = 0;
792                         Bprint(output, "/* unfolding */\n");
793                 }
794         }
795         for (i = 0; i < num; i++)Bputc(output, '\t');
796 }
797 void
798 outs(int n){
799         if (p > string){
800                 if (lbegin){
801                         ptabs(n);
802                         lbegin = 0;
803                         if (split == 1){
804                                 split = 0;
805                                 if (clev->tabs > 0)Bprint(output, "\t");
806                         }
807                 }
808                 *p = '\0';
809                 Bprint(output, "%s", string);
810                 lastlook = p = string;
811         }
812         else {
813                 if (lbegin != 0){
814                         lbegin = 0;
815                         split = 0;
816                 }
817         }
818 }
819 void
820 putch(char c,int ok)
821 {
822         int cc;
823         if(p < &string[LINE-1]){
824                 if(count+TABLENG*clev->tabs >= maxleng && ok && !folded){
825                         if(c != ' ')*p++ = c;
826                         OUT;
827                         split = 1;
828                         if((cc=getch()) != '\n')unget(cc);
829                 }
830                 else {
831                         *p++ = c;
832                         count++;
833                 }
834         }
835         else {
836                 outs(clev->tabs);
837                 *p++ = c;
838                 count = 0;
839         }
840 }
841 struct keyw *
842 lookup(char *first, char *last)
843 {
844         struct keyw *ptr;
845         char    *cptr, *ckey, *k;
846
847         if(first == last || first == 0)return(0);
848         cptr = first;
849         while (*cptr == ' ' || *cptr == '\t')cptr++;
850         if(cptr >= last)return(0);
851         ptr = key;
852         while ((ckey = ptr->name) != 0){
853                 for (k = cptr; (*ckey == *k && *ckey != '\0'); k++, ckey++);
854                 if(*ckey=='\0' && (k==last|| (k<last && !isalnum(*k)))){
855                         opflag = 1;
856                         lastlook = 0;
857                         return(ptr);
858                 }
859                 ptr++;
860         }
861         return(0);
862 }
863 int
864 comment(int ok)
865 {
866         int ch;
867         int hitnl;
868
869         hitnl = 0;
870         while ((ch  = getch()) != Beof){
871                 putch(ch, NO);
872                 if (ch == '*'){
873 gotstar:
874                         if ((ch  = getch()) == '/'){
875                                 putch(ch,NO);
876                                 return(hitnl);
877                         }
878                         putch(ch,NO);
879                         if (ch == '*')goto gotstar;
880                 }
881                 if (ch == '\n'){
882                         if(ok && !hitnl){
883                                 outs(clev->tabs);
884                         }
885                         else {
886                                 outs(0);
887                         }
888                         lbegin = 1;
889                         count = 0;
890                         hitnl = 1;
891                 }
892         }
893         return(hitnl);
894 }
895 int
896 cpp_comment(int ok)
897 {
898         int ch;
899         int hitnl;
900
901         hitnl = 0;
902         while ((ch = getch()) != -1) {
903                 if (ch == '\n') {
904                         if (ok && !hitnl)
905                                 outs(clev->tabs);
906                         else
907                                 outs(0);
908                         lbegin = 1;
909                         count = 0;
910                         hitnl = 1;
911                         break;
912                 }
913                 putch(ch, NO);
914         }
915         return hitnl;
916 }
917 void
918 putspace(char ch, int ok)
919 {
920         if(p == string)putch(ch,ok);
921         else if (*(p - 1) != ch) putch(ch,ok);
922 }
923 int
924 getch(void){
925         char c;
926         if(inswitch){
927                 if(next != '\0'){
928                         c=next;
929                         next = '\0';
930                         return(c);
931                 }
932                 if(tptr <= lastplace){
933                         if(*tptr != '\0')return(*tptr++);
934                         else if(++tptr <= lastplace)return(*tptr++);
935                 }
936                 inswitch=0;
937                 lastplace = tptr = temp;
938         }
939         return(Bgetc(input));
940 }
941 void
942 unget(char c)
943 {
944         if(inswitch){
945                 if(tptr != temp)
946                         *(--tptr) = c;
947                 else next = c;
948         }
949         else Bungetc(input);
950 }
951 char *
952 getnext(int must){
953         int c;
954         char *beg;
955         int prect,nlct;
956         prect = nlct = 0;
957         if(tptr > lastplace){
958                 tptr = lastplace = temp;
959                 err = 0;
960                 inswitch = 0;
961         }
962         tp = lastplace;
963         if(inswitch && tptr <= lastplace)
964                 if (isalnum(*lastplace)||ispunct(*lastplace)||isop(*lastplace))return(lastplace);
965 space:
966         while(isspace(c=Bgetc(input)))puttmp(c,1);
967         beg = tp;
968         puttmp(c,1);
969         if(c == '/'){
970                 if(puttmp(Bgetc(input),1) == '*'){
971 cont:
972                         while((c=Bgetc(input)) != '*'){
973                                 puttmp(c,0);
974                                 if(must == 0 && c == '\n')
975                                         if(nlct++ > 2)goto done;
976                         }
977                         puttmp(c,1);
978         star:
979                         if(puttmp((c=Bgetc(input)),1) == '/'){
980                                 beg = tp;
981                                 puttmp((c=Bgetc(input)),1);
982                         }
983                         else if(c == '*')goto star;
984                         else goto cont;
985                 }
986                 else goto done;
987         }
988         if(isspace(c))goto space;
989         if(c == '#' && tp > temp+1 && *(tp-2) == '\n'){
990                 if(prect++ > 2)goto done;
991                 while(puttmp((c=Bgetc(input)),1) != '\n')
992                         if(c == '\\')puttmp(Bgetc(input),1);
993                 goto space;
994         }
995         if(isalnum(c)){
996                 while(isalnum(c = Bgetc(input)))puttmp(c,1);
997                 Bungetc(input);
998         }
999 done:
1000         puttmp('\0',1);
1001         lastplace = tp-1;
1002         inswitch = 1;
1003         return(beg);
1004 }
1005 void
1006 copy(char *s)
1007 {
1008         while(*s != '\0')putch(*s++,NO);
1009 }
1010 void
1011 clearif(struct indent *cl)
1012 {
1013         int i;
1014         for(i=0;i<IFLEVEL-1;i++)cl->ifc[i] = 0;
1015 }
1016 char 
1017 puttmp(char c, int keep)
1018 {
1019         if(tp < &temp[TEMP-120])
1020                 *tp++ = c;
1021         else {
1022                 if(keep){
1023                         if(tp >= &temp[TEMP-1]){
1024                                 fprint(2,"can't look past huge comment - quiting\n");
1025                                 exits("boom");
1026                         }
1027                         *tp++ = c;
1028                 }
1029                 else if(err == 0){
1030                         err++;
1031                         fprint(2,"truncating long comment\n");
1032                 }
1033         }
1034         return(c);
1035 }
1036 void
1037 error(char *s)
1038 {
1039         fprint(2,"saw EOF while looking for %s\n",s);
1040         exits("boom");
1041 }