Blob
1 #include <u.h>2 #include <libc.h>3 #include <bio.h>4 #include "cb.h"5 #include "cbtype.h"7 void8 main(int argc, char *argv[])9 {10 Biobuf stdin, stdout;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 void55 work(void){56 int c;57 struct keyw *lptr;58 char *pt;59 int cc;60 int ct;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 else298 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 void573 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 void583 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 int589 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 void612 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 void621 resetdo(void){622 if(docurly[dolevel] == NO)623 clev->pdepth = dopdepth[dolevel];624 if(--dolevel < 0)dolevel = 0;625 }626 void627 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 void656 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 void680 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 void714 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 else726 putch(*s,NO);727 }728 if (strict && ((o->blanks & ALWAYS)729 || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0))) putch(' ',YES);730 }731 int732 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 void772 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 void792 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 void814 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;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 int858 comment(int ok)859 {860 int ch;861 int hitnl;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 int890 cpp_comment(int ok)891 {892 int ch;893 int hitnl;895 hitnl = 0;896 while ((ch = getch()) != -1) {897 if (ch == '\n') {898 if (ok && !hitnl)899 outs(clev->tabs);900 else901 outs(0);902 lbegin = 1;903 count = 0;904 hitnl = 1;905 break;906 }907 putch(ch, NO);908 }909 return hitnl;910 }911 void912 putspace(char ch, int ok)913 {914 if(p == string)putch(ch,ok);915 else if (*(p - 1) != ch) putch(ch,ok);916 }917 int918 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 void936 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 void1000 copy(char *s)1001 {1002 while(*s != '\0')putch(*s++,NO);1003 }1004 void1005 clearif(struct indent *cl)1006 {1007 int i;1008 for(i=0;i<IFLEVEL-1;i++)cl->ifc[i] = 0;1009 }1010 char1011 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 void1031 error(char *s)1032 {1033 fprint(2,"saw EOF while looking for %s\n",s);1034 exits("boom");1035 }