home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / c / ppc.arc / PPC.C next >
C/C++ Source or Header  |  1988-09-17  |  16KB  |  559 lines

  1. /* PPC.C - Pretty Printer for C
  2.    Created from CB on SIMTEL20 by Richard Conn
  3.    CB was heavily modified to create PPC */
  4.  
  5. #include <stdio.h>
  6.  
  7. #define TITLE "Pretty Printer for C, Beta Test Version 1.0"
  8. #define MAXBRAC 20    /* maximum number of open braces allowed */
  9. #define IFLEVEL 20    /* maximum number of nested IFs allowed */
  10.  
  11. int slevel[IFLEVEL];
  12. int spflg[MAXBRAC][IFLEVEL];
  13. int sind [MAXBRAC][IFLEVEL];
  14. int siflev[IFLEVEL];
  15. int sifflg[IFLEVEL];
  16. int clevel = 0; /* Number of open braces */
  17. int iflev = 0; /* Number of active IFs */
  18. int ifflg = -1; /* Indicates if we have an active IF */
  19. int level = 0;
  20. int ind[IFLEVEL]; /* Indentation amount for a particular IF */
  21. int pflg[IFLEVEL]; /* Number of characters to indent for a particular IF */
  22. int eflg = 0; /* We are in an ELSE? */
  23. int paren = 0; /* Number of open parentheses */
  24. int tabcount = 4; /* Number of characters to indent */
  25. char lchar;
  26. char pchar;
  27. int aflg = 0;
  28. int stabs[MAXBRAC][IFLEVEL];
  29. int qflg = 0;
  30.  
  31. /* The following are reserved words used for special processing */
  32. char *wstr[] = {
  33.     "typedef",
  34.     "struct",
  35.     "union",
  36.     "int",
  37.     "char",
  38.     "unsigned",
  39.     "long",
  40.     "auto",
  41.     NULL
  42. };
  43. char *wrsvwds[] = {
  44.     "int",
  45.     "char",
  46.     "unsigned",
  47.     "long",
  48.     "auto",
  49.     NULL
  50. };
  51. char *wif[] = {
  52.     "if",
  53.     NULL
  54. };
  55. char *welse[] = {
  56.     "else",
  57.     NULL
  58. };
  59. char *wfor[] = {
  60.     "for",
  61.     NULL
  62. };
  63. char *wds[] = {
  64.     "case",
  65.     "default",
  66.     NULL
  67. };
  68.  
  69. /* J is the index for the next character in the STRING buffer
  70.    STRING is the buffer in which the output line is built */
  71. int j = 0;
  72. char string[400];
  73.  
  74. char cc;
  75. int sflg = 1;
  76. int bflg = 0;
  77. int peek = -1;
  78. int tabs = 0;
  79. int lastchar = ' ';
  80. int cin;
  81.  
  82. /* Input and output buffers */
  83. FILE *inpbuf;
  84. FILE *outbuf;
  85.  
  86. main(argc, argv)
  87. int argc;
  88. char *argv[];
  89. {
  90.     char bakfil[100]; /* name of current backup file */
  91.     int filno; /* number of current file */
  92.     int cont; /* local continuation flag */
  93.     int ct; /* count of local open parens */
  94.     int eflg; /* indicates we are in an ELSE */
  95.     int i;
  96.  
  97.     if (argc == 1) {
  98.         printf ("%s\n", TITLE);
  99.         printf ("  Syntax: ppc [-i#] filename.ext [filename.ext ...]\n");
  100.         printf ("  Options:\n");
  101.         printf ("     -i#  Set indentation level for files\n");
  102.         exit (0);
  103.     }
  104.  
  105.     /* Zero indentation indicator and indent character count buffers */
  106.     for (i=0; i<IFLEVEL; i++) { 
  107.         ind[i] = 0; 
  108.         pflg[i] = 0; 
  109.     }
  110.  
  111.     /* Main Loop */
  112.     for (filno=1; argv[filno]!=NULL; filno++) {
  113.  
  114.         /* Process next file (if not an option) */
  115.         if (*argv[filno] != '-') {
  116.             mkext (bakfil, argv[filno], "bak");
  117.             unlink (bakfil);
  118.             rename (argv[filno], bakfil);
  119.             if ((inpbuf = fopen (bakfil, "r")) == NULL) {
  120.                 perror (bakfil);
  121.                 exit (1);
  122.             }
  123.             if ((outbuf = fopen (argv[filno], "w")) == NULL) {
  124.                 perror (argv[filno]);
  125.                 exit (1);
  126.             }
  127.             fprintf (stderr, "  Pretty Printing %s\n", argv[filno]);
  128.             while ( (cin = getchr()) != EOF) {
  129.                 switch(cin) {
  130.                 case ' ':
  131.                 case '\t':
  132.                     if (lookup(welse) == 1) {
  133.                         gotelse ();
  134.                         if (sflg == 0 || j > 0) string[j++] =cin;
  135.                         putz ();
  136.                         sflg = 0;
  137.                         break;
  138.                     }
  139.                     if (sflg == 0 || j > 0) string[j++] =cin;
  140.                     break;
  141.                 case '\n':
  142.                     if ((eflg = lookup(welse)) == 1) gotelse();
  143.                     putz();
  144.                     fprintf (outbuf,"\n");
  145.                     sflg = 1;
  146.                     if (eflg == 1) {
  147.                         pflg[level]++;
  148.                         tabs++;
  149.                     }
  150.                     else
  151.                         if (pchar == lchar)
  152.                             aflg = 1;
  153.                     break;
  154.                 case '{':
  155.                     if (lookup(welse) == 1) gotelse();
  156.                     siflev[clevel]= iflev;
  157.                     sifflg[clevel]= ifflg;
  158.                     iflev = ifflg = 0;
  159.                     clevel++;
  160.                     if (sflg == 1 && pflg[level] != 0) {
  161.                         pflg[level]--;
  162.                         tabs--;
  163.                     }
  164.                     string[j++] =cin;
  165.                     putz ();
  166.                     getnl ();
  167.                     putz ();
  168.                     fprintf (outbuf,"\n");
  169.                     tabs++;
  170.                     sflg = 1;
  171.                     if (pflg[level] > 0) {
  172.                         ind[level] = 1;
  173.                         level++;
  174.                         slevel[level] = clevel;
  175.                     }
  176.                     break;
  177.                 case '}':
  178.                     clevel--;
  179.                     if ((iflev = siflev[clevel]-1) < 0) iflev = 0;
  180.                     ifflg = sifflg[clevel];
  181.                     putz ();
  182.                     tabs--;
  183.                     ptabs ();
  184.                     if ((peek = getchr()) == ';') {
  185.                         fprintf (outbuf, "%c;", cin);
  186.                         peek = -1;
  187.                     }
  188.                     else fprintf (outbuf,"%c", cin);
  189.                     getnl ();
  190.                     putz ();
  191.                     fprintf (outbuf,"\n");
  192.                     sflg = 1;
  193.                     if (clevel < slevel[level]) if (level > 0) level--;
  194.                     if (ind[level] != 0) {
  195.                         tabs -= pflg[level];
  196.                         pflg[level] =0;
  197.                         ind[level] = 0;
  198.                     }
  199.                     break;
  200.                 case '"':
  201.                 case '\'':
  202.                     string[j++] =cin;
  203.                     while ((cc = getc(inpbuf)) !=cin) {
  204.                         string[j++] =cc;
  205.                         if (cc == '\\') string[j++] = getc(inpbuf);
  206.                         if (cc == '\n') {
  207.                             putz();
  208.                             sflg = 1;
  209.                         }
  210.                     }
  211.                     string[j++] =cc;
  212.                     if (getnl() ==1) {
  213.                         lchar = cc;
  214.                         peek = '\n';
  215.                     }
  216.                     break;
  217.                 case ';':
  218.                     string[j++] =cin;
  219.                     putz ();
  220.                     if (pflg[level] > 0 && ind[level] == 0) {
  221.                         tabs -= pflg[level];
  222.                         pflg[level] = 0;
  223.                     }
  224.                     getnl ();
  225.                     putz ();
  226.                     fprintf (outbuf,"\n");
  227.                     sflg = 1;
  228.                     if (iflev > 0)
  229.                         if (ifflg == 1) {
  230.                             iflev--;
  231.                             ifflg = 0;
  232.                         }
  233.                         else iflev = 0;
  234.                     break;
  235.                 case '\\':
  236.                     string[j++] =cin;
  237.                     string[j++] =getchr();
  238.                     break;
  239.                 case '?':
  240.                     qflg = 1;
  241.                     string[j++] =cin;
  242.                     break;
  243.                 case ':':
  244.                     string[j++] =cin;
  245.                     if (qflg == 1) {
  246.                         qflg = 0;
  247.                         break;
  248.                     }
  249.                     if (lookup(wrsvwds) == 1) break;
  250.                     if (lookup(wds)== 0) {
  251.                         sflg = 0;
  252.                         putz ();
  253.                     }
  254.                     else {
  255.                         tabs--;
  256.                         putz ();
  257.                         tabs++;
  258.                     }
  259.                     if ((peek = getchr()) == ';') {
  260.                         fprintf (outbuf, ";");
  261.                         peek = -1;
  262.                     }
  263.                     getnl ();
  264.                     putz ();
  265.                     fprintf (outbuf,"\n");
  266.                     sflg = 1;
  267.                     break;
  268.                 case '/':
  269.                     string[j++] =cin;
  270.                     if ((peek = getchr()) != '*') break;
  271.                     string[j++] = peek;
  272.                     peek = -1;
  273.                     comment ();
  274.                     break;
  275.                 case ')':
  276.                     paren--;
  277.                     string[j++] = cin;
  278.                     putz ();
  279.                     if (getnl() == 1) {
  280.                         peek = '\n';
  281.                         if (paren != 0) aflg = 1;
  282.                         else if (tabs > 0) {
  283.                             pflg[level]++;
  284.                             tabs++;
  285.                             ind[level] = 0;
  286.                         }
  287.                     }
  288.                     break;
  289.                 case '#':
  290.                     string[j++] =cin;
  291.                     while ((cc = getc(inpbuf)) != '\n') string[j++] = cc;
  292.                     string[j++] =cc;
  293.                     sflg = 0;
  294.                     putz ();
  295.                     sflg = 1;
  296.                     break;
  297.                 case '(':
  298.                     string[j++] =cin;
  299.                     paren++;
  300.                     if (lookup(wfor) == 1) {
  301.                         while ((cin = xgets()) != ';');
  302.                         ct = 0;
  303.                         cont = 1;
  304.                         while (cont) {
  305.                             while ((cin = xgets()) != ')') {
  306.                                 if (cin== '(') ct++;
  307.                             }
  308.                             if(ct != 0) {
  309.                                 ct--;
  310.                             }
  311.                             else cont = 0;
  312.                         }
  313.                         paren--;
  314.                         putz ();
  315.                         if (getnl() ==1) {
  316.                             peek = '\n';
  317.                             pflg[level]++;
  318.                             tabs++;
  319.                             ind[level] = 0;
  320.                         }
  321.                         break;
  322.                     }
  323.                     if (lookup(wif)== 1) {
  324.                         putz ();
  325.                         stabs[clevel][iflev] = tabs;
  326.                         spflg[clevel][iflev] = pflg[level];
  327.                         sind[clevel][iflev] = ind[level];
  328.                         iflev++;
  329.                         ifflg = 1;
  330.                     }
  331.                     break;
  332.                 default:
  333.                     string[j++] = cin;
  334.                     if (cin != ',') lchar = cin;
  335.                     break;
  336.                 }
  337.             }
  338.             fclose (inpbuf);
  339.             fclose (outbuf);
  340.         }
  341.         /* Process an option */
  342.         else {
  343.             option (&argv[filno][1]);
  344.         }
  345.     }
  346. }
  347.  
  348. /* Process an option on the command line */
  349. option (item)
  350. char *item;
  351. {
  352.     switch (*item) {
  353.     case 'i' :
  354.     case 'I' :
  355.         tabcount = atoi (++item);
  356.         break;
  357.     default :
  358.         fprintf (stderr, "Invalid option in command line: %s\n", item);
  359.         break;
  360.     }
  361. }
  362.  
  363. /*  Output leading indentation characters on the line */
  364. ptabs()
  365. {
  366.     int i, k;
  367.  
  368.     for (i = 0; i < tabs; i++) { 
  369.         for (k = 0; k<tabcount; k++)
  370.             fprintf (outbuf, " "); 
  371.     }
  372. }
  373.  
  374. /* Return the next non-space or non-tab character and set PEEK to -1
  375.    and PCHAR to LASTCHAR as side effects */
  376. getchr()
  377. {
  378.     if (peek < 0 && lastchar != ' ' && lastchar != '\t') pchar = lastchar;
  379.     if (peek == '\t') peek = ' ';
  380.     if (peek == ' ' && peek == lastchar) {
  381.         peek = -1;
  382.     }
  383.     while (peek < 0) {
  384.         peek = getc (inpbuf);
  385.         if (peek == EOF) break;
  386.         if (peek == '\t') peek = ' ';
  387.         if (peek == ' ' && peek == lastchar) peek = -1;
  388.     }
  389.     lastchar = peek;
  390.     peek = -1;
  391.     return (lastchar);
  392. }
  393.  
  394. /* If the STRING buffer is not empty (J>0), output indentation tabs
  395.    and the STRING buffer after appending a null to the STRING buffer
  396.    and reset the STRING buffer to empty */
  397. putz()
  398. {
  399.     int k;
  400.  
  401.     if (j > 0) {
  402.         if (sflg != 0) {
  403.             ptabs();
  404.             sflg = 0;
  405.             if (aflg == 1) {
  406.                 aflg = 0;
  407.                 if (tabs > 0) {
  408.                     for (k = 0; k<tabcount; k++) fprintf (outbuf, " "); 
  409.                 }
  410.             }
  411.         }
  412.         string[j] = '\0';
  413.         fprintf (outbuf, "%s", string);
  414.         j = 0;
  415.     }
  416.     else {
  417.         if (sflg != 0) {
  418.             sflg = 0;
  419.             aflg = 0;
  420.         }
  421.     }
  422. }
  423.  
  424. /* Return 1 if the first non-blank token in STRING is an element of
  425.    the passed table */
  426. lookup(tab)
  427. char *tab[];
  428. {
  429.     char r;
  430.     int l, kk, k, i;
  431.  
  432.     if (j < 1) return(0);
  433.     kk = 0;
  434.     while (string[kk] == ' ') kk++;
  435.     for (i = 0; tab[i] != NULL; i++) {
  436.         l = 0;
  437.         for (k = kk; (r= tab[i][l++]) == string[k] && r !='\0'; k++);
  438.         if (r == '\0' && (string[k] < 'a' || string[k] > 'z')) return(1);
  439.     }
  440.     return(0);
  441. }
  442.  
  443. /* Return next character which is not an escaped character (leading
  444.    back slash), a character constant, a string constant, or a new
  445.    line (building the STRING buffer as we encounter these other items) */
  446. xgets()
  447. {
  448.     int ch;
  449.  
  450.     while (1) {
  451.         if ((ch = string[j++]= getchr()) == '\\') {
  452.             string[j++] = getchr();
  453.         }
  454.         else {
  455.             if (ch == '\'' || ch == '"') {
  456.                 while ((cc = string[j++] = getchr()) != ch) {
  457.                     if (cc == '\\') string[j++] = getchr();
  458.                 }
  459.             }
  460.             else {
  461.                 if (ch == '\n') {
  462.                     putz ();
  463.                     aflg = 1;
  464.                 }
  465.                 else return(ch);
  466.             }
  467.         }
  468.     }
  469. }
  470.  
  471. /* We got an ELSE clause, so process if levels et al */
  472. gotelse()
  473. {
  474.     tabs = stabs[clevel][iflev];
  475.     pflg[level] = spflg[clevel][iflev];
  476.     ind[level] = sind[clevel][iflev];
  477.     ifflg = 1;
  478. }
  479.  
  480. /* Skip to next non-space, non-tab, or non-comment character, returning
  481.    1 if that character is a new line and 0 otherwise */
  482. getnl()
  483. {
  484.     while ((peek = getchr()) == '\t' || peek == ' ') {
  485.         string[j++] = peek;
  486.         peek = -1;
  487.     }
  488.     if ((peek = getchr()) == '/') {
  489.         peek = -1;
  490.         if ((peek = getchr()) == '*') {
  491.             string[j++] ='/';
  492.             string[j++] ='*';
  493.             peek = -1;
  494.             comment();
  495.         }
  496.         else string[j++] = '/';
  497.     }
  498.     if ((peek = getchr()) == '\n') {
  499.         peek = -1;
  500.         return (1);
  501.     }
  502.     return (0);
  503. }
  504.  
  505. /* Process comment, copying it into the output STRING buffer and allowing
  506.    for nested comments */
  507. comment()
  508. {
  509.     int repeat;
  510.     int gotstar;
  511.  
  512.     repeat = 1;
  513.     while (repeat) {
  514.         while ((cin = string[j++] = getc(inpbuf)) != '*') {
  515.             if (cin== '\n') {
  516.                 putz();
  517.                 sflg = 1;
  518.             }
  519.         }
  520.  
  521.         /* We got an asterisk */
  522.         if (string[j-2]=='/') {
  523.             fprintf (stderr, "Input has nested comments\n");
  524.             comment ();
  525.         }
  526.         else {
  527.             gotstar = 1;
  528.             while (gotstar)
  529.                 if ((cin = string[j++] = getc(inpbuf)) != '*') gotstar = 0;
  530.             if (cin == '/') repeat = 0;
  531.             if (cin == '\n') { 
  532.                 putz (); 
  533.                 sflg = 1; 
  534.             }
  535.         }
  536.     }
  537. }
  538.  
  539. /* Build a new file name string (NEW) given the first part of an old
  540.    file name string (OLD) and an extension (EXT) to be placed at the end of
  541.    the new file name string */
  542. mkext(new, old, ext)
  543. char *new;
  544. char *old;
  545. char *ext;
  546. {
  547.     /* copy file name */
  548.     while ((*old!='\0')&&(*old!='.')) *new++ = *old++;
  549.  
  550.     /* add a dot for the extension */
  551.     *new++ = '.';
  552.  
  553.     /* copy extension */
  554.     while (*ext!='\0') *new++ = *ext++;
  555.  
  556.     /* add string terminator */
  557.     *new = '\0';
  558. }
  559.