home *** CD-ROM | disk | FTP | other *** search
- /*
- [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);
- }
-