## 8 Using ASCII Art to Produce Flow Graphs. ¶

You can configure the exact appearance of `cflow` output flow graph using `--level-indent` option. The simplest use for this option is to change the default indentation per nesting level. To do so, give the option a numeric argument specifying the number of columns to indent for each nesting level. For example, the following command sets the indentation level to 2, which is half of the default:

    cflow --level-indent 2 d.c

It can be used, for instance, to keep the graph within the page margins.

However, `--level-indent` can do much more than that. Each line in the flow graph consists of the following graphical elements: a start marker, an end marker, with several indent fills between them. By default, both start and end markers are empty, and each indent fill contains four spaces.

If the argument to `--level-indent` option has the form element=string, it specifies a character string that should be output in place of a given graph element. The element names are:

start | Start marker
0 | Indent fill 0
1 | Indent fill 1
end0 | End marker 0
end1 | End marker 1

Why are there two kinds of indent fills and end markers? Remember that the flow graph represents a call tree, so it contains terminal nodes (leaves), i.e. the calls that end a function, and non-terminal nodes (the calls followed by another ones on the same nesting level). The end marker 0 is for non-terminal nodes, and end marker 1 is for terminal nodes.

As for indent fills, indent fill 1 is used to represent graph edge, whereas fill 0 is used to keep the output properly aligned.

To demonstrate this, let’s consider following sample program:

    /* foo.c */
    int
    main()
    {
        f();
        g();
        f();
    }

    int
    f()
    {
        i = h();
    }

Now, let’s represent line elements by the following strings:

start | ‘`::`’
0 | ‘`` ’ (two spaces)
1 | ‘`|` ’ (a vertical bar and a space)
end0 | ‘`+-`’
end1 | ‘`\-`’

The corresponding command line will be: `cflow --level begin=:: --level '0= ' --level '1=| ' --level end0='+-' --level end1='\\-' foo.c`. Notice escaping the backslash characters in `end1`: generally speaking, string in `--level-option` can contain usual `C` escape sequences, so the backslash character itself must be escaped. Another shortcut, allowed in string is the notation `CxN`, where C is any single character and N is a decimal number. This notation means “repeat character C N times”. However, character ‘`x`’ looses its special meaning if used at the beginning of the string.

This command will produce the following output:

    ::+-main() <int main () at foo.c:3>:
    ::  +-f() <int f () at foo.c:11>:
    ::  | \-h()
    ::  \-g()

Thus, we obtained an ASCII art representation of the call tree. GNU `cflow` provides a special option `--tree` (`-T`), which is a shortcut for `--level '0= ' --level '1=| ' --level end0='+-' --level end1='\\-'`. The following is an example of flow graph produced with this option. The source file `wc.c` is a simple implementation of UNIX `wc` command, See Source of the `wc` command.

    $ cflow --tree --brief --cpp wc.c
    +-main() <int main (int argc,char **argv) at wc.c:127>
      +-errf() <void errf (char *fmt,...) at wc.c:34>
      | \-error_print()
      |     <void error_print (int perr,char *fmt,va_list ap) at wc.c:22>
      |   +-vfprintf()
      |   +-perror()
      |   +-fprintf()
      |   \-exit()
      +-counter() <void counter (char *file) at wc.c:108>
      | +-fopen()
      | +-perrf() <void perrf (char *fmt,...) at wc.c:46>
      | | \-error_print()
      | |    <void error_print (int perr,char *fmt,va_list ap)
      | |    at wc.c:22> [see 3]
      | +-getword() <int getword (FILE *fp) at wc.c:78>
      | | +-feof()
      | | \-isword() <int isword (unsigned char c) at wc.c:64>
      | |   \-isalpha()
      | +-fclose()
      | \-report()
      |     <void report (char *file,count_t ccount,
      |       count_t wcount,count_t lcount) at wc.c:57>
      |   \-printf()
      \-report()
           <void report (char *file,count_t ccount,
             count_t wcount,count_t lcount) at wc.c:57> [see 17]