home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 344_01 / cb.c < prev    next >
C/C++ Source or Header  |  1990-12-11  |  14KB  |  537 lines

  1. /*
  2.         HEADER:         CUG236;
  3.         TITLE:          C Source Formatter;
  4.         DATE:           04/04/1987;
  5.         DESCRIPTION:    "Formats a C source program with proper indents for
  6.                         each statement.";
  7.         VERSION:        2.1;
  8.         KEYWORDS:       Pretty Printer;
  9.         FILENAME:       CB.C;
  10.         SEE-ALSO:       CB.DOC;
  11.         COMPILERS:      vanilla;
  12.         AUTHORS:        W. C. Colley III, J. W. Kindschi Jr.;
  13. */
  14.  
  15. /*
  16.         Modified for Turbo C and to clean up some problems
  17.         with "if", "else", "for" and comments.
  18.         by: Don Holland (5 Dec 1990)
  19.  
  20.         Modified for Portable C
  21.         by: William C. Colley, III (4 APR 1987)
  22.  
  23.         Modified for Lattice C Ver 1.01
  24.         by: John W. Kindschi Jr. (10-30-83)
  25.  
  26.         Swiped from CPIG'S UNIX system and modified to
  27.         run under BDS C by William C. Colley, III
  28.  
  29.  
  30. To use the program type the following command line:
  31.  
  32.         A>cb input.fil [output.fil]
  33.  
  34.         Where input.fil is the file to be pretty printed and [output.fil]
  35.         is the destination file. If no output file is specified, then
  36.         the output goes to standard output.
  37. */
  38.  
  39. #include <stdio.h>
  40. #include <ctype.h>
  41. #include <stddef.h>
  42.  
  43. /*
  44.  * Portability Note:  The AZTEC C compilers handle the binary/text file
  45.  * dichotomy differently from most other compilers.  Uncomment the following
  46.  * pair of #defines if you are running AZTEC C:
  47.  */
  48.  
  49. /*
  50. #define getc(f)         agetc(f)
  51. #define putc(c,f)       aputc(c,f)
  52. */
  53.  
  54. char cc, lchar, pchar, string[200];
  55. char *wif[] =   {   
  56.    "if",   NULL                };
  57. char *welse[] = {   
  58.    "else", NULL                };
  59. char *wfor[] =  {   
  60.    "for",  NULL                };
  61. char *wds[] =   {   
  62.    "case", "default",  NULL    };
  63.  
  64. int clevel, ct, iflev, ind[10], level, paren, sifflg[10], siflev[10];
  65. int sind[20][10], slevel[10], spflg[20][10], stabs[20][10];
  66. int aflg, bflg, eflg, ifflg = 0, pflg[10], qflg, sflg = 1;
  67. int c, j, lastchar, peek = -1, tabs, ifnlflg;       /* 12/5/90 */
  68. FILE *f1, *f2 = stdout;
  69.  
  70. void comment(), gotelse(), ptabs(), put_str();
  71.  
  72. /*************************************************************************/
  73.  
  74. int main(argc,argv)
  75.  
  76. int argc;
  77. char *argv[];
  78.  
  79. {
  80.  
  81.    int getchr(), get_nl(), get_str(), lookup();
  82.  
  83.    /* Initialize everything here */
  84.  
  85.    if (argc < 2 || argc > 3) {
  86.       fprintf(stderr,"Usage:  CB input.fil { output.fil }\n");  
  87.       return !0;
  88.    }
  89.    if (!(f1 = fopen(*++argv,"r"))) {
  90.       fprintf(stderr,"ERROR:  Cannot find file %s\n",*argv);  
  91.       return !0;
  92.    }
  93.    if (argc == 3 && !(f2 = fopen(*++argv,"w"))) {
  94.       fprintf(stderr,"ERROR:  Cannot create file %s\n",*argv);  
  95.       return !0;
  96.    }
  97.  
  98.    /* End of Initialization */
  99.  
  100.    while ((c = getchr()) != EOF) {
  101.       switch (c) {
  102.       default:
  103.          string[j++] = c;
  104.          if (c != ',')
  105.             lchar = c;
  106.          break;
  107.  
  108.       case ' ':
  109.       case '\t':  
  110.          string[j] = NULL;                 /* 12/5/90 */
  111.          if (!paren)                       /* 12/5/90 */
  112.             ifnlflg = 0;                   /* 12/5/90 */
  113.          if (lookup(welse)) {              /* 12/5/90 */
  114.             if (get_nl())                  /* 12/5/90 */
  115.                goto prelse;                /* 12/5/90 */
  116.             if (peek == '{') {             /* 12/5/90 */
  117.                string[j++] = ' ';          /* 12/5/90 */
  118.                c = '{';                    /* 12/5/90 */
  119.                peek = -1;                  /* 12/5/90 */
  120.                goto brelse;                /* 12/5/90 */
  121.             }                              /* 12/5/90 */
  122.             else                           /* 12/5/90 */
  123.                goto prelse;                /* 12/5/90 */
  124.          }                                 /* 12/5/90 */
  125.          if (sflg == 0 || j > 0)
  126.             string[j++] = c;
  127.          break;
  128.  
  129.       case '\n':  
  130.          string[j] = NULL;        /* 12/5/90 */
  131.          ifnlflg = 0;             /* 12/5/90 */
  132. prelse:                           /* 12/5/90 */
  133.          if (eflg = lookup(welse) == 1)
  134.             gotelse();
  135.          put_str();
  136.          fprintf(f2,"\n");
  137.          sflg = 1;
  138.          if (eflg == 1) {  
  139.             pflg[level]++;  
  140.             tabs++; 
  141.          }
  142.          else
  143.             if (pchar == lchar)
  144.                aflg = 1;
  145.          break;
  146.  
  147.       case '{':
  148.          ifnlflg = 0;               /* 12/5/90 */
  149. brelse:                             /* 12/5/90 */
  150.          if (lookup(welse)) {       /* 12/5/90 */
  151.             gotelse();
  152.             pflg[level]++;          /* 12/5/90 */
  153.             tabs++;                 /* 12/5/90 */
  154.          }                          /* 12/5/90 */
  155.          siflev[clevel] = iflev;  
  156.          sifflg[clevel] = ifflg;
  157.          iflev = ifflg = 0;  
  158.          clevel++;
  159.          if (sflg == 1 && pflg[level] != 0) {
  160.             pflg[level]--;  
  161.             tabs--;
  162.          }
  163.          string[j++] = c;  
  164.          put_str();  
  165.          get_nl();  
  166.          put_str();
  167.          fprintf(f2,"\n");  
  168.          tabs++;  
  169.          sflg = 1;
  170.          if (pflg[level] > 0) {
  171.             ind[level] = 1;  
  172.             level++;  
  173.             slevel[level] = clevel;
  174.          }
  175.          break;
  176.  
  177.       case '}':   
  178.          clevel--;
  179.          if ((iflev = siflev[clevel]-1) < 0)
  180.             iflev = 0;
  181.          ifflg = sifflg[clevel];  
  182.          put_str();  
  183.          tabs--;  
  184.          ptabs();
  185.          if ((peek = getchr()) == ';') {
  186.             fprintf(f2,"%c;",c);  
  187.             peek = -1;
  188.          }
  189.          else
  190.             fprintf(f2,"%c",c);
  191.          get_nl();  
  192.          put_str();  
  193.          fprintf(f2,"\n");  
  194.          sflg = 1;
  195.          if (clevel < slevel[level] && level > 0)
  196.             level--;
  197.          if (ind[level] != 0) {
  198.             tabs -= pflg[level];  
  199.             pflg[level] = ind[level] = 0;
  200.          }
  201.          break;
  202.  
  203.       case '"':
  204.       case '\'':  
  205.          string[j++] = c;
  206.          while ((cc = getchr()) != c) {
  207.             string[j++] = cc;
  208.             if (cc == '\\')
  209.                string[j++] = getchr();
  210.             if (cc == '\n') { 
  211.                put_str();  
  212.                sflg = 1; 
  213.             }
  214.          }
  215.          string[j++] = cc;
  216.          if (get_nl() == 1) { 
  217.             lchar = cc;  
  218.             peek = '\n'; 
  219.          }
  220.          break;
  221.  
  222.       case ';':   
  223.          string[j++] = c;  
  224.          put_str();
  225.          if (pflg[level] > 0 && ind[level] == 0) {
  226.             tabs -= pflg[level];  
  227.             pflg[level] = 0;
  228.          }
  229.          get_nl();  
  230.          put_str();  
  231.          fprintf(f2,"\n");  
  232.          sflg = 1;
  233.          if(iflev)                  /* 12/5/90 */
  234.             if (ifflg == 1)         /* 12/5/90 */
  235.                ifflg = iflev = 0;   /* 12/5/90 */
  236.             else {                  /* 12/5/90 */
  237.                ifflg--;             /* 12/5/90 */
  238.                iflev--;             /* 12/5/90 */
  239.             }                       /* 12/5/90 */
  240.          break;
  241.  
  242.       case '\\':  
  243.          string[j++] = c;  
  244.          string[j++] = getchr();  
  245.          break;
  246.  
  247.       case '?':   
  248.          qflg = 1;  
  249.          string[j++] = c;  
  250.          break;
  251.  
  252.       case ':':   
  253.          string[j++] = c;
  254.          if (qflg == 1) { 
  255.             qflg = 0;  
  256.             break; 
  257.          }
  258.          if (!lookup(wds)) { 
  259.             sflg = 0;  
  260.             put_str(); 
  261.          }
  262.          else { 
  263.             tabs--;  
  264.             put_str();  
  265.             tabs++; 
  266.          }
  267.          if ((peek = getchr()) == ';') {
  268.             fprintf(f2,";");  
  269.             peek = -1;
  270.          }
  271.          get_nl();  
  272.          put_str();  
  273.          fprintf(f2,"\n");  
  274.          sflg = 1;
  275.          break;
  276.  
  277.       case '/':   
  278.          string[j++] = c;
  279.          if ((peek = getchr()) != '*')
  280.             break;
  281.          string[j++] = peek;  
  282.          peek = -1;  
  283.          comment();  
  284.          get_nl();                      /* 12/5/90 */
  285.          if (peek != -1)                /* 12/5/90 */
  286.             ungetc(peek, f1);           /* 12/5/90 */
  287.          put_str();                     /* 12/5/90 */
  288.          peek = '\n';                   /* 12/5/90 */
  289.          break;
  290.  
  291.       case ')':   
  292.          paren--;  
  293.          string[j++] = c;  
  294.          put_str();
  295.          if (get_nl() == 1 || (!paren && ifnlflg)) { /* 12/5/90 */
  296.             ifnlflg = 0;                             /* 12/5/90 */
  297.             if (peek != '{') {                       /* 12/5/90 */
  298.                if (peek != -1)                       /* 12/5/90 */
  299.                   ungetc(peek, f1);                  /* 12/5/90 */
  300.                peek = '\n';
  301.                if (paren != 0)
  302.                   aflg = 1;
  303.                else
  304.                   if (tabs > 0) {
  305.                      pflg[level]++;  
  306.                      tabs++;  
  307.                      ind[level] = 0;
  308.                   }
  309.             }
  310.          }
  311.          break;
  312.  
  313.       case '#':   
  314.          string[j++] = c;
  315.          while ((cc = getchr()) != '\n')
  316.             string[j++] = cc;
  317.          string[j++] = cc;  
  318.          sflg = 0;  
  319.          put_str();  
  320.          sflg = 1;
  321.          break;
  322.  
  323.       case '(':   
  324.          string[j++] = c;  
  325.          paren++;
  326.          if (lookup(wfor) == 1) {
  327.             while ((c = get_str()) != ';');
  328.             ct = 0;
  329. cont:                       
  330.             while ((c = get_str()) != ')')
  331.                if (c == '(')
  332.                   ct++;
  333.             if (ct != 0) { 
  334.                ct--;  
  335.                goto cont; 
  336.             }
  337.             paren--;  
  338.             put_str();
  339.             if (get_nl() == 1 || !paren)
  340.                if (peek != '{') {
  341.                   if (peek != -1)
  342.                      ungetc(peek, f1);
  343.                   peek = '\n';  
  344.                   pflg[level]++;
  345.                   tabs++;  
  346.                   ind[level] = 0;
  347.                }
  348.             break;
  349.          }
  350.          if (lookup(wif) == 1) {
  351.             ifnlflg = 1;    /* 12/5/90 */
  352.             put_str();
  353.             stabs[clevel][iflev] = tabs;
  354.             spflg[clevel][iflev] = pflg[level];
  355.             sind[clevel][iflev] = ind[level];
  356.             iflev++;  
  357.             ifflg++;        /* 12/5/90 */
  358.          }
  359.       }
  360.    }
  361.    if (f2 != stdout && (ferror(f2) || fclose(f2))) {
  362.       fprintf(stderr,"ERROR:  Disk full\n");  
  363.       return !0;
  364.    }
  365.    fclose(f1);  
  366.    return 0;
  367.  
  368. }
  369.  
  370. /*************************************************************************/
  371.  
  372. void ptabs()
  373. {
  374.  
  375.    int i;
  376.  
  377.    for (i=0; i < tabs; i++)
  378.       fprintf(f2,"\t");
  379.  
  380. }
  381.  
  382. /*************************************************************************/
  383.  
  384. int getchr()
  385. {
  386.  
  387.    if (peek < 0 && lastchar != ' ' && lastchar != '\t')
  388.       pchar = lastchar;
  389.    lastchar = (peek < 0) ? getc(f1) : peek;  
  390.    peek = -1;
  391.    return lastchar;
  392.  
  393. }
  394.  
  395. /*************************************************************************/
  396.  
  397. void put_str()
  398. {
  399.  
  400.    if (j > 0) {
  401.       if (sflg != 0) {
  402.          ptabs();  
  403.          sflg = 0;
  404.          if (aflg == 1) {
  405.             aflg = 0;
  406.             if (tabs > 0)
  407.                fprintf(f2,"    ");
  408.          }
  409.       }
  410.       string[j] = NULL;  
  411.       fprintf(f2,"%s",string);  
  412.       j = 0;
  413.    }
  414.    else
  415.       if (sflg != 0) { 
  416.          sflg = 0;  
  417.          aflg = 0; 
  418.       }
  419.  
  420. }
  421.  
  422. /*************************************************************************/
  423.  
  424. int lookup(tab)
  425.  
  426. char *tab[];
  427.  
  428. {
  429.    char r;
  430.    int i,kk,k,l;
  431.  
  432.    if (j < 1)
  433.       return 0;
  434.    for (kk = 0; string[kk] == ' '; ++kk)
  435.       ;
  436.    for (i = 0; tab[i] != 0; i++) {
  437.       l = 0;
  438.       for (k=kk; (r = tab[i][l++]) == string[k] && r != NULL; ++k)
  439.          ;
  440.       if (r == NULL &&                /* 12/5/90 */
  441.       (isspace(string[k]) || ispunct(string[k]) || string[k] == NULL))
  442.          return 1;
  443.    }
  444.    return 0;
  445.  
  446. }
  447.  
  448. /*************************************************************************/
  449.  
  450. int get_str()
  451. {
  452.  
  453.    char ch;
  454.  
  455. beg:
  456.    if ((ch = string[j++] = getchr()) == '\\') {
  457.       string[j++] = getchr();  
  458.       goto beg;
  459.    }
  460.    if (ch == '\'' || ch == '"') {
  461.       while ((cc = string[j++] = getchr()) != ch)
  462.          if (cc == '\\')
  463.             string[j++] = getchr();
  464.       goto beg;
  465.    }
  466.    if (ch == '\n') { 
  467.       put_str();  
  468.       aflg = 1;  
  469.       goto beg; 
  470.    }
  471.    else
  472.       return ch;
  473.  
  474. }
  475.  
  476. /*************************************************************************/
  477.  
  478. void gotelse()
  479. {
  480.  
  481.    tabs = stabs[clevel][iflev];  
  482.    pflg[level] = spflg[clevel][iflev];
  483.    ind[level] = sind[clevel][iflev];  
  484.    ifflg++;               /* 12/5/90 */
  485.  
  486. }
  487.  
  488. /*************************************************************************/
  489.  
  490. int get_nl()
  491. {
  492.  
  493.    while ((peek = getchr()) == '\t' || peek == ' ') {
  494.       string[j++] = peek;  
  495.       peek = -1;
  496.    }
  497.    if ((peek = getchr()) == '/') {
  498.       peek = -1;
  499.       if ((peek = getchr()) == '*') {
  500.          string[j++] = '/';  
  501.          string[j++] = '*';
  502.          peek = -1;  
  503.          comment();
  504.       }
  505.       else
  506.          string[j++] = '/';
  507.    }
  508.    if ((peek = getchr()) == '\n') { 
  509.       peek = -1;  
  510.       return 1; 
  511.    }
  512.    return 0;
  513.  
  514. }
  515.  
  516. /*************************************************************************/
  517.  
  518. void comment()
  519. {
  520.  
  521. rep:
  522.    while ((c = string[j++] = getchr()) != '*')
  523.       if (c == '\n') { 
  524.          put_str();  
  525.          sflg = 1; 
  526.       }
  527. gotstar:
  528.    if ((c = string[j++] = getchr()) != '/') {
  529.       if (c == '*')
  530.          goto gotstar;
  531.       goto rep;
  532.    }
  533.  
  534. }
  535.  
  536. /*************************************************************************/
  537.