[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6 Controlling Symbol Types

An alert reader has already noticed something strange in the above output: the function _exit is missing, although according to the source file it is called twice by printdir. It is because by default cflow omits from its output all symbols beginning with underscore character. To include these symbols as well, specify ‘-i _’ (or ‘--include _’) command line option. Continuing our example:

$ cflow --number -i _ d.c
    1 main() <int main (int argc,char **argv) at d.c:85>:
    2     fprintf()
    3     atoi()
    4     printdir() <void printdir (int level,char *name) at d.c:42> (R):
    5         getcwd()
    6         perror()
    7         _exit()
    8         chdir()
    9         opendir()
   10         readdir()
   11         printf()
   12         ignorent() <int ignorent (char *name) at d.c:28>:
   13             strcmp()
   14         isdir() <int isdir (char *name) at d.c:12>:
   15             stat()
   16             perror()
   17             S_ISDIR()
   18         putchar()
   19         printdir()
                <void printdir (int level,char *name) at d.c:42>
                (recursive: see 4)
   20         closedir()

In general, ‘--include’ takes an argument specifying a list of symbol classes. Default option behavior is to include the requested classes to the output. If the argument begins with a minus or caret sign, this behavior is reversed and the requested symbol classes are excluded from the output.

The symbol class ‘_’ includes symbols whose names begin with an underscore. Another useful symbol class is ‘s’, representing static functions or data. By default, static functions are always included in the output. To omit them, one can give ‘-i ^s’ (or ‘-i -s(4)) command line option. Our sample program ‘d.c’ defines static function isdir, running cflow -i ^s, completely omits this function and its callees from the resulting graph:

$ cflow --number -i ^s d.c
    1 main() <int main (int argc,char **argv) at d.c:85>:
    2     fprintf()
    3     atoi()
    4     printdir() <void printdir (int level,char *name) at d.c:42> (R):
    5         getcwd()
    6         perror()
    7         chdir()
    8         opendir()
    9         readdir()
   10         printf()
   11         ignorent() <int ignorent (char *name) at d.c:28>:
   12             strcmp()
   13         putchar()
   14         printdir()
                <void printdir (int level,char *name) at d.c:42>
                (recursive: see 4)
   15         closedir()

Actually, the exclusion sign (‘^’ or ‘-’) can be used any place in ‘-i’ argument, not only at the beginning. Thus, option ‘-i _^s’ means “include symbols, beginning with underscore and exclude static functions”. Several ‘-i’ options accumulate, so the previous example can also be written as ‘-i _ -i ^s’.

It is important to notice that by default cflow graphs contain only functions. You can, however, request displaying variables as well, by using symbol class ‘x’. This class contains all data symbols, both global and static, so to include these in the output, use option ‘-i x’. For example:

$ cflow --number -i x d.c
    1 main() <int main (int argc,char **argv) at d.c:85>:
    2     fprintf()
    3     stderr
    4     max_level <int max_level at d.c:37>
    5     atoi()
    6     printdir() <void printdir (int level,char *name) at d.c:42> (R):
    7         DIR
    8         dir
    9         getcwd()
   10         perror()
   11         chdir()
   12         opendir()
   13         readdir()
   14         printf()
   15         ignorent() <int ignorent (char *name) at d.c:28>:
   16             ignored_names <char *ignored_names[] at d.c:24>
   17             strcmp()
   18         isdir() <int isdir (char *name) at d.c:12>:
   19             stat()
   20             perror()
   21             S_ISDIR()
   22             NULL
   23         max_level <int max_level at d.c:37>
   24         putchar()
   25         printdir()
                <void printdir (int level,char *name) at d.c:42>
                (recursive: see 6)
   26         closedir()

Now, lines 3, 4, 16 and 23 show data symbols, with their definitions when available. Notice, however, lines 7 and 8. Why both type name DIR and automatic variable dir are listed as data?

To answer this question, let’s first describe the cflow notion of symbols. The program keeps its symbol tables, which are initially filled with C predefined keywords. When parsing input files, cflow updates these tables. In particular, upon encountering a typedef, it registers the defined symbol as a type.

Now, DIR is not declared in ‘d.c’, so cflow has no way of knowing it is a data type. So, it supposes it is a variable. But then the input:

  DIR *dir;

is parsed as an expression, meaning “multiply DIR by dir”.

Of course, it is wrong. There are two ways to help cflow out of this confusion. You can either explicitly declare DIR as data type, or let cflow run preprocessor, so it sees the contents of the include files and determines it by itself. Running preprocessor is covered by the next chapter (see section Running Preprocessor). In the present chapter we will concentrate on the first method.

The command line option ‘--symbol’ (‘-s’) declares a syntactic class of the symbol. Its argument consists of two strings separated by a colon:

  --symbol sym:class

The first string, sym is a C identifier to be recorded in the symbol table. The second string, class, specifies a class to be associated with this symbol. In particular, if class is ‘type’, the symbol sym will be recorded as a C type definition. Thus, to fix the above output, run:

$ cflow --number -i x --symbol DIR:type d.c

Another important symbol type is a parameter wrapper. It is a kind of a macro, often used in sources that are meant to be compatible with pre-ANSI compilers to protect parameter declarations in function prototypes. For example, in the declaration below, taken from ‘/usr/include/resolv.h’, __P is a parameter wrapper:

void res_npquery __P((const res_state, const u_char *, int, FILE *));

For cflow to be able to process such declarations, declare __P as a wrapper, for example:

cflow --symbol __P:wrapper *.c

In both examples above the reason for using the ‘--symbol’ option was that cflow was unable to determine what the given symbol was, either because it did not see the type definition, as it was in case with ‘DIR’, or because the macro definition was not expanded. Both cases are better solved by using preprocess mode, described in the next chapter. Nevertheless, even with preprocessor, the ‘--symbol’ option remains useful, as shown in the following sections.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1 Syntactic classes

Generally speaking, the syntactic class of a symbol defines where in the C code this symbol can legitimately appear. There are following classes:

keyword
kw

A keyword, like ‘if’, ‘when’ etc.

modifier

Type modifier, i.e. the symbol appearing after a data type to modify its meaning, like ‘*’.

qualifier

Declaration qualifier. Can appear both before C declaration (much like ‘static’ or ‘extern’) and after a data type (like modifiers).

You would usually declare a gcc keyword ‘__extension__’ as a qualifier:

--symbol __extension__:qualifier
identifier

A C identifier.

type

A C data type, like ‘int’, ‘char’, etc.

wrapper

That has two meanings. First, it can be used to declare parameter wrappers when running cflow without preprocessor. This usage was described above. Second, it indicates any symbol that can appear in a declaration either before an identifier or before a terminating semicolon and optionally followed by a parenthesized expression list.

We recommended to use this class for the gcc__attribute__’ keyword.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2 Symbol aliases

Yet another use for the ‘--symbol’ option is to define symbol aliases. An alias is a token that behaves exactly as the symbol it refers to. Alias is declared using the following construct:

--symbol newsym:=oldsym

As a result of this option, the symbol newsym is declared to be the equivalent of oldsym.

Symbol aliasing can be regarded as defining the symbol class by example of another symbol. It is useful for some special keywords, such as ‘__restrict’:

--symbol __restrict:=restrict

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3 GCC Initialization

The following is a recommended set of cflow initialization options for use with gcc. We suggest you to put them in your ‘cflow.rc’ file (see section Configuration Files and Variables.).

--symbol __inline:=inline
--symbol __inline__:=inline
--symbol __const__:=const
--symbol __const:=const
--symbol __restrict:=restrict
--symbol __extension__:qualifier
--symbol __attribute__:wrapper
--symbol __asm__:wrapper
--symbol __nonnull:wrapper
--symbol __wur:wrapper

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated on December 30, 2021 using texi2html 5.0.