home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
PROGRAM
/
CP14.ZIP
/
CP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-20
|
13KB
|
526 lines
/*
[76703,4265]
NUTTER.LST 01-Aug-88 29168
Keywords: NUTTER AUG88 C SOURCE CONTROL
Automatic Module Control in C - source listings from Stewart Nutters
article in the August 1988 issue of DDJ.
LISTING 1
*/
/* print a visual tree representation of a 'C' program */
/* cp.c */
/***********************************************************
cprinter - print a visual tree representation
of a 'C' program
copyright 1987, Stewart A. Nutter
Please do not distribute this for profit. For
individual use only.
written by: Stewart A. Nutter
**********************************************************/
#define MAINMODULE 1
#include "cp.h"
/* v1.1 Prototypes */
int xref(char *fname);
/* external in cpfuncts.c */
extern int find_mod(char *buf);
extern void getstats(void);
extern int doprint(int n);
extern void pagebreak(void);
extern void leftmargin(void); /* v1.1 */
extern char getnext(FILE *stream);
extern void pushc(char c);
extern int strcheck(char c);
extern int addlist(struct Func_list *p, char *buf, int cnt);
void main(int argc, char **argv) /* v1.1 made void */
{
char szName[20]; /* input file name */
int l, i; /* index variables */
int sflag;
int pcnt;
int tmp;
int pmax; /* max number of xref columns */
int index;
FILE *stream;
struct Pages *p;
long int total; /* total number of bytes */
long int ltotal; /* total number of lines */
pFlist = Flist;
pMlist = Mlist;
pMnames = Mnames;
for (i = 0; i < 50; i++) /* clear out the recursion list */
rlist[i] = NULL;
/* v1.4 Funny sort of bug: during the initial processing,
* the first string in our string segment gets printed!
*/
printf("\ncp - ver. 1.3, (C) 1987, 1988 Stewart A. Nutter");
printf("\n written by Stewart A. Nutter\n");
/* no arguments - print instructions */
if (argc < 2) {
printf("\ncp listfile [ outfile ] [ /l:xx /w:yy /t:main /s:z ]\n");
printf(" outfile = \"prn\" \n");
printf(" l: page length = 66 [0, 50-255]\n");
printf(" w: page width = 80 [80-255]\n");
printf(" m: left margin = 8 [0-30]\n");
printf(" r: right margin = 8 [0-30]\n");
printf(" t: target function = \"main\"\n");
printf(" s: statistics only = 0 [0=all, 1=stats only]\n");
printf("\n");
printf("Notes: 1. Maximum recursive function displacement of 50.\n");
printf(" 2. Maximum number of functions calls is %d.\n", MAXFNCTS);
printf(" 3. Maximum number of modules is %d.\n", MAXMODULES);
exit(0);
}
if ((stream = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "\n%s", strerror(errno));
exit(1);
}
/* an output file name was given? */
index = 2;
#ifdef NO_STDOUT
if (argc > 2 && argv[index][0] != '/') {
output = fopen(argv[2], "w+");
index++;
} else
output = fopen("prn", "w+"); /* prn device by default */
#endif
for (i = index; i < argc; i++) {
if ((argv[i][0] == '/')
&& (strlen(argv[i]) > 3)
&& (argv[i][2] == ':')) {
switch (argv[i][1]) {
case 'l': /* change the page length */
tmp = atoi(&argv[i][3]);
if (((tmp > 50) && (tmp < 256)) || (tmp == 0))
pl = tmp;
break;
case 'm': /* change the left margin */
tmp = atoi(&argv[i][3]);
if ((tmp >= 0) && (tmp <= 30))
lm = tmp;
break;
case 'r': /* change the right margin */
tmp = atoi(&argv[i][3]);
if ((tmp >= 0) && (tmp <= 30))
rm = tmp;
break;
case 's': /* set the stats only? */
stats = atoi(&argv[i][3]);
break;
case 't': /* change the target function */
strcpy(target, &argv[i][3]);
break;
case 'w': /* change the width */
tmp = atoi(&argv[i][3]);
if ((tmp > 79) && (tmp < 256))
pw = tmp;
break;
}
} else {
printf("\nUnknown argument: %s", argv[i]);
exit(1);
}
}
#ifdef NO_STDOUT
if (output == NULL) {
fprintf(stderr, "\n%s", strerror(errno));
exit(1);
}
#endif
width = pw - lm - rm;
if (width < 40) {
fprintf(stderr, "\nThe page width is too narrow.");
exit(1);
}
printf("\n");
/* read the input file for file names */
while (!feof(stream)) {
szName[0] = '\0';
fgets(szName, 19, stream);
if ((l = strlen(szName)) > 1) {
if (szName[l - 1] == '\n')
szName[l - 1] = '\0'; /* remove newline char */
xref(szName);
}
}
/* pointer list for sort */
for (i = 0, pMlist = Mlist; i < Mqty; i++) {
pm[i] = pMlist++;
}
printf("\n\nSorting the function list...\n");
sflag = 1;
while (sflag) { /* sort the function names */
sflag = 0;
for (i = 0; i < Mqty - 1; i++) {
if (strcmp(pm[i]->function, pm[i + 1]->function) > 0) {
sflag = 1;
pMlist = pm[i];
pm[i] = pm[i + 1];
pm[i + 1] = pMlist;
}
}
}
i = find_mod(target); /* must start with the target function */
if (i >= 0) { /* 'main' must exist */
depth = 0;
printf("Checking for usage...\n");
/* check how many times each function is used */
getstats();
depth = 0;
bfr[0] = 0;
printf("Starting the printout...\n");
line = 0;
if (stats == 0) {
pm[i]->used = 1; /* set so main shows up in the list */
doprint(i); /* print the non-library functions */
for (i = 0; i < Mqty; i++) { /* print defined functions now */
printf("\n"); /* v1.4 */
line++;
if (pm[i]->used > 1) { /* must be used more than once */
doprint(i); /* print the tree structure */
}
}
}
/* print statistics on the modules */
line = 9999; /* force a new page */
pMnames = Mnames;
pagebreak();
leftmargin();
printf("Module statistics :\n"); /* v1.4 */
line++;
total = 0L;
ltotal = 0L;
for (i = 0; i < Mcnt; i++) { /* print module names & sizes */
pagebreak();
leftmargin();
printf("%-12s - %5u lines, %6ld bytes\n", /* v1.4 */
pMnames->name, pMnames->length,
pMnames->size);
total += pMnames->size;
ltotal += pMnames->length;
line++;
pMnames++;
}
fputc('\n',stdout); /* v1.4 */
leftmargin();
printf( /* v1.4 */
"Total source size = %ld bytes in %ld lines for %d modules\n",
total, ltotal, Mcnt);
/* print the used function page index */
line = 9999; /* force a new page */
pagebreak();
leftmargin();
printf("Function index :\n"); /* v1.4 */
line++;
for (i = 0; i < Mqty; i++) { /* print used function names */
pMlist = pm[i];
if (pMlist->used > 0) {
pagebreak();
leftmargin();
printf( /* v1.4 */
"%-25s - %-12s - used =%d \n",
pMlist->function, (pMlist->name)->name,
pMlist->used);
line++;
}
}
/* print the function page cross reference */
if (stats == 0 && pl > 0) { /* print everything */
pmax = (int) (width - 27) / 5;
line = 9999; /* force a new page */
pagebreak();
leftmargin();
printf("Function cross reference :\n"); /* v1.4 */
line++;
for (i = 0; i < Mqty; i++) { /* print used function names */
pMlist = pm[i];
if (pMlist->used > 0) {
pagebreak();
leftmargin();
printf("%-25s- ", pMlist->function); /* v1.4 */
p = pMlist->pg;
if (p != NULL) {
pcnt = 0;
while (p->next != NULL) {
printf("%4d,", p->pg); /* v1.4 */
p = p->next;
pcnt++;
if (pcnt >= pmax) {
fputc('\n', stdout);
leftmargin();
printf("%27s", " "); /* v1.4 */
line++;
pcnt = 0;
}
}
printf("%4d\n", p->pg); /* v1.4 */
line++;
} else
printf("\n"); /* v1.4 */
}
}
}
/* print statistics on all unused modules */
line = 9999; /* force a new page */
pagebreak();
leftmargin();
printf("Un-used function list :\n"); /* v1.4 */
line++;
pcnt = 0;
for (i = 0; i < Mqty; i++) { /* print unused function names */
pMlist = pm[i];
if (pMlist->used == 0) {
pagebreak();
pcnt++;
leftmargin();
printf( /* v1.4 */
"%-25s - %-12s \n",
pMlist->function, (pMlist->name)->name);
line++;
}
}
if (pcnt == 0) {
leftmargin();
printf( /* v1.4 */
"No un-used functions in the list.\n");
}
/* print module comments */
line = 9999; /* force a new page */
pMnames = Mnames;
pagebreak();
leftmargin();
printf("Module comments :\n"); /* v 1.4 */
line++;
for (i = 0; i < Mcnt; i++) { /* print module names & comments */
pagebreak();
leftmargin();
printf( /* v1.4 */
"%12s -%s\n",
pMnames->name, pMnames->cmt);
line++;
pMnames++;
}
printf("%c", 0x0c); /* ending formfeed v1.4 */
}
}
/* process the file for function names */
int xref(char *fname)
{
int done; /* loop termination flag */
int brace_cnt; /* count of the open braces */
int open_paren; /* open paranthisis count */
int ret; /* return value */
int indx; /* for/next index */
int dflg; /* function definition flag */
static int wflg = 0;
char c; /* character read from disk file */
char buffer[50]; /* temporary buffer */
char bufr[256]; /* temporary buffer */
register char *p; /* fast character pointer */
FILE *stream; /* module file pointer */
struct Mod_list *cptr; /* pointer to the module list structure */
static char back[] =
{8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
printf("%cProcessing file: %-12s ", 0x0d, fname);
if ((stream = fopen(fname, "r")) == NULL)
return (-1);
pp = pc;
if ((pMnames->name = strdup(fname)) == NULL) {
fprintf(stderr, "Ran out of memory.\n");
exit(1);
}
pMnames->length = 0;
pMnames->size = 0L;
buffer[0] = 0;
p = buffer;
open_paren = 0;
brace_cnt = 0;
firstcmt = 0;
filecmt[0] = 0;
done = 0;
ret = 0;
while (!ret) {
c = getnext(stream);
switch (c) {
case '{':
brace_cnt++; /* increment the open brace count */
break;
case '}':
brace_cnt--; /* decrement the open brace count */
break;
case '(':
if (open_paren == 0) { /* first open paren only */
open_paren = 1;
}
wflg = 1;
break;
case ' ': /* skip tabs and spaces */
case '\t':
do {
c = getnext(stream);
}
while (c == '\t' || c == ' ');
if (c != '(')
wflg = 1;
pushc(c);
break;
case 0x1a: /* end of the file indicator */
ret = 1;
wflg = 1;
default:
/* the character must be a variable character */
if (strcheck(c)) {
*p++ = c;
*p = 0;
} else
wflg = 1;
break;
}
if (wflg) {
if (buffer[0] && (buffer[0] < '0' || buffer[0] > '9')) {
done = 1;
} else {
p = buffer;
buffer[0] = 0;
open_paren = 0;
}
wflg = 0;
}
/* if done != 0 there is a token */
if (done) {
done = 0;
*p = 0;
if (open_paren) { /* functions start with an open paren */
open_paren = 0;
if (brace_cnt == 0) { /* and no braces */
dflg = 0;
for (indx = 0; indx < 256 && dflg == 0; indx++) {
c = getnext(stream);
if (c == ';')
dflg = 1;
else if (c == '\n')
dflg = 2;
bufr[indx] = c;
}
if (dflg == 0) {
fprintf(stderr, "\nSyntax error: ");
fprintf(stderr, "Module description.\n");
bufr[indx] = 0;
fprintf(stderr, "\n%s\n", bufr);
exit(1);
}
/* put the characters back to be read */
while (indx) {
pushc(bufr[indx - 1]);
indx--;
}
/* this is a function definition */
if (dflg == 2) {
printf("%-40s%s", buffer, back);
pMlist->name = pMnames;
pMlist->qty = 0;
pMlist->ptr = pFlist;
/* allocate memory for name */
if ((pMlist->function = strdup(buffer))
== NULL) {
fprintf(stderr, "\nRan out of memory.");
exit(1);
}
pMlist->used = 0;
pMlist->pg = NULL;
cptr = pMlist;
pMlist++;
Mqty++;
if (Mqty > MAXMODULES) {
fprintf(stderr,
"Too many new functions\n");
exit(1);
}
}
} else {
cptr->qty += addlist(cptr->ptr,
buffer, cptr->qty);
}
}
p = buffer;
*p = 0;
}
}
fclose(stream);
pMnames->cmt = strdup(filecmt);
pMnames++; /* point to the next function data structure */
Mcnt++; /* count of the different functions */
return (ret);
}