home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / flow / !flow / c / cflow
Encoding:
Text File  |  1992-11-25  |  7.6 KB  |  351 lines

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