Next: , Previous: Intro, Up: Top


2 Simple Ways to Analyze Programs with cflow.

Let's begin our acquaintance with the GNU cflow utility with an example. Suppose you have a simple implementation of whoami command and you wish to obtain a graph of function dependencies. Here is the program:

     /* whoami.c - a simple implementation of whoami utility */
     #include <pwd.h>
     #include <sys/types.h>
     #include <stdio.h>
     #include <stdlib.h>
     
     int
     who_am_i (void)
     {
       struct passwd *pw;
       char *user = NULL;
     
       pw = getpwuid (geteuid ());
       if (pw)
         user = pw->pw_name;
       else if ((user = getenv ("USER")) == NULL)
         {
           fprintf (stderr, "I don't know!\n");
           return 1;
         }
       printf ("%s\n", user);
       return 0;
     }
     
     int
     main (int argc, char **argv)
     {
       if (argc > 1)
         {
           fprintf (stderr, "usage: whoami\n");
           return 1;
         }
       return who_am_i ();
     }

Running cflow produces the following output:

     $ cflow whoami.c
     main() <int main (int argc,char **argv) at whoami.c:26>:
         fprintf()
         who_am_i() <int who_am_i (void) at whoami.c:8>:
             getpwuid()
             geteuid()
             getenv()
             fprintf()
             printf()

This is a direct call graph showing caller—callee dependencies in the input file. Each line starts with a function name, followed by a pair of parentheses to indicate that it is a function. If this function is defined in one of the input files, the line continues by displaying, within a pair of angle brackets, a function signature and the location of its definition. If the function calls another functions, the line ends with a colon. For example, the line

     main() <int main (int argc,char **argv) at whoami.c:25>:

shows that function main is defined in file whoami.c at line 25, as int main (int argc, char **argv). Terminating colon indicates that main invokes other functions.

The lines following this one show which functions are called by main. Each such line is indented by a fixed amount of white space (by default, four spaces) for each nesting level.

Usually cflow prints a full function signature. However, sometimes you may wish to omit some part of it. Several options are provided for this purpose. To print signatures without function names, use --omit-symbol-names option. To omit argument list, use --omit-arguments. These options can be needed for a variety of reasons, one of them being to make the resulting graph more compact. To illustrate their effect, here is how would the first line of the above graph look if you had used both --omit- options:

     main() <int () at whoami.c:25>:

By default, cflow starts outputting direct graph from the function called main. It is convenient when analyzing a set of input files comprising an entire C program. However, there are circumstances where a user would want to see only a part of the graph starting on particular function. Cflow allows to select such function using --main (-m) command line option. Thus, running

     cflow --main who_am_i whoami.c

on the above file will produce following graph:

     who_am_i() <int who_am_i (void) at whoami.c:8>:
         getpwuid()
         geteuid()
         getenv()
         fprintf()
         printf()