## 5 Handling Recursive Calls. ¶

Sometimes programs contain functions that recursively call themselves. GNU output format provides a special indication for such functions. The definition of the recursive function is marked with an ‘`(R)`’ at the end of line (before terminating colon). Subsequent recursive calls to this function are marked with a ‘`(recursive: see refline)`’ at the end of line. Here, refline stands for the reference line number where the recursion root definition was displayed.

To illustrate this, let’s consider the following program, that prints recursive listing of a directory, allowing to cut off at the arbitrary nesting level:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <dirent.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdlib.h>
    #include <string.h>

    /* Return true if file NAME is a directory. */
    static int
    isdir (char *name)
    {
      struct stat st;

      if (stat (name, &st))
        {
          perror (name);
          return 0;
        }
      return S_ISDIR (st.st_mode);
    }

    static char *ignored_names[] = { ".", "..", NULL };

    /* Return true if NAME should not be recursed into */
    int
    ignorent (char *name)
    {
      char **p;
      for (p = ignored_names; *p; p++)
        if (strcmp (name, *p) == 0)
          return 1;
      return 0;
    }

    int max_level = -1;

    /* Print contents of the directory PREFIX/NAME.
       Prefix each output line with LEVEL spaces. */
    void
    printdir (int level, char *name)
    {
      DIR *dir;
      struct dirent *ent;
      char cwd[512];

      if (!getcwd(cwd, sizeof cwd))
        {
          perror ("cannot save cwd\n");
          _exit (1);
        }
      chdir (name);
      dir = opendir (".");
      if (!dir)
        {
          perror (name);
          _exit (1);
        }

      while ((ent = readdir (dir)))
        {
          printf ("%*.*s%s", level, level, "", ent->d_name);
          if (ignorent (ent->d_name))
            printf ("\n");
          else if (isdir (ent->d_name))
            {
              printf ("/");
              if (level + 1 == max_level)
                putchar ('\n');
              else
                {
                  printf (" contains:\n");
                  printdir (level + 1, ent->d_name);
                }
            }
          else
            printf ("\n");
        }
      closedir (dir);
      chdir (cwd);
    }

    int
    main (int argc, char **argv)
    {
      if (argc < 2)
        {
          fprintf (stderr, "usage: d [-MAX] DIR [DIR...]\n");
          return 1;
        }

      if (argv[1][0] == '-')
        {
          if (!(argv[1][1] == '-' && argv[1][2] == 0))
            max_level = atoi (&argv[1][1]);
          --argc;
          ++argv;
        }

      while (--argc)
        printdir (0, *++argv);

      return 1;
    }

Running `cflow` on this program produces the following graph:

    $ cflow --number 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         isdir() <int isdir (char *name) at d.c:12>:
       14             stat()
       15             perror()
       16             S_ISDIR()
       17         putchar()
       18         printdir()
                    <void printdir (int level,char *name) at d.c:42>
                    (recursive: see 4)
       19         closedir()

The `printdir` description in line 4 shows that the function is recursive. The recursion call is shown in line 18.