home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / prog2 / cb1.lzh / CB1.C next >
Encoding:
C/C++ Source or Header  |  1988-05-03  |  26.6 KB  |  1,185 lines

  1. /************    DOCUMENTATION
  2.  
  3. cb [-jnst] [-l length] [ file ...]    --- C program beautifier ---
  4.     j: split lines are put back together
  5.     l: split lines that are longer than length
  6.     n: tab = n spaces (default = 2)
  7.     s: K & R style
  8.     t: tab = real tabs
  9.  
  10.     cb temp>file.c        Beautifies temp and places result in file.c
  11.     cb temp1 temp2>>file.c    Beautifies temp1 & temp2 and adds to file.c
  12.  
  13.                                            ********************************/
  14.  
  15.  
  16. #include <stdio.h>
  17. /* character type flags */
  18. #define _U  01
  19. #define _L  02
  20. #define _N  04
  21. #define _S  010
  22. #define _P  020
  23. #define _C  040
  24. #define _X  0100
  25. #define _O  0200
  26.  
  27. #define isop(c)     ((_chartype_+1)[c]&_O)
  28. #define isalpha(c)  ((_chartype_+1)[c]&(_U|_L))
  29. #define isupper(c)  ((_chartype_+1)[c]&_U)
  30. #define islower(c)  ((_chartype_+1)[c]&_L)
  31. #define isdigit(c)  ((_chartype_+1)[c]&_N)
  32. #define isxdigit(c) ((_chartype_+1)[c]&(_N|_X))
  33. #define isspace(c)  ((_chartype_+1)[c]&_S)
  34. #define ispunct(c)  ((_chartype_+1)[c]&_P)
  35. #define isalnum(c)  ((_chartype_+1)[c]&(_U|_L|_N))
  36. #define isprint(c)  ((_chartype_+1)[c]&(_P|_U|_L|_N))
  37. #define iscntrl(c)  ((_chartype_+1)[c]&_C)
  38. #define isascii(c)  ((unsigned)(c)<=0177)
  39. #define toupper(c)  ((c)-'a'+'A')
  40. #define tolower(c)  ((c)-'A'+'a')
  41. #define toascii(c)  ((c)&0177)
  42. char _chartype_[] = {
  43.   0,
  44.   _C,  _C,     _C,     _C,     _C,     _C,     _C,     _C,
  45.   _C,  _C|_S,  _C|_S,  _C|_S,  _C|_S,  _C|_S,  _C,     _C,
  46.   _C,  _C,     _C,     _C,     _C,     _C,     _C,     _C,
  47.   _C,  _C,     _C,     _C,     _C,     _C,     _C,     _C,
  48.   _S,  _P|_O,  _P,     _P,     _P,     _P|_O,  _P|_O,  _P,
  49.   _P,  _P,     _P|_O,  _P|_O,  _P,     _P|_O,  _P,     _P|_O,
  50.   _N,  _N,     _N,     _N,     _N,     _N,     _N,     _N,
  51.   _N,  _N,     _P,     _P,     _P|_O,  _P|_O,  _P|_O,  _P,
  52.   _P,  _U|_X,  _U|_X,  _U|_X,  _U|_X,  _U|_X,  _U|_X,  _U,
  53.   _U,  _U,     _U,     _U,     _U,     _U,     _U,     _U,
  54.   _U,  _U,     _U,     _U,     _U,     _U,     _U,     _U,
  55.   _U,  _U,     _U,     _P,     _P,     _P,     _P|_O,  _P|_L,
  56.   _P,  _L|_X,  _L|_X,  _L|_X,  _L|_X,  _L|_X,  _L|_X,  _L,
  57.   _L,  _L,     _L,     _L,     _L,     _L,     _L,     _L,
  58.   _L,  _L,     _L,     _L,     _L,     _L,     _L,     _L,
  59.   _L,  _L,     _L,     _P,     _P|_O,  _P,     _P,     _C
  60. };
  61.  
  62. #define IF     1
  63. #define ELSE   2
  64. #define CASE   3
  65. #define TYPE   4
  66. #define DO     5
  67. #define STRUCT 6
  68. #define OTHER  7
  69.  
  70. #define ALWAYS    01
  71. #define NEVER     02
  72. #define SOMETIMES 04
  73.  
  74. #define YES 1
  75. #define NO  0
  76.  
  77. #define KEYWORD 1
  78. #define DATADEF 2
  79. #define SINIT   3
  80.  
  81. #define CLEVEL   20
  82. #define IFLEVEL  10
  83. #define DOLEVEL  10
  84. #define OPLENGTH 10
  85. #define LINE     256
  86. #define LINELENG 120
  87. #define MAXTABS  20
  88. #define TABLENG  8
  89. #define TEMP     1024
  90.  
  91. #define OUT    outs(clev->tabs); putchar('\n');opflag = lbegin = 1; count = 0
  92. #define OUTK   OUT; keyflag = 0;
  93. #define BUMP   clev->tabs++; clev->pdepth++
  94. #define UNBUMP clev->tabs -= clev->pdepth; clev->pdepth = 0
  95. #define eatspace() while((cc=getch())==' '||cc=='\t'); unget(cc)
  96. #define eatallsp() while((cc=getch())==' '||cc=='\t'||cc=='\n'); unget(cc)
  97.  
  98. struct indent {    /* one for each level of { } */
  99.   int tabs;
  100.   int pdepth;
  101.   int iflev;
  102.   int ifc[IFLEVEL];
  103.   int spdepth[IFLEVEL];
  104. } ind[CLEVEL];
  105. struct indent *clev = ind;
  106. struct keyw {
  107.   char  *name;
  108.   char  punc;
  109.   char  type;
  110. } key[] = {
  111.   "switch", ' ', OTHER,
  112.   "do", ' ', DO,
  113.   "while", ' ', OTHER,
  114.   "if", ' ', IF,
  115.   "for", ' ', OTHER,
  116.   "else", ' ', ELSE,
  117.   "case", ' ', CASE,
  118.   "default", ' ', CASE,
  119.   "char", '\t', TYPE,
  120.   "int", '\t', TYPE,
  121.   "short", '\t', TYPE,
  122.   "long", '\t', TYPE,
  123.   "unsigned", '\t', TYPE,
  124.   "float", '\t', TYPE,
  125.   "double", '\t', TYPE,
  126.   "struct", ' ', STRUCT,
  127.   "union", ' ', STRUCT,
  128.   "extern", ' ', TYPE,
  129.   "register", ' ', TYPE,
  130.   "static", ' ', TYPE,
  131.   "typedef", ' ', TYPE,
  132.   0, 0, 0
  133. };
  134. struct keyw *lookup();
  135. struct op {
  136.   char  *name;
  137.   char  blanks;
  138.   char  setop;
  139. } op[] = {
  140.   "+=", ALWAYS, YES,
  141.   "-=", ALWAYS, YES,
  142.   "*=", ALWAYS, YES,
  143.   "/=", ALWAYS, YES,
  144.   "%=", ALWAYS, YES,
  145.   ">>=",ALWAYS, YES,
  146.   "<<=",ALWAYS, YES,
  147.   "&=", ALWAYS, YES,
  148.   "^=", ALWAYS, YES,
  149.   "|=", ALWAYS, YES,
  150.   ">>", ALWAYS, YES,
  151.   "<<", ALWAYS, YES,
  152.   "<=", ALWAYS, YES,
  153.   ">=", ALWAYS, YES,
  154.   "==", ALWAYS, YES,
  155.   "!=", ALWAYS, YES,
  156.   "=",  ALWAYS, YES,
  157.   "&&", ALWAYS, YES,
  158.   "||", ALWAYS, YES,
  159.   "++", NEVER,  NO,
  160.   "--", NEVER,  NO,
  161.   "->", NEVER,  NO,
  162.   "<",  ALWAYS, YES,
  163.   ">",  ALWAYS, YES,
  164.   "+",  ALWAYS, YES,
  165.   "/",  ALWAYS, YES,
  166.   "%",  ALWAYS, YES,
  167.   "^",  ALWAYS, YES,
  168.   "|",  ALWAYS, YES,
  169.   "!",  NEVER,  YES,
  170.   "~",  NEVER,  YES,
  171.   "*",  SOMETIMES, YES,
  172.   "&",  SOMETIMES, YES,
  173.   "-",  SOMETIMES, YES,
  174.   "?",  ALWAYS, YES,
  175.   ":",  ALWAYS, YES,
  176.   0,0,0
  177. };
  178. FILE *input = stdin;
  179. char *getnext();
  180. char puttmp();
  181. int opflag=1;
  182. int strict=0,join=0,keyflag=0,paren=0,split=0,folded=0,dolevel=0;
  183. int dotabs[DOLEVEL];
  184. int docurly[DOLEVEL];
  185. int dopdepth[DOLEVEL];
  186. int structlev=0,err=0,question=0,count=0,inswitch=0;
  187. char string[LINE];
  188. char *lastlook;
  189. char *p = string;
  190. char temp[TEMP];
  191. char *tp;
  192. char *lastplace = temp;
  193. char *tptr = temp;
  194. int maxleng = LINELENG;
  195. int maxtabs = MAXTABS;
  196. char next = '\0';
  197. int tab,z,i=1,lbegin=1,space=2;
  198.  
  199. main(argc,argv)
  200. char **argv;
  201. {
  202.   if(argc == 1)
  203.       help();
  204.  
  205.   while(--argc>0)
  206.   {
  207.     if(*argv[i]=='-')
  208.       while(*++argv[i])
  209.         switch (*argv[i])
  210.         {
  211.         case '0':  case '1':  case '2':  case '3':  case '4':
  212.         case '5':  case '6':  case '7':  case '8':  case '9':
  213.           space=*argv[i]-'0';
  214.           break;
  215.         case 's':
  216.           strict = 1;
  217.           break;
  218.         case 't':
  219.           ++tab;
  220.           break;
  221.         case 'j':
  222.           join = 1;
  223.           break;
  224.         case 'l':
  225.           ++i;
  226.           maxleng = atoi(argv[i]);
  227.           maxtabs = maxleng/TABLENG - 2;
  228.           maxleng -= .1 * maxleng;
  229.           argc--;
  230.           break;
  231.         default:
  232.           fprintf(stderr,"Usage: cb [-jnst] [-l length] [ file ...]\n");
  233.           fprintf(stderr,"    j: split lines are put back together\n");
  234.           fprintf(stderr,"    l: split lines that are longer than length\n");
  235.           fprintf(stderr,"    n: tab = n spaces (default = 2)\n");
  236.           fprintf(stderr,"    s: K & R style\n");
  237.           fprintf(stderr,"    t: tab = real tabs\n");
  238.           exit(2);
  239.         }
  240.     else
  241.     {
  242.       if ((input = fopen( argv[i], "r")) == NULL)
  243.       {
  244.         fprintf(stderr, "cb: cannot open input file %s\n", argv[i]);
  245.         exit(1);
  246.       }
  247.     }
  248.     ++i;
  249.   }
  250.   work();
  251.   exit(0);
  252. }
  253.  
  254. work(){
  255.   register int c;
  256.   register struct keyw *lptr;
  257.   char *pt;
  258.   char cc;
  259.   int ct;
  260.  
  261.   while ((c = getch()) != EOF){
  262.     switch (c){
  263.     case '{':
  264.       if ((lptr = lookup(lastlook,p)) != 0){
  265.         if (lptr->type == ELSE)gotelse();
  266.         else if(lptr->type == DO)gotdo();
  267.         else if(lptr->type == STRUCT)structlev++;
  268.       }
  269.       if(++clev >= &ind[CLEVEL-1]){
  270.         fprintf(stderr,"too many levels of curly brackets\n");
  271.         clev = &ind[CLEVEL-1];
  272.       }
  273.       clev->pdepth = 0;
  274.       clev->tabs = (clev-1)->tabs;
  275.       clearif(clev);
  276.       if(strict && clev->tabs > 0)
  277.         putspace(' ',NO);
  278.       putch(c,NO);
  279.       getnl();
  280.       if(keyflag == DATADEF){
  281.         OUT;
  282.       }
  283.       else {
  284.         OUTK;
  285.       }
  286.       clev->tabs++;
  287.       pt = getnext(0);      /* to handle initialized structures */
  288.       if(*pt == '{'){    /* hide one level of {} */
  289.         while((c=getch()) != '{');
  290.         putch(c,NO);
  291.         if(strict){
  292.           putch(' ',NO);
  293.           eatspace();
  294.         }
  295.         keyflag = SINIT;
  296.       }
  297.       continue;
  298.     case '}':
  299.       pt = getnext(0);      /* to handle initialized structures */
  300.       if(*pt == ','){
  301.         if(strict){
  302.           putspace(' ',NO);
  303.           eatspace();
  304.         }
  305.         putch(c,NO);
  306.         putch(*pt,NO);
  307.         *pt = '\0';
  308.         ct = getnl();
  309.         pt = getnext(0);
  310.         if(*pt == '{'){
  311.           OUT;
  312.           while((cc = getch()) != '{');
  313.           putch(cc,NO);
  314.           if(strict){
  315.             putch(' ',NO);
  316.             eatspace();
  317.           }
  318.           pt = getnext(0);
  319.           continue;
  320.         }
  321.         else if(strict || ct){
  322.           OUT;
  323.         }
  324.         continue;
  325.       }
  326.       else if(keyflag == SINIT && *pt == '}'){
  327.         if(strict)
  328.           putspace(' ',NO);
  329.         putch(c,NO);
  330.         getnl();
  331.         OUT;
  332.         keyflag = DATADEF;
  333.         *pt = '\0';
  334.         pt = getnext(0);
  335.       }
  336.       outs(clev->tabs);
  337.       if(--clev < ind)clev = ind;
  338.       ptabs(clev->tabs);
  339.       putch(c,NO);
  340.       lbegin = 0;
  341.       lptr=lookup(pt,lastplace+1);
  342.       c = *pt;
  343.       if(*pt == ';' || *pt == ','){
  344.         putch(*pt,NO);
  345.         *pt = '\0';
  346.         lastplace=pt;
  347.       }
  348.       ct = getnl();
  349.       if((dolevel && clev->tabs <= dotabs[dolevel]) || (structlev )
  350.           || (lptr != 0 &&lptr->type == ELSE&& clev->pdepth == 0)){
  351.         if(c == ';'){
  352.           OUTK;
  353.         }
  354.         else if(strict || (lptr != 0 && lptr->type == ELSE && ct == 0)){
  355.           putspace(' ',NO);
  356.           eatspace();
  357.         }
  358.         else if(lptr != 0 && lptr->type == ELSE){
  359.           OUTK;
  360.         }
  361.         if(structlev){
  362.           structlev--;
  363.           keyflag = DATADEF;
  364.         }
  365.       }
  366.       else {
  367.         OUTK;
  368.         if(strict && clev->tabs == 0){
  369.           if((c=getch()) != '\n'){
  370.             putchar('\n');
  371.             putchar('\n');
  372.             unget(c);
  373.           }
  374.           else {
  375.             putchar('\n');
  376.             if((c=getch()) != '\n')unget(c);
  377.             putchar('\n');
  378.           }
  379.         }
  380.       }
  381.       if(lptr != 0 && lptr->type == ELSE && clev->pdepth != 0){
  382.         UNBUMP;
  383.       }
  384.       if(lptr == 0 || lptr->type != ELSE){
  385.         clev->iflev = 0;
  386.         if(dolevel&&docurly[dolevel]==NO&&clev->tabs==dotabs[dolevel]+1)
  387.           clev->tabs--;
  388.         else if(clev->pdepth != 0){
  389.           UNBUMP;
  390.         }
  391.       }
  392.       continue;
  393.     case '(':
  394.       paren++;
  395.       if ((lptr = lookup(lastlook,p)) != 0){
  396.         if(!(lptr->type == TYPE || lptr->type == STRUCT))keyflag=KEYWORD;
  397.         if (strict){
  398.           putspace(lptr->punc,NO);
  399.           opflag = 1;
  400.         }
  401.         putch(c,NO);
  402.         if (lptr->type == IF)gotif();
  403.       }
  404.       else {
  405.         putch(c,NO);
  406.         lastlook = p;
  407.         opflag = 1;
  408.       }
  409.       continue;
  410.     case ')':
  411.       if(--paren < 0)paren = 0;
  412.       putch(c,NO);
  413.       if((lptr = lookup(lastlook,p)) != 0){
  414.         if(lptr->type == TYPE || lptr->type == STRUCT)
  415.           opflag = 1;
  416.       }
  417.       else if(keyflag == DATADEF)opflag = 1;
  418.       else opflag = 0;
  419.       outs(clev->tabs);
  420.       pt = getnext(1);
  421.       if ((ct = getnl()) == 1 && !strict){
  422.         if(dolevel && clev->tabs <= dotabs[dolevel])
  423.           resetdo();
  424.         if(clev->tabs > 0 && (paren != 0 || keyflag == 0)){
  425.           if(join){
  426.             eatspace();
  427.             putch(' ',YES);
  428.             continue;
  429.           } else {
  430.             OUT;
  431.             split = 1;
  432.             continue;
  433.           }
  434.         }
  435.         else if(clev->tabs > 0 && *pt != '{'){
  436.           BUMP;
  437.         }
  438.         OUTK;
  439.       }
  440.       else if(strict){
  441.         if(clev->tabs == 0){
  442.           if(*pt != ';' && *pt != ',' && *pt != '(' && *pt != '['){
  443.             OUTK;
  444.           }
  445.         }
  446.         else {
  447.           if(keyflag == KEYWORD && paren == 0){
  448.             if(dolevel && clev->tabs <= dotabs[dolevel]){
  449.               resetdo();
  450.               eatspace();
  451.               continue;
  452.             }
  453.             if(*pt != '{'){
  454.               BUMP;
  455.               OUTK;
  456.             }
  457.             else {
  458.               *pt='\0';
  459.               eatspace();
  460.               unget('{');
  461.             }
  462.           }
  463.           else if(ct){
  464.             if(paren){
  465.               if(join){
  466.                 eatspace();
  467.               } else {
  468.                 split = 1;
  469.                 OUT;
  470.               }
  471.             }
  472.             else {
  473.               OUTK;
  474.             }
  475.           }
  476.         }
  477.       }
  478.       else if(dolevel && clev->tabs <= dotabs[dolevel])
  479.         resetdo();
  480.       continue;
  481.     case ' ':
  482.     case '\t':
  483.       if ((lptr = lookup(lastlook,p)) != 0){
  484.         if(!(lptr->type==TYPE||lptr->type==STRUCT))
  485.           keyflag = KEYWORD;
  486.         else if(paren == 0)keyflag = DATADEF;
  487.         if(strict){
  488.           if(lptr->type != ELSE){
  489.             if(lptr->type == TYPE){
  490.               if(paren != 0)putch(' ',YES);
  491.             }
  492.             else
  493.               putch(lptr->punc,NO);
  494.             eatspace();
  495.           }
  496.         }
  497.         else putch(c,YES);
  498.         switch(lptr->type){
  499.         case CASE:
  500.           outs(clev->tabs-1);
  501.           continue;
  502.         case ELSE:
  503.           pt = getnext(1);
  504.           eatspace();
  505.           if((cc = getch()) == '\n' && !strict){
  506.             unget(cc);
  507.           }
  508.           else {
  509.             unget(cc);
  510.             if(checkif(pt))continue;
  511.           }
  512.           gotelse();
  513.           if(strict) unget(c);
  514.           if(getnl() == 1 && !strict){
  515.             OUTK;
  516.             if(*pt != '{'){
  517.               BUMP;
  518.             }
  519.           }
  520.           else if(strict){
  521.             if(*pt != '{'){
  522.               OUTK;
  523.               BUMP;
  524.             }
  525.           }
  526.           continue;
  527.         case IF:
  528.           gotif();
  529.           continue;
  530.         case DO:
  531.           gotdo();
  532.           pt = getnext(1);
  533.           if(*pt != '{'){
  534.             eatallsp();
  535.             OUTK;
  536.             docurly[dolevel] = NO;
  537.             dopdepth[dolevel] = clev->pdepth;
  538.             clev->pdepth = 0;
  539.             clev->tabs++;
  540.           }
  541.           continue;
  542.         case TYPE:
  543.           if(paren)continue;
  544.           if(!strict)continue;
  545.           gottype(lptr);
  546.           continue;
  547.         case STRUCT:
  548.           gotstruct();
  549.           continue;
  550.         }
  551.       }
  552.       else if (lbegin == 0 || p > string)
  553.         if(strict)
  554.           putch(c,NO);
  555.         else putch(c,YES);
  556.       continue;
  557.     case ';':
  558.       putch(c,NO);
  559.       if(paren != 0){
  560.         if(strict){
  561.           putch(' ',YES);
  562.           eatspace();
  563.         }
  564.         opflag = 1;
  565.         continue;
  566.       }
  567.       outs(clev->tabs);
  568.       pt = getnext(0);
  569.       lptr=lookup(pt,lastplace+1);
  570.       if(lptr == 0 || lptr->type != ELSE){
  571.         clev->iflev = 0;
  572.         if(clev->pdepth != 0){
  573.           UNBUMP;
  574.         }
  575.         if(dolevel&&docurly[dolevel]==NO&&clev->tabs<=dotabs[dolevel]+1)
  576.           clev->tabs--;
  577.         /*
  578.             else if(clev->pdepth != 0){
  579.                UNBUMP;
  580.             }
  581. */
  582.       }
  583.       getnl();
  584.       OUTK;
  585.       continue;
  586.     case '\n':
  587.       if ((lptr = lookup(lastlook,p)) != 0){
  588.         pt = getnext(1);
  589.         if (lptr->type == ELSE){
  590.           if(strict)
  591.             if(checkif(pt))continue;
  592.           gotelse();
  593.           OUTK;
  594.           if(*pt != '{'){
  595.             BUMP;
  596.           }
  597.         }
  598.         else if(lptr->type == DO){
  599.           OUTK;
  600.           gotdo();
  601.           if(*pt != '{'){
  602.             docurly[dolevel] = NO;
  603.             dopdepth[dolevel] = clev->pdepth;
  604.             clev->pdepth = 0;
  605.             clev->tabs++;
  606.           }
  607.         }
  608.         else {
  609.           OUTK;
  610.           if(lptr->type == STRUCT)gotstruct();
  611.         }
  612.       }
  613.       else if(p == string)putchar('\n');
  614.       else {
  615.         if(clev->tabs > 0 &&(paren != 0 || keyflag == 0)){
  616.           if(join){
  617.             putch(' ',YES);
  618.             eatspace();
  619.             continue;
  620.           } else {
  621.             OUT;
  622.             split = 1;
  623.             continue;
  624.           }
  625.         }
  626.         else if(keyflag == KEYWORD){
  627.           OUTK;
  628.           continue;
  629.         }
  630.         OUT;
  631.       }
  632.       continue;
  633.     case '"':
  634.     case '\'':
  635.       putch(c,NO);
  636.       while ((cc = getch()) != c){
  637.         putch(cc,NO);
  638.         if (cc == '\\'){
  639.           putch(getch(),NO);
  640.         }
  641.         if (cc == '\n'){
  642.           outs(clev->tabs);
  643.           lbegin = 1;
  644.           count = 0;
  645.         }
  646.       }
  647.       putch(cc,NO);
  648.       opflag=0;
  649.       if (getnl() == 1){
  650.         unget('\n');
  651.       }
  652.       continue;
  653.     case '\\':
  654.       putch(c,NO);
  655.       putch(getch(),NO);
  656.       continue;
  657.     case '?':
  658.       question = 1;
  659.       gotop(c);
  660.       continue;
  661.     case ':':
  662.       if (question == 1){
  663.         question = 0;
  664.         gotop(c);
  665.         continue;
  666.       }
  667.       putch(c,NO);
  668.       if(structlev)continue;
  669.       if ((lptr = lookup(lastlook,p)) != 0){
  670.         if (lptr->type == CASE)outs(clev->tabs - 1);
  671.       }
  672.       else {
  673.         lbegin = 0;
  674.         outs(clev->tabs);
  675.       }
  676.       getnl();
  677.       OUTK;
  678.       continue;
  679.     case '/':
  680.       if ((cc = getch()) != '*'){
  681.         unget(cc);
  682.         gotop(c);
  683.         continue;
  684.       }
  685.       putch(c,NO);
  686.       putch(cc,NO);
  687.       cc = comment(YES);
  688.       if(getnl() == 1){
  689.         if(cc == 0){
  690.           OUT;
  691.         }
  692.         else {
  693.           outs(0);
  694.           putchar('\n');
  695.           lbegin = 1;
  696.           count = 0;
  697.         }
  698.         lastlook = 0;
  699.       }
  700.       continue;
  701.     case '[':
  702.       putch(c,NO);
  703.       ct = 0;
  704.       while((c = getch()) != ']' || ct > 0){
  705.         putch(c,NO);
  706.         if(c == '[')ct++;
  707.         if(c == ']')ct--;
  708.       }
  709.       putch(c,NO);
  710.       continue;
  711.     case '#':
  712.       putch(c,NO);
  713.       while ((cc = getch()) != '\n'){
  714.         if (cc == '\\'){
  715.           putch(cc,NO);
  716.           cc = getch();
  717.         }
  718.         putch(cc,NO);
  719.       }
  720.       putch(cc,NO);
  721.       lbegin = 0;
  722.       outs(clev->tabs);
  723.       lbegin = 1;
  724.       count = 0;
  725.       continue;
  726.     default:
  727.       if (c == ','){
  728.         opflag = 1;
  729.         putch(c,YES);
  730.         if (strict){
  731.           if ((cc = getch()) != ' ')unget(cc);
  732.           if(cc != '\n')putch(' ',YES);
  733.         }
  734.       }
  735.       else if(isop(c))gotop(c);
  736.       else {
  737.         if(isalnum(c) && lastlook == 0)lastlook = p;
  738.         putch(c,NO);
  739.         if(keyflag != DATADEF)opflag = 0;
  740.       }
  741.     }
  742.   }
  743. }
  744.  
  745. gotif(){
  746.   outs(clev->tabs);
  747.   if(++clev->iflev >= IFLEVEL-1){
  748.     fprintf(stderr,"too many levels of if\n");
  749.     clev->iflev = IFLEVEL-1;
  750.   }
  751.   clev->ifc[clev->iflev] = clev->tabs;
  752.   clev->spdepth[clev->iflev] = clev->pdepth;
  753. }
  754.  
  755. gotelse(){
  756.   clev->tabs = clev->ifc[clev->iflev];
  757.   clev->pdepth = clev->spdepth[clev->iflev];
  758.   if(--(clev->iflev) < 0)clev->iflev = 0;
  759. }
  760.  
  761. checkif(pt)
  762. char *pt;
  763. {
  764.   register struct keyw *lptr;
  765.   int cc;
  766.   if((lptr=lookup(pt,lastplace+1))!= 0){
  767.     if(lptr->type == IF){
  768.       if(strict)putch(' ',YES);
  769.       copy(lptr->name);
  770.       *pt='\0';
  771.       lastplace = pt;
  772.       if(strict){
  773.         putch(lptr->punc,NO);
  774.         eatallsp();
  775.       }
  776.       clev->tabs = clev->ifc[clev->iflev];
  777.       clev->pdepth = clev->spdepth[clev->iflev];
  778.       keyflag = KEYWORD;
  779.       return(1);
  780.     }
  781.   }
  782.   return(0);
  783. }
  784. gotdo(){
  785.   if(++dolevel >= DOLEVEL-1){
  786.     fprintf(stderr,"too many levels of do\n");
  787.     dolevel = DOLEVEL-1;
  788.   }
  789.   dotabs[dolevel] = clev->tabs;
  790.   docurly[dolevel] = YES;
  791. }
  792. resetdo(){
  793.   if(docurly[dolevel] == NO)
  794.     clev->pdepth = dopdepth[dolevel];
  795.   if(--dolevel < 0)dolevel = 0;
  796. }
  797. gottype(lptr)
  798. struct keyw *lptr;
  799. {
  800.   char *pt;
  801.   struct keyw *tlptr;
  802.   int c;
  803.   while(1){
  804.     pt = getnext(1);
  805.     if((tlptr=lookup(pt,lastplace+1))!=0){
  806.       putch(' ',YES);
  807.       copy(tlptr->name);
  808.       *pt='\0';
  809.       lastplace = pt;
  810.       if(tlptr->type == STRUCT){
  811.         putch(tlptr->punc,YES);
  812.         gotstruct();
  813.         break;
  814.       }
  815.       lptr=tlptr;
  816.       continue;
  817.     }
  818.     else{
  819.       putch(lptr->punc,NO);
  820.       while((c=getch())== ' ' || c == '\t');
  821.       unget(c);
  822.       break;
  823.     }
  824.   }
  825. }
  826. gotstruct(){
  827.   int c;
  828.   int cc;
  829.   char *pt;
  830.   while((c=getch()) == ' ' || c == '\t')
  831.     if(!strict)putch(c,NO);
  832.   if(c == '{'){
  833.     structlev++;
  834.     unget(c);
  835.     return;
  836.   }
  837.   if(isalpha(c)){
  838.     putch(c,NO);
  839.     while(isalnum(c=getch()))putch(c,NO);
  840.   }
  841.   unget(c);
  842.   pt = getnext(1);
  843.   if(*pt == '{')structlev++;
  844.   if(strict){
  845.     eatallsp();
  846.     putch(' ',NO);
  847.   }
  848. }
  849. gotop(c)
  850. {
  851.   char optmp[OPLENGTH];
  852.   char *op_ptr;
  853.   struct op *s_op;
  854.   char *a, *b;
  855.   op_ptr = optmp;
  856.   *op_ptr++ = c;
  857.   while (isop(( *op_ptr = getch())))op_ptr++;
  858.   if(!strict)unget(*op_ptr);
  859.   else if (*op_ptr != ' ')unget( *op_ptr);
  860.   *op_ptr = '\0';
  861.   s_op = op;
  862.   b = optmp;
  863.   while ((a = s_op->name) != 0){
  864.     op_ptr = b;
  865.     while ((*op_ptr == *a) && (*op_ptr != '\0')){
  866.       a++;
  867.       op_ptr++;
  868.     }
  869.     if (*a == '\0'){
  870.       keep(s_op);
  871.       opflag = s_op->setop;
  872.       if (*op_ptr != '\0'){
  873.         b = op_ptr;
  874.         s_op = op;
  875.         continue;
  876.       }
  877.       else break;
  878.     }
  879.     else s_op++;
  880.   }
  881. }
  882.  
  883.  
  884. keep(o)
  885. struct op *o;
  886. {
  887.   char    *s;
  888.   int ok;
  889.   ok = !strict;
  890.   if (strict && ((o->blanks & ALWAYS)
  891.       || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0)))
  892.     putspace(' ',YES);
  893.   for(s=o->name; *s != '\0'; s++){
  894.     putch(*s,ok);
  895.     ok = NO;
  896.   }
  897.   if (strict && ((o->blanks & ALWAYS)
  898.       || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0)))
  899.     putch(' ',YES);
  900. }
  901. getnl(){
  902.   register int ch;
  903.   char *savp;
  904.   int gotcmt;
  905.   gotcmt = 0;
  906.   savp = p;
  907.   while ((ch = getch()) == '\t' || ch == ' ')putch(ch,NO);
  908.   if (ch == '/'){
  909.     if ((ch = getch()) == '*'){
  910.       putch('/',NO);
  911.       putch('*',NO);
  912.       comment(NO);
  913.       ch = getch();
  914.       gotcmt=1;
  915.     }
  916.     else {
  917.       if(inswitch)*(++lastplace) = ch;
  918.       else {
  919.         inswitch = 1;
  920.         *lastplace = ch;
  921.       }
  922.       unget('/');
  923.       return(0);
  924.     }
  925.   }
  926.   if(ch == '\n'){
  927.     if(gotcmt == 0)p=savp;
  928.     return(1);
  929.   }
  930.   unget(ch);
  931.   return(0);
  932. }
  933. ptabs(n){
  934.   int     i;
  935.   int num;
  936.   if(n > maxtabs){
  937.     if(!folded){
  938.       printf("/* code folded from here */\n");
  939.       folded = 1;
  940.     }
  941.     num = n-maxtabs;
  942.   }
  943.   else {
  944.     num = n;
  945.     if(folded){
  946.       folded = 0;
  947.       printf("/* unfolding */\n");
  948.     }
  949.   }
  950.   if(tab)
  951.     for (i = 0; i < num; i++)printf("\t");    /* tab = real tabs */
  952.   else
  953.     for (i = 0; i < num; i++)
  954.       for(z=0;z<space;z++)printf(" ");     /* tab = "space" spaces */
  955. }
  956. outs(n){
  957.   if (p > string){
  958.     if (lbegin){
  959.       ptabs(n);
  960.       lbegin = 0;
  961.       if (split == 1){
  962.         split = 0;
  963.         if (clev->tabs > 0)printf("    ");
  964.       }
  965.     }
  966.     *p = '\0';
  967.     printf("%s", string);
  968.     lastlook = p = string;
  969.   }
  970.   else {
  971.     if (lbegin != 0){
  972.       lbegin = 0;
  973.       split = 0;
  974.     }
  975.   }
  976. }
  977. putch(c,ok)
  978. char c;
  979. {
  980.   register int cc;
  981.   if(p < &string[LINE-1]){
  982.     if(count+TABLENG*clev->tabs >= maxleng && ok && !folded){
  983.       if(c != ' ')*p++ = c;
  984.       OUT;
  985.       split = 1;
  986.       if((cc=getch()) != '\n')unget(cc);
  987.     }
  988.     else {
  989.       *p++ = c;
  990.       count++;
  991.     }
  992.   }
  993.   else {
  994.     outs(clev->tabs);
  995.     *p++ = c;
  996.     count = 0;
  997.   }
  998. }
  999. struct keyw *
  1000. lookup(first, last)
  1001. char *first, *last;
  1002. {
  1003.   struct keyw *ptr;
  1004.   char    *cptr, *ckey, *k;
  1005.  
  1006.   if(first == last || first == 0)return(0);
  1007.   cptr = first;
  1008.   while (*cptr == ' ' || *cptr == '\t')cptr++;
  1009.   if(cptr >= last)return(0);
  1010.   ptr = key;
  1011.   while ((ckey = ptr->name) != 0){
  1012.     for (k = cptr; (*ckey == *k && *ckey != '\0'); k++, ckey++);
  1013.     if(*ckey=='\0' && (k==last|| (k<last && !isalnum(*k)))){
  1014.       opflag = 1;
  1015.       lastlook = 0;
  1016.       return(ptr);
  1017.     }
  1018.     ptr++;
  1019.   }
  1020.   return(0);
  1021. }
  1022. comment(ok)
  1023. {
  1024.   register int ch;
  1025.   int hitnl;
  1026.  
  1027.   hitnl = 0;
  1028.   while ((ch  = getch()) != EOF){
  1029.     putch(ch, NO);
  1030.     if (ch == '*'){
  1031. gotstar:
  1032.       if ((ch  = getch()) == '/'){
  1033.         putch(ch,NO);
  1034.         return(hitnl);
  1035.       }
  1036.       putch(ch,NO);
  1037.       if (ch == '*')goto gotstar;
  1038.     }
  1039.     if (ch == '\n'){
  1040.       if(ok && !hitnl){
  1041.         outs(clev->tabs);
  1042.       }
  1043.       else {
  1044.         outs(0);
  1045.       }
  1046.       lbegin = 1;
  1047.       count = 0;
  1048.       hitnl = 1;
  1049.     }
  1050.   }
  1051.   return(hitnl);
  1052. }
  1053. putspace(ch,ok)
  1054. char    ch;
  1055. {
  1056.   if(p == string)putch(ch,ok);
  1057.   else if (*(p - 1) != ch) putch(ch,ok);
  1058. }
  1059. getch(){
  1060.   register char c;
  1061.   if(inswitch){
  1062.     if(next != '\0'){
  1063.       c=next;
  1064.       next = '\0';
  1065.       return(c);
  1066.     }
  1067.     if(tptr <= lastplace){
  1068.       if(*tptr != '\0')return(*tptr++);
  1069.       else if(++tptr <= lastplace)return(*tptr++);
  1070.     }
  1071.     inswitch=0;
  1072.     lastplace = tptr = temp;
  1073.   }
  1074.   return(getc(input));
  1075. }
  1076. unget(c)
  1077. {
  1078.   if(inswitch){
  1079.     if(tptr != temp)
  1080.       *(--tptr) = c;
  1081.     else next = c;
  1082.   }
  1083.   else ungetc(c,input);
  1084. }
  1085. char *
  1086. getnext(must){
  1087.   int c;
  1088.   char *beg;
  1089.   int prect,nlct;
  1090.   prect = nlct = 0;
  1091.   if(tptr > lastplace){
  1092.     tptr = lastplace = temp;
  1093.     err = 0;
  1094.     inswitch = 0;
  1095.   }
  1096.   tp = beg = lastplace;
  1097.   if(inswitch && tptr <= lastplace)
  1098.     if (isalnum(*lastplace)||ispunct(*lastplace)||isop(*lastplace))
  1099.       return(lastplace);
  1100. space:
  1101.   while(isspace(c=getc(input)))puttmp(c,1);
  1102.   beg = tp;
  1103.   puttmp(c,1);
  1104.   if(c == '/'){
  1105.     if(puttmp((c=getc(input)),1) == '*'){
  1106. cont:
  1107.       while((c=getc(input)) != '*'){
  1108.         puttmp(c,0);
  1109.         if(must == 0 && c == '\n')
  1110.           if(nlct++ > 2)goto done;
  1111.       }
  1112.       puttmp(c,1);
  1113. star:
  1114.       if(puttmp((c=getc(input)),1) == '/'){
  1115.         beg = tp;
  1116.         puttmp((c=getc(input)),1);
  1117.       }
  1118.       else if(c == '*')goto star;
  1119.       else goto cont;
  1120.     }
  1121.     else goto done;
  1122.   }
  1123.   if(isspace(c))goto space;
  1124.   if(c == '#' && tp > temp+1 && *(tp-2) == '\n'){
  1125.     if(prect++ > 2)goto done;
  1126.     while(puttmp((c=getc(input)),1) != '\n')
  1127.       if(c == '\\')puttmp(getc(input),1);
  1128.     goto space;
  1129.   }
  1130.   if(isalnum(c)){
  1131.     while(isalnum(c = getc(input)))puttmp(c,1);
  1132.     ungetc(c,input);
  1133.   }
  1134. done:
  1135.   puttmp('\0',1);
  1136.   lastplace = tp-1;
  1137.   inswitch = 1;
  1138.   return(beg);
  1139. }
  1140. copy(s)
  1141. char *s;
  1142. {
  1143.   while(*s != '\0')putch(*s++,NO);
  1144. }
  1145. clearif(cl)
  1146. struct indent *cl;
  1147. {
  1148.   int i;
  1149.   for(i=0;i<IFLEVEL-1;i++)cl->ifc[i] = 0;
  1150. }
  1151. char puttmp(c,keep)
  1152. char c;
  1153. {
  1154.   if(tp < &temp[TEMP-120])
  1155.     *tp++ = c;
  1156.   else {
  1157.     if(keep){
  1158.       if(tp >= &temp[TEMP-1]){
  1159.         fprintf(stderr,"can't look past huge comment - quitting\n");
  1160.         exit(3);
  1161.       }
  1162.       *tp++ = c;
  1163.     }
  1164.     else if(err == 0){
  1165.       err++;
  1166.       fprintf(stderr,"truncating long comment\n");
  1167.     }
  1168.   }
  1169.   return(c);
  1170. }
  1171.  
  1172.  
  1173. help()
  1174. {
  1175. puts("cb [-jnst] [-l length] [ file ...]    /* C program beautifier */");
  1176. puts("j: split lines are put back together");
  1177. puts("l: split lines that are longer than length");
  1178. puts("n: tab = n spaces (default = 2)");
  1179. puts("s: K & R style");
  1180. puts("t: tab = real tabs");
  1181. puts(" ");
  1182. puts("cb temp>file.c        Beautifies temp and places result in file.c");
  1183. puts("cb temp1 temp2>>file.c    Beautifies temp1 & temp2 and adds to file.c");
  1184. exit(0);
  1185. }