home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
213_01
/
cbprepr.c
< prev
next >
Wrap
Text File
|
1979-12-31
|
19KB
|
920 lines
/* CBPREPR.C VERS:- 01.00 DATE:- 09/26/86 TIME:- 09:36:05 PM */
/*
%CC1 $1.C -O -X -E6000
%CLINK $1 DIO -S -E6000
%DELETE $1.CRL
*/
/*
Description:
Filter to prepare C code for formatting:
add and delete white space to produce consistent text;
introduce newlines to produce one statment per line;
left justify all lines.
DIO redirection.
To indent according to control level, output from CBPREP
must be filtered by CB, the formatting program written
by W.C. Colley and R. Hollinbeck and based on a unix utility.
CBPREP uses the routines getch() and comment() of CB.
By J.A. Rupley, Tucson, Arizona
Coded for BDS C compiler, version 1.50a
*/
#include "bdscio.h"
#include "dio.h"
/*debug*/
/*
#define DEBUG
*/
int j;
int cc;
int peek;
int sflag;
int expr_flag;
int lastchar;
int c;
int control_keys, else_key, do_key, case_key, default_key, flow_keys;
int typedef_key, struct_key, union_key, c_keys, keys_total;
int close_loc, paren_count, ctrl_count, last_count, last_key;
char string[200];
char *keyword[30];
main(argc, argv)
int argc;
char *argv[];
{
int k;
int count;
dioinit(&argc, argv);
/*exit if improper command line parameters*/
if (!_dioinflg)
use_mess();
/*set up pointers to keyword strings*/
init_key();
close_loc = paren_count = ctrl_count = last_count = 0;
last_key = keys_total + 1;
expr_flag = 0;
sflag = 0;
peek = -1;
j = 0;
/* Start of text manipulation. */
while (((c = getchr()) != EOF) && (c != CPMEOF))
{
/*at terminators reset control values*/
if (c == '}' || c == '{' || c == ':')
paren_count = ctrl_count = 0;
switch (c)
{
/*no white space starting line*/
/*only single spaces elsewhere*/
case '\t' :
c = ' ';
case ' ' :
while (((peek = getchr()) == ' ') || (peek == '\t'))
peek = -1;
if (j)
string[j++] = c;
break;
/*at end of line, perform additional*/
/*formatting checks on entire line*/
case '\n' :
if (check_puts())
printf("\n");
break;
/*block delimiters on separate line*/
case '}' :
case '{' :
if (j)
if (check_puts())
printf("\n");
string[j++] = c;
while (((peek = getchr()) == ' ') || (peek == '\t'))
peek = -1;
if (peek != '\n')
{
check_puts();
printf("\n");
}
break;
/*space after, no space before ; and ,*/
case ';' :
case ',' :
if (j && (string[j - 1] == ' '))
j--;
string[j++] = c;
if (((peek = getchr()) != ' ') && (peek != '\t'))
string[j++] = ' ';
break;
/*remove some spaces adjacent to brackets/parentheses*/
/* -[- -] -(- -) */
/*add space if identifier follows close parenthesis*/
/* )+ident ]+ident*/
case '(' :
case '[' :
while (((peek = getchr()) == ' ') || (peek == '\t'))
peek = -1;
if ((j > 1) && (string[j - 1] == ' ') &&
isname_char(string[j - 2]))
j--;
string[j++] = c;
break;
case ')' :
case ']' :
if (j && (string[j - 1] == ' '))
j--;
string[j++] = c;
if (isname_char(peek = getchr()))
string[j++] = ' ';
break;
/*pass over text*/
/*delete imbedded newlines*/
case '"' :
case '\'' :
string[j++] = c;
while ((cc = getchr()) != c)
{
string[j++] = cc;
if (cc == '\n')
j--;
if (cc == '\\')
string[j++] = getchr();
}
string[j++] = cc;
break;
case '\\' :
string[j++] = c;
string[j++] = getchr();
break;
/*pass over #defines*/
case '#' :
if (j)
if (check_puts())
printf("\n");
string[j++] = c;
while ((cc = getchr()) != '\n')
string[j++] = cc;
string[j++] = cc;
puts();
break;
/*pass over comments*/
/*add lead tab if comment follows text*/
/*if "/" not comment start, fall through to default*/
/*there is also comment check during operator output*/
case '/' :
if ((peek = getchr()) == '*')
{
comment();
break;
}
default :
if (isoperator(c))
operators();
else
string[j++] = c;
break;
}
}
dioflush();
exit();
}
/*page eject*/
/*
main routine to introduce and delete spaces from text with operators
*/
void operators()
{
/*checks on special expression operators or operator pairs*/
/*remove lead and trail spaces as appropriate*/
peek = getchr();
if ((c == peek) && ((c == '+') || (c == '-')))
{
string[j++] = c;
string[j++] = peek;
peek = -1;
return;
}
while (string[j - 1] == ' ')
j--;
if ((c == '-') && (peek == '>'))
{
string[j++] = c;
string[j++] = peek;
peek = -1;
while (((c = getchr()) == ' ') || (c == '\t'))
;
peek = c;
return;
}
if (c == '.')
{
string[j++] = c;
while (((c = getchr()) == ' ') || (c == '\t'))
;
peek = c;
return;
}
while (((cc = getchr()) == ' ') || (cc == '\t'))
;
peek = cc;
/*test whether last character sequence is expression*/
/*for start of line (j=0), check_puts() tested end of prev line*/
if (j)
expr_flag = isexpression(string[j - 1]);
/*add lead space (trail space is as appropriate added below)*/
if (j && (string[j - 1] != '(') && (string[j - 1] != '['))
string[j++] = ' ';
/*expr_flag TRUE is followed by a binary or assign operator*/
if (expr_flag)
{
while (isbinop(c))
{
peek = getchr();
if ((c == '/') && (peek == '*'))
{
comment(); /*watch for comments*/
return;
}
string[j++] = c;
while (((c = getchr()) == ' ') || (c == '\t'))
;
expr_flag = 0;
}
string[j++] = ' ';
}
/*handling of unary operator sequences*/
/*for when expr_flag = 0 at entry to operators()*/
/*or on fall through from above block executed when expr_flag = 1*/
while (isoperator(c))
{
string[j++] = c;
while (((c = getchr()) == ' ') || (c == '\t'))
;
}
peek = c;
return;
}
/*page eject*/
/*
return true if last character sequence is an expression;
enter routine with string index j set at last character location + 1
ie at the end of the string;
*/
/*last_count = string position of last keyword found*/
/*last_key = identifier of last keyword*/
/*paren_count = count of control exprsn parenthesis imbalance*/
/*ctrl_count = string position after last parenthesis check*/
/*close_loc = string position of close of parenthesis*/
/*above externals reset as needed below or in check_puts()*/
int isexpression(testchar)
char testchar;
{
int k, l, count;
int pcount;
int temp;
char word[80];
k = last_count;
last_key = keys_total + 1;
string[j] = '\0';
/*can an open exprsn be closed*/
/*if so, set close_loc flag and exit if terminal ')'*/
if (paren_count)
{
count = end_paren(&string[ctrl_count], &paren_count);
if (!paren_count)
{
close_loc = ctrl_count += count;
if (!string[close_loc])
return FALSE;
}
else
ctrl_count = strlen(string);
}
/*check if previous word == expression*/
switch (testchar)
{
case '\'' :
case '"' :
case '_' :
case '+' :
case '-' :
case ']' :
case '.' : /*for float constants*/
return TRUE;
default :
if (isdigit(testchar))
return TRUE;
if (!isalpha(testchar) && (testchar != ')'))
return FALSE;
/*keywords are not expressions*/
/*and may change syntax for following operator*/
/*locate last keyword in line*/
/*if a control keyword is met*/
/*check parenthesis balance for following expression*/
while (k < j)
{
count = next_alpha_word(&string[k], word);
k += count;
if (strlen(word) < 2 || strlen(word) > 8)
continue;
for (l = 0; l <= keys_total; l++)
if (!strcmp(word, keyword[l]))
{
last_count = k;
last_key = l;
if (l <= control_keys)
{
paren_count = 0;
ctrl_count = last_count;
count = end_paren(&string[ctrl_count], &paren_count);
if (!paren_count)
ctrl_count += count;
else
ctrl_count = strlen(string);
}
break;
}
}
/*set last_count and*/
/*return if no keyword*/
if (last_key > keys_total)
{
last_count = strlen(string);
return TRUE;
}
else
while (string[last_count] == ' ')
last_count++;
/*return if keyword or (keyword) at end of line*/
if (!string[last_count] || string[last_count] == ')')
return FALSE;
/*assume the following declarations are the last on a line*/
if (last_key == union_key || last_key == struct_key ||
last_key == typedef_key)
return FALSE;
if (last_key > control_keys)
return TRUE; /*not control keyword*/
/*check exprsn following control keyword*/
if (!paren_count)
{
if (!string[ctrl_count])
return FALSE; /*control exprsn ends line*/
else
return TRUE;
}
else
return TRUE; /*unclosed control expression*/
}
}
/*page eject*/
/*
process line buffer, including a call to line_check(),
then print it
*/
int check_puts()
{
/*terminate string*/
if (!j)
return 1;
else
string[j] = '\0';
/*remove trailing spaces*/
while (string[j - 1] == ' ')
string[j--] = '\0';
/*set expression flag for next line and try to close open expressions*/
expr_flag = isexpression(string[j - 1]);
/*insert newline if open expression was closed*/
if (close_loc && close_loc < (j - 1))
{
while (string[close_loc] == ' ')
close_loc++;
insert_char(string, close_loc, '\n');
}
/*reset control values*/
last_count = 0;
last_key = keys_total + 1;
ctrl_count = 0;
close_loc = 0;
/*process string*/
if (!line_check(string))
return 0;
else
j = strlen(string);
/*remove trailing spaces again*/
while (string[j - 1] == ' ')
string[j--] = '\0';
/*print buffer and continue*/
puts();
return 1;
}
/*page eject*/
/*
main routine for processing line of text
to make changes not done on the character scan
*/
int line_check(teststr)
char *teststr;
{
int k, l;
int count;
int tempchar;
int pcount;
/*space after if, while, for, switch, etc, */
for (k = 0; k <= keys_total; k++)
{
if (count = str1_start_str2(keyword[k], teststr))
{
tempchar = teststr[count];
/*reject if keyword is first part of longer name*/
/*reject if space present or end of exprsn or line*/
if ((tempchar != ' ') && (tempchar != ';') &&
(tempchar != ')') && (tempchar != '\n') &&
!isname_char(tempchar))
count = insert_char(teststr, count, ' ');
break;
}
count = 0;
}
/*newline after (control expression)*/
/*if newline needed, then process remainder of line*/
/*so have only one statement or control expression per line*/
if (count && (k <= control_keys))
{
/*go to end of control expression */
pcount = 0;
if ((count = end_paren(teststr, &pcount)) > 0)
return break_line(teststr, count);
count = 0;
}
/*newline after else and do */
if (count && ((k == do_key) || (k == else_key)))
{
/*reject if keyword is first part of longer name*/
if (!isname_char(teststr[count]))
return break_line(teststr, count);
count = 0;
}
/*newline after : except if operator (-?-:-) */
/*allow (case '-' :) and (anyword :) */
if (count && ((k == case_key) || (k == default_key)))
{
if (count = str1_in_str2(":", teststr))
return break_line(teststr, count);
count = 0;
}
/*this sequence destroys the value of count = keyword ident*/
if (count = str1_in_str2(" ", teststr))
{
count = good_char(teststr, count);
if (teststr[count++] == ':')
return break_line(teststr, count);
}
/*only one statement per line*/
count = 0;
while (teststr[count] != '\0')
{
count = good_char(teststr, count);
if (((tempchar = teststr[count++]) == ';') ||
(tempchar == '}') || (tempchar == '{'))
return break_line(teststr, count);
}
return 1;
}
/*page eject*/
void use_mess()
{
printf(
"\nUSAGE:\n");
printf(
" cbprep <input_fid [>out_fid or |DIO_pipe or default = crt]\n\n");
printf(
"one of three formatting filters:\n\n");
printf(
"unvanuys - converts keywords of Van Nuys Toolkit to standard K & R 'c'\n");
printf(
"cbprep - produces consistent spacing of 'c' text and one statement per line\n");
printf(
" output must be filtered by cb\n");
printf(
"cb - indents according to control level\n\n");
dioexit();
}
/*
"c" reserved words---
the first four require a control expression following;
some of the others may have an exprsn or statemnt etc following;
*/
void init_key()
{
int k;
k = 0;
keyword[k++] = "if";
keyword[k++] = "while";
keyword[k++] = "for";
keyword[k++] = "switch";
control_keys = k - 1; /*end of keywrds requiring exprsn*/
keyword[k++] = "do";
do_key = k - 1;
keyword[k++] = "else";
else_key = k - 1; /*end of keywrds with following line feed */
keyword[k++] = "return";
keyword[k++] = "case";
case_key = k - 1;
keyword[k++] = "default";
default_key = k - 1;
keyword[k++] = "break";
keyword[k++] = "continue";
keyword[k++] = "goto";
flow_keys = k - 1; /*end of keywords for flow control*/
keyword[k++] = "auto";
keyword[k++] = "static";
keyword[k++] = "extern";
keyword[k++] = "register";
keyword[k++] = "typedef";
typedef_key = k - 1; /*typedef keyword*/
keyword[k++] = "char";
keyword[k++] = "short";
keyword[k++] = "int";
keyword[k++] = "long";
keyword[k++] = "unsigned";
keyword[k++] = "float";
keyword[k++] = "double";
keyword[k++] = "struct";
struct_key = k - 1; /*struct keyword*/
keyword[k++] = "union";
union_key = k - 1; /*union keyword*/
keyword[k++] = "sizeof";
c_keys = k - 1; /*end of 'c' keywords*/
keyword[k++] = "FILE"; /*additional keywords*/
keys_total = k - 1;
}
int getchr()
{
int tempchar;
tempchar = lastchar;
lastchar = (peek < 0) ? getchar() : peek;
if ((lastchar == EOF) || (lastchar == CPMEOF))
{
if (tempchar != '\n')
{
puts();
printf("\n");
}
dioflush();
exit();
}
else
lastchar = (lastchar & 0x7f);
peek = -1;
return (lastchar == '\r' ? getchr() : lastchar);
}
void puts()
{
if (!j)
return;
string[j] = '\0';
printf("%s", string);
j = 0;
return;
}
void comment()
{
if (j)
{
check_puts();
printf(" ");
}
string[j++] = c;
string[j++] = peek;
peek = -1;
sflag = 1;
rep :
while ((c = string[j++] = getchr()) != '*')
if (c == '\n')
puts();
if ((j > 1) && (string[j - 2] == '/'))
{
sflag++;
goto rep;
}
while ((c = string[j++] = getchr()) == '*')
;
if ((c == '/') && !(--sflag))
{
puts();
return;
}
else
if (c == '\n')
puts();
goto rep;
}
int isoperator(testchar)
int testchar;
{
switch (testchar)
{
case '!' :
case '%' :
case '&' :
case '*' :
case '+' :
case '-' :
case '/' :
case ':' :
case '<' :
case '=' :
case '>' :
case '?' :
case '^' :
case '|' :
case '~' :
case '.' :
return TRUE;
default :
return FALSE;
}
}
int isbinop(testchar)
char testchar;
{
switch (testchar)
{
case '%' :
case '/' :
case ':' :
case '<' :
case '=' :
case '>' :
case '?' :
case '^' :
case '|' :
return TRUE;
case '&' :
if ((peek == '&') || (string[j - 1] == '&'))
return TRUE;
case '*' :
case '-' :
case '+' :
if (expr_flag)
return TRUE;
case '!' :
if (peek == '=')
return TRUE;
default :
return FALSE;
}
}
int isname_char(testchar)
char testchar;
{
if (isalpha(testchar) || isdigit(testchar) || (testchar == '_'))
return TRUE;
else
return FALSE;
}
/*
find next all alpha word contained in string;
skip over text within " or ';
copy word to buffer;
return position in string of character following end of word;
*/
int next_alpha_word(str, buf)
char *str, *buf;
{
int count, word;
count = 0;
restart :
word = 0;
/*find next alpha character or end of string*/
while (!isalpha(str[count = good_char(str, count)]) && str[count])
count++;
/*copy characters into buffer until meet non-alpha character*/
/*if non-alpha is part of a 'c' identifier*/
/*go to end of identifier and then continue search*/
while (isname_char(str[count]))
{
if (!isalpha(str[count]))
{
while (isname_char(str[count]))
count++;
goto restart;
}
else
buf[word++] = str[count++];
}
/*exit if end of string*/
buf[word] = '\0';
return count;
}
/*
the next two functions perform as follows:
if string 1 is found in string2, return the position of the character
in str2 immediately following the str1 sequence;
else 0 is returned
*/
int str1_in_str2(str1, str2)
char *str1, *str2;
{
int i, loc;
for (i = 0; i < strlen(str2); i++)
if (loc = str1_start_str2(str1, &str2[i]))
return (loc + i);
return 0;
}
int str1_start_str2(str1, str2)
char *str1, *str2;
{
int loc;
loc = 0;
while (*str1++ == *str2++)
{
loc++;
if (!*str1)
return loc;
if (!*str2)
return 0;
}
return 0;
}
/*
test if string pointer is at good character
= non_text and non_space character;
if it is not, then advance pointer to next good character
*/
int good_char(str, loc)
char *str;
int loc;
{
int passchar, tempchar;
while (1)
{
if (!(tempchar = str[loc++]))
return --loc;
if ((tempchar == '"') || (tempchar == '\''))
{
while ((passchar = str[loc++]) != tempchar)
{
if (passchar == '\\')
passchar = str[loc++];
}
continue;
}
if (tempchar == '\\')
tempchar = str[loc++];
if (tempchar != ' ')
return --loc;
}
}
int break_line(teststr, count)
char *teststr;
int count;
{
count = good_char(teststr, count);
if (teststr[count] != '\0')
{
if (teststr[count] != '\n')
count = insert_char(teststr, count, '\n');
/*recursive call to check out rest of line*/
return line_check(&teststr[count]);
}
else
return 1;
}
int insert_char(str, loc, newchar)
char *str;
int loc, newchar;
{
char tempstr[200];
int k;
strcpy(tempstr, str);
k = loc;
if (newchar == '\n')
while (tempstr[loc - 1] == ' ')
loc--;
tempstr[loc] = newchar;
strcpy(&tempstr[loc + 1], &str[k]);
strcpy(str, tempstr);
return ++loc;
}
/*
check for balance of parentheses within string:
return 0 if no parentheses present and enter with *p_pflag = 0;
return -1 if imbalance;
else return pointer to next character after close of parentheses;
enter with pointer p_pflag to location with current value of paren count,
which is revised according to the search;
*/
int end_paren(str, p_pflag)
char *str;
int *p_pflag;
{
int loc, pflag;
pflag = *p_pflag;
loc = 0;
if (pflag == 0)
if (loc = str1_in_str2("(", str))
pflag++;
while (pflag)
{
loc = good_char(str, loc);
if (str[loc] == '(')
pflag++;
if (str[loc] == ')')
pflag--;
if (str[loc] == '\0')
{
loc = -1;
break;
}
loc++;
}
*p_pflag = pflag;
return loc;
}