home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol228 / cflow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-02-10  |  6.0 KB  |  327 lines

  1.  
  2. /*
  3. **   CFLOW.C : find module call structure of c program
  4. **   refer to cflow.doc for how to use
  5. **    
  6. **         copyright 1984 by Mark Ellington
  7. **
  8. **     released for public domain use only
  9. **     
  10. */
  11.  
  12. #define TRUE    1
  13. #define    FALSE    0
  14. #define    ERROR    -1
  15. #define    EOF    -1    
  16.  
  17. #include printf.c
  18. #include b:cflolib.c80   /* not needed with BDS? */ 
  19.  
  20. int fptr;       /* input file pointer */ 
  21. int level;      /* keep track of level of open "{"s */
  22. char name[100]; /* module name buffer */
  23.  
  24. char ins[100];  /* source input line buffer */
  25. int curchar;    /* current character in input line buffer
  26.            array subscript */     
  27.  
  28. main(argc,argv)
  29. int argc; char *argv[];
  30. {
  31.  
  32.     printf("\nCFLOW --> \n");
  33.  
  34.     if (argc != 2) {
  35.         printf("\nusage: cflow [infilename.ext] "); 
  36.                 exit();
  37.     }
  38.  
  39.     if ((fptr = fopen(argv[1],"r")) == FALSE) {
  40.         printf("\nCan't open %s\n",argv[1]);
  41.         exit();
  42.     }
  43.  
  44.     printf("\nSource file: %s",argv[1]);
  45.  
  46.     modules(); 
  47.  
  48.     fclose(fptr);
  49. }
  50.  
  51.  
  52. modules()    /* find function declarations and calls */
  53. {
  54.     int j;
  55.     char c;
  56.     int incom;    /* comment flag */
  57.     int decl;    /* module declaration line flag */
  58.     int lastlin;    /* last line of file flag */
  59.     int quoted;    /* within " quotes */
  60.     int header;    /* within function header (before 1st '{') */
  61.  
  62.     incom = lastlin = quoted  = header = FALSE;
  63.  
  64.     level = 0;
  65.  
  66.     do {
  67.  
  68.         lastlin = fgets();    /* read a line of source */
  69.         
  70.         decl = FALSE;  /* assume nothing */
  71.         curchar = 0;
  72.         while (curchar < 100) {/* read for significant characters */
  73.  
  74.             if (skipline()) break;
  75.  
  76.             quotes();    /* skip single quoted character */
  77.  
  78.             incom = comment(incom);    /* true if in comment */
  79.  
  80.             c = ins[curchar];
  81.         
  82.             /* read for significant characters */
  83.  
  84.             if (!incom) {
  85.  
  86.                 /* skip double quoted strings */
  87.             
  88.                 if (c == '\042') quoted = !quoted;
  89.                 
  90.                 if (!quoted) {
  91.             
  92.                     switch(c) { 
  93.  
  94.                     case '{' :    
  95.                         level++;
  96.                         header = FALSE;
  97.                         break;
  98.  
  99.                     case '}' :    
  100.                         level--;
  101.                         break;    
  102.  
  103.                     /* "(" always follows function call */
  104.                             /* or declaration */
  105.             
  106.                     case '(' :    
  107.  
  108.                     if (!ischar(ins[curchar-1])) 
  109.                         break;
  110.                     lookbak(curchar);
  111.                     j = modname();
  112.                     if (!j) break;
  113.                     else decl = TRUE;
  114.                     if (j == 2) 
  115.                         header = TRUE;    
  116.                     break;
  117.  
  118.  
  119.                               default : 
  120.                           break;
  121.                     }
  122.                 }
  123.             }
  124.         
  125.             ++curchar;     /* next character */
  126.         }
  127.         
  128.             /* display argument declarations */
  129.         comout(ins);             
  130.         if (header && !decl) printf("%s",ins);
  131.  
  132.     } while (lastlin);    /*  = 0 if last line */
  133.  
  134. }
  135.  
  136. /* skip this line ? */
  137.  
  138. skipline()
  139. {
  140. char c;
  141.     c = ins[curchar];
  142.  
  143.     if (c == '\0') return(TRUE);    /* end of line */
  144.  
  145.     else if (c == '#')            /* skip macro defs */
  146.         if (curchar < 5)    /* at beginning of line */
  147.             if (!strcmp("define",&ins[curchar+1])) 
  148.                 return(TRUE); 
  149.  
  150.     else return(FALSE);            /* no */
  151.  
  152. }
  153.  
  154.  
  155. /* skip characters quoted (for instance '}' would throw off level count */
  156.  
  157. quotes()
  158. {  
  159.     if (flowchar(ins[curchar]))        /* test critical chars only */
  160.         if (ins[curchar+1] == '\047')   /* next char single quote? */
  161.         if (curchar+2 < 100)        /* don't pass end of string */
  162.             curchar = curchar + 2; /* skip past quote */
  163. }
  164.  
  165.  
  166. /* return TRUE if entering comment, FALSE if exiting */
  167.  
  168. comment(incom)
  169. int incom;
  170. {
  171.     if (ins[curchar] == '/') {
  172.         if (ins[curchar+1] == '*') 
  173.             if (curchar + 1 < 100)    /* stay within string */ 
  174.                 return(TRUE);
  175.         else if (ins[curchar-1] == '*')
  176.             if (curchar - 1 >= 0)   /* stay within string */
  177.                 return(FALSE);
  178.     }
  179.     else return(incom);  /* unchanged */
  180. }
  181.  
  182.  
  183. /* look back from position n in string.  called with n indicating '('.
  184.    determine function name  */
  185.  
  186. lookbak(n)
  187. int n;
  188. {
  189.     int i;
  190.  
  191.     while (!ischar(ins[n])) {
  192.         if (n == 0) break;
  193.         --n;
  194.     }
  195.  
  196.     /* find leading blank */
  197.     while (ischar(ins[n-1])) {
  198.         if (n == 0) break;
  199.         --n;
  200.     }
  201.  
  202.     /* save name */
  203.     /* include variable declarations if module declaration */
  204.  
  205.     i = 0;
  206.     if (level == 0) {
  207.         while (ins[n])             /* full line if declaration */
  208.             name[i++] = ins[n++];
  209.     }
  210.     else {
  211.         while (ischar(ins[n]))      /* function call within function */
  212.             name[i++] = ins[n++];
  213.     }
  214.  
  215.     name[i] = '\0';
  216.  
  217.     comout(name);    /* remove comment from name string */
  218.         
  219. }
  220.  
  221.  
  222. /* terminate string at comment */
  223.  
  224. comout(s)
  225. char *s;
  226. {
  227. char c;    
  228.     
  229.     while(c = *s++) 
  230.         if (c == '/')
  231.             if (*s == '*') {
  232.                 --s;
  233.                 *s++ = '\n';
  234.                 *s = '\0';
  235.                 break;
  236.             }
  237.  
  238. }
  239.  
  240.  
  241.  
  242. /* display module name with indentation according to { level */
  243. /* returns 0 if not module, 1 if call within module, 2 if    */
  244. /* module declaration  */
  245.  
  246. modname()
  247. {
  248.     int j;
  249.  
  250.     if (unreserved()) {        /* test if builtin like while */
  251.             if (level == 0) {
  252.             printf("\n\n\n");
  253.             printf("**\n");
  254.             comout(ins);
  255.             printf("%s",ins);
  256.             return(2);
  257.                 }
  258.         else {
  259.             printf("\n");
  260.             for (j=0; j < level; ++j) 
  261.                 putchar('\t');
  262.             printf("%s()",name);
  263.             return(1);
  264.         }
  265.         }
  266.     return(0);
  267.     
  268. }
  269.  
  270. /* test for names that are operators not functions */
  271.  
  272. unreserved()
  273. {
  274.  
  275.     if (!strcmp(name,"return")) return(0);
  276.     else if (!strcmp(name,"if")) return(0);
  277.     else if (!strcmp(name,"while")) return(0);
  278.     else if (!strcmp(name,"for")) return(0);
  279.     else if (!strcmp(name,"switch")) return(0);
  280.  
  281.     else return(1);
  282.  
  283. }
  284.  
  285.  
  286. /* test if character is one that program tracks */
  287.  
  288. flowchar(c)
  289. char c;
  290. {
  291.     if (c == '{' || c == '}' || c == '\"') return(TRUE);
  292.     else return(FALSE);
  293.     
  294.  
  295.  
  296. /* test for character */
  297.  
  298. ischar(c)
  299. char c;
  300. {
  301.     if (isalpha(c) || isdigit(c)) return(TRUE);
  302.     else return(FALSE);
  303. }
  304.  
  305.  
  306. /* read a line of source */
  307.  
  308. fgets()
  309. {
  310.     char ch, *s;
  311.     s = ins;
  312.     while ((ch = getc(fptr)) != EOF) {
  313.         *s++ = ch;
  314.         if (ch == '\n') {
  315.             *s = '\0';
  316.             return(TRUE);
  317.         }
  318.     }
  319.     *s = '\0';
  320.     return(FALSE);
  321.  
  322. }    
  323.     
  324.  
  325.  
  326.