home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
c
/
ppc.arc
/
PPC.C
next >
Wrap
C/C++ Source or Header
|
1988-09-17
|
16KB
|
559 lines
/* PPC.C - Pretty Printer for C
Created from CB on SIMTEL20 by Richard Conn
CB was heavily modified to create PPC */
#include <stdio.h>
#define TITLE "Pretty Printer for C, Beta Test Version 1.0"
#define MAXBRAC 20 /* maximum number of open braces allowed */
#define IFLEVEL 20 /* maximum number of nested IFs allowed */
int slevel[IFLEVEL];
int spflg[MAXBRAC][IFLEVEL];
int sind [MAXBRAC][IFLEVEL];
int siflev[IFLEVEL];
int sifflg[IFLEVEL];
int clevel = 0; /* Number of open braces */
int iflev = 0; /* Number of active IFs */
int ifflg = -1; /* Indicates if we have an active IF */
int level = 0;
int ind[IFLEVEL]; /* Indentation amount for a particular IF */
int pflg[IFLEVEL]; /* Number of characters to indent for a particular IF */
int eflg = 0; /* We are in an ELSE? */
int paren = 0; /* Number of open parentheses */
int tabcount = 4; /* Number of characters to indent */
char lchar;
char pchar;
int aflg = 0;
int stabs[MAXBRAC][IFLEVEL];
int qflg = 0;
/* The following are reserved words used for special processing */
char *wstr[] = {
"typedef",
"struct",
"union",
"int",
"char",
"unsigned",
"long",
"auto",
NULL
};
char *wrsvwds[] = {
"int",
"char",
"unsigned",
"long",
"auto",
NULL
};
char *wif[] = {
"if",
NULL
};
char *welse[] = {
"else",
NULL
};
char *wfor[] = {
"for",
NULL
};
char *wds[] = {
"case",
"default",
NULL
};
/* J is the index for the next character in the STRING buffer
STRING is the buffer in which the output line is built */
int j = 0;
char string[400];
char cc;
int sflg = 1;
int bflg = 0;
int peek = -1;
int tabs = 0;
int lastchar = ' ';
int cin;
/* Input and output buffers */
FILE *inpbuf;
FILE *outbuf;
main(argc, argv)
int argc;
char *argv[];
{
char bakfil[100]; /* name of current backup file */
int filno; /* number of current file */
int cont; /* local continuation flag */
int ct; /* count of local open parens */
int eflg; /* indicates we are in an ELSE */
int i;
if (argc == 1) {
printf ("%s\n", TITLE);
printf (" Syntax: ppc [-i#] filename.ext [filename.ext ...]\n");
printf (" Options:\n");
printf (" -i# Set indentation level for files\n");
exit (0);
}
/* Zero indentation indicator and indent character count buffers */
for (i=0; i<IFLEVEL; i++) {
ind[i] = 0;
pflg[i] = 0;
}
/* Main Loop */
for (filno=1; argv[filno]!=NULL; filno++) {
/* Process next file (if not an option) */
if (*argv[filno] != '-') {
mkext (bakfil, argv[filno], "bak");
unlink (bakfil);
rename (argv[filno], bakfil);
if ((inpbuf = fopen (bakfil, "r")) == NULL) {
perror (bakfil);
exit (1);
}
if ((outbuf = fopen (argv[filno], "w")) == NULL) {
perror (argv[filno]);
exit (1);
}
fprintf (stderr, " Pretty Printing %s\n", argv[filno]);
while ( (cin = getchr()) != EOF) {
switch(cin) {
case ' ':
case '\t':
if (lookup(welse) == 1) {
gotelse ();
if (sflg == 0 || j > 0) string[j++] =cin;
putz ();
sflg = 0;
break;
}
if (sflg == 0 || j > 0) string[j++] =cin;
break;
case '\n':
if ((eflg = lookup(welse)) == 1) gotelse();
putz();
fprintf (outbuf,"\n");
sflg = 1;
if (eflg == 1) {
pflg[level]++;
tabs++;
}
else
if (pchar == lchar)
aflg = 1;
break;
case '{':
if (lookup(welse) == 1) gotelse();
siflev[clevel]= iflev;
sifflg[clevel]= ifflg;
iflev = ifflg = 0;
clevel++;
if (sflg == 1 && pflg[level] != 0) {
pflg[level]--;
tabs--;
}
string[j++] =cin;
putz ();
getnl ();
putz ();
fprintf (outbuf,"\n");
tabs++;
sflg = 1;
if (pflg[level] > 0) {
ind[level] = 1;
level++;
slevel[level] = clevel;
}
break;
case '}':
clevel--;
if ((iflev = siflev[clevel]-1) < 0) iflev = 0;
ifflg = sifflg[clevel];
putz ();
tabs--;
ptabs ();
if ((peek = getchr()) == ';') {
fprintf (outbuf, "%c;", cin);
peek = -1;
}
else fprintf (outbuf,"%c", cin);
getnl ();
putz ();
fprintf (outbuf,"\n");
sflg = 1;
if (clevel < slevel[level]) if (level > 0) level--;
if (ind[level] != 0) {
tabs -= pflg[level];
pflg[level] =0;
ind[level] = 0;
}
break;
case '"':
case '\'':
string[j++] =cin;
while ((cc = getc(inpbuf)) !=cin) {
string[j++] =cc;
if (cc == '\\') string[j++] = getc(inpbuf);
if (cc == '\n') {
putz();
sflg = 1;
}
}
string[j++] =cc;
if (getnl() ==1) {
lchar = cc;
peek = '\n';
}
break;
case ';':
string[j++] =cin;
putz ();
if (pflg[level] > 0 && ind[level] == 0) {
tabs -= pflg[level];
pflg[level] = 0;
}
getnl ();
putz ();
fprintf (outbuf,"\n");
sflg = 1;
if (iflev > 0)
if (ifflg == 1) {
iflev--;
ifflg = 0;
}
else iflev = 0;
break;
case '\\':
string[j++] =cin;
string[j++] =getchr();
break;
case '?':
qflg = 1;
string[j++] =cin;
break;
case ':':
string[j++] =cin;
if (qflg == 1) {
qflg = 0;
break;
}
if (lookup(wrsvwds) == 1) break;
if (lookup(wds)== 0) {
sflg = 0;
putz ();
}
else {
tabs--;
putz ();
tabs++;
}
if ((peek = getchr()) == ';') {
fprintf (outbuf, ";");
peek = -1;
}
getnl ();
putz ();
fprintf (outbuf,"\n");
sflg = 1;
break;
case '/':
string[j++] =cin;
if ((peek = getchr()) != '*') break;
string[j++] = peek;
peek = -1;
comment ();
break;
case ')':
paren--;
string[j++] = cin;
putz ();
if (getnl() == 1) {
peek = '\n';
if (paren != 0) aflg = 1;
else if (tabs > 0) {
pflg[level]++;
tabs++;
ind[level] = 0;
}
}
break;
case '#':
string[j++] =cin;
while ((cc = getc(inpbuf)) != '\n') string[j++] = cc;
string[j++] =cc;
sflg = 0;
putz ();
sflg = 1;
break;
case '(':
string[j++] =cin;
paren++;
if (lookup(wfor) == 1) {
while ((cin = xgets()) != ';');
ct = 0;
cont = 1;
while (cont) {
while ((cin = xgets()) != ')') {
if (cin== '(') ct++;
}
if(ct != 0) {
ct--;
}
else cont = 0;
}
paren--;
putz ();
if (getnl() ==1) {
peek = '\n';
pflg[level]++;
tabs++;
ind[level] = 0;
}
break;
}
if (lookup(wif)== 1) {
putz ();
stabs[clevel][iflev] = tabs;
spflg[clevel][iflev] = pflg[level];
sind[clevel][iflev] = ind[level];
iflev++;
ifflg = 1;
}
break;
default:
string[j++] = cin;
if (cin != ',') lchar = cin;
break;
}
}
fclose (inpbuf);
fclose (outbuf);
}
/* Process an option */
else {
option (&argv[filno][1]);
}
}
}
/* Process an option on the command line */
option (item)
char *item;
{
switch (*item) {
case 'i' :
case 'I' :
tabcount = atoi (++item);
break;
default :
fprintf (stderr, "Invalid option in command line: %s\n", item);
break;
}
}
/* Output leading indentation characters on the line */
ptabs()
{
int i, k;
for (i = 0; i < tabs; i++) {
for (k = 0; k<tabcount; k++)
fprintf (outbuf, " ");
}
}
/* Return the next non-space or non-tab character and set PEEK to -1
and PCHAR to LASTCHAR as side effects */
getchr()
{
if (peek < 0 && lastchar != ' ' && lastchar != '\t') pchar = lastchar;
if (peek == '\t') peek = ' ';
if (peek == ' ' && peek == lastchar) {
peek = -1;
}
while (peek < 0) {
peek = getc (inpbuf);
if (peek == EOF) break;
if (peek == '\t') peek = ' ';
if (peek == ' ' && peek == lastchar) peek = -1;
}
lastchar = peek;
peek = -1;
return (lastchar);
}
/* If the STRING buffer is not empty (J>0), output indentation tabs
and the STRING buffer after appending a null to the STRING buffer
and reset the STRING buffer to empty */
putz()
{
int k;
if (j > 0) {
if (sflg != 0) {
ptabs();
sflg = 0;
if (aflg == 1) {
aflg = 0;
if (tabs > 0) {
for (k = 0; k<tabcount; k++) fprintf (outbuf, " ");
}
}
}
string[j] = '\0';
fprintf (outbuf, "%s", string);
j = 0;
}
else {
if (sflg != 0) {
sflg = 0;
aflg = 0;
}
}
}
/* Return 1 if the first non-blank token in STRING is an element of
the passed table */
lookup(tab)
char *tab[];
{
char r;
int l, kk, k, i;
if (j < 1) return(0);
kk = 0;
while (string[kk] == ' ') kk++;
for (i = 0; tab[i] != NULL; i++) {
l = 0;
for (k = kk; (r= tab[i][l++]) == string[k] && r !='\0'; k++);
if (r == '\0' && (string[k] < 'a' || string[k] > 'z')) return(1);
}
return(0);
}
/* Return next character which is not an escaped character (leading
back slash), a character constant, a string constant, or a new
line (building the STRING buffer as we encounter these other items) */
xgets()
{
int ch;
while (1) {
if ((ch = string[j++]= getchr()) == '\\') {
string[j++] = getchr();
}
else {
if (ch == '\'' || ch == '"') {
while ((cc = string[j++] = getchr()) != ch) {
if (cc == '\\') string[j++] = getchr();
}
}
else {
if (ch == '\n') {
putz ();
aflg = 1;
}
else return(ch);
}
}
}
}
/* We got an ELSE clause, so process if levels et al */
gotelse()
{
tabs = stabs[clevel][iflev];
pflg[level] = spflg[clevel][iflev];
ind[level] = sind[clevel][iflev];
ifflg = 1;
}
/* Skip to next non-space, non-tab, or non-comment character, returning
1 if that character is a new line and 0 otherwise */
getnl()
{
while ((peek = getchr()) == '\t' || peek == ' ') {
string[j++] = peek;
peek = -1;
}
if ((peek = getchr()) == '/') {
peek = -1;
if ((peek = getchr()) == '*') {
string[j++] ='/';
string[j++] ='*';
peek = -1;
comment();
}
else string[j++] = '/';
}
if ((peek = getchr()) == '\n') {
peek = -1;
return (1);
}
return (0);
}
/* Process comment, copying it into the output STRING buffer and allowing
for nested comments */
comment()
{
int repeat;
int gotstar;
repeat = 1;
while (repeat) {
while ((cin = string[j++] = getc(inpbuf)) != '*') {
if (cin== '\n') {
putz();
sflg = 1;
}
}
/* We got an asterisk */
if (string[j-2]=='/') {
fprintf (stderr, "Input has nested comments\n");
comment ();
}
else {
gotstar = 1;
while (gotstar)
if ((cin = string[j++] = getc(inpbuf)) != '*') gotstar = 0;
if (cin == '/') repeat = 0;
if (cin == '\n') {
putz ();
sflg = 1;
}
}
}
}
/* Build a new file name string (NEW) given the first part of an old
file name string (OLD) and an extension (EXT) to be placed at the end of
the new file name string */
mkext(new, old, ext)
char *new;
char *old;
char *ext;
{
/* copy file name */
while ((*old!='\0')&&(*old!='.')) *new++ = *old++;
/* add a dot for the extension */
*new++ = '.';
/* copy extension */
while (*ext!='\0') *new++ = *ext++;
/* add string terminator */
*new = '\0';
}