ROBODoc
FUNCTION
ROBODoc is intended to be a replacement for the original AutoDocs program. ROBODoc will extract the comment headers from a source file, and put them into a separate documentation file. General Flow
Sourcecode ---> [ROBODoc] ---> Document.
The whole ROBODoc process consists of three steps: scanning, analysing, generating.
Scanning
ROBODoc scans the source directory tree. This collects the names of all the source files.
Analysing
ROBODOc analyses all the sourcefiles. This reads the content of all source files and collects all the headers.
Generating
In this step the headers are written to one or more documentation files. In addition
The data collected during scanning and analysing is stored in a number of structures.
RB_Directory, it stores the names of the sourcefiles and directories in the source direcory tree. File names are stored in a RB_Filename structure, directory names in a RB_Path structure. Each RB_Filename contains a pointer (path) to a RB_Path structure that tells in which directory a file is located. Each RB_Path has a pointer (parent) to another RB_Path structure that tells in which directory is a directory located (of which directory it is a subdirectory). The only exception is the root directory.
Besides the name of the sourcefile, the RB_Filename also stores the name of the documentation file.
For each sourcefile there is an RB_Part structure. It contains a pointer (filename) to the RB_Filename and a list (headers) of RB_Header structure containing the headers found in the sourcefile.
Every RB_Header structure contains a pointer (owner) to the RB_Part structure to which it belongs. Headers can form a hierarchy that is used to create sections and subsections in the documentation. To store this hierarchy every RB_header structure contains a pointer (parent) to its parent header. For instance, given the following two headers, SubModule is the parent of SubSubModule.
****h* TopModule/SubModule * ****
****h* SubModule/SubSubModule * ****
In the documentation this creates the sections
1.TopModule 1.1 SubModule 1.1.1 SubSubModule
The RB_Directory and the linked list of RB_Part structures are stored in a RB_Document structure.
During the generation of the documentation ROBODoc tries to create cross links between the mention of a header's name (an object) and the documentation generated from that header (the documentation for the object).
To aid this proces there is an array of RB_link structures. This array is sorted for quick searching. RB_link structures the name of a header and the name of the label under which the documentation can be found in the documentation file.
AUTHOR
See AUTHORS in the archive.
CREATION DATE
20-Dec-94 Jacco van Weert.
MODIFICATION HISTORY
See ChangeLog in the archive. Latest version can be found on:
BUGS
Other bugs? Catch them in a jar and send them to rfsber -(at)- xs4all.nl
UserInterface
[ Top ] [ ROBODoc ] [ Modules ]
FUNCTION
This module contains functions to parse the command line and inform the user about any errors.
copying
[ Top ] [ UserInterface ] [ Variables ]
FUNCTION
Information about the ROBODoc licence.
AUTHOR
Frans
Find_And_Fix_Path
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Searches through the options to find a path. This path is converted to a propper path if it contains errors such as the use of '\' or when it does not start with ./ or a drive name. The option must exist.
SYNOPSIS
static char *Find_And_Fix_Path( char *option_name )
INPUTS
- option_name -- the option name for the path
RESULT
- path -- the path.
SOURCE
{ char *temp; char *temp2; temp = Find_Parameterized_Option( option_name ); assert( temp ); temp = Path_Convert_Win32_to_Unix( temp ); temp2 = Fix_Path( temp ); free( temp ); return temp2; }
Find_Option
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Search configuration.options for a specific option.
SYNOPSIS
int Find_Option( char *option ) /* INPUTS * o option -- the option to be found.
RESULT
- TRUE -- option does exist
- FALSE -- option does not exist
SOURCE
{ unsigned int parameter_nr; int found = FALSE; for ( parameter_nr = 0; parameter_nr < configuration.options.number; parameter_nr++ ) { if ( !RB_Str_Case_Cmp ( configuration.options.names[parameter_nr], option ) ) { found = TRUE; break; } } return found; }
Find_Parameterized_Option
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Search for an option of the form
--a_option_name a_value
in configuration.options.
SYNOPSIS
char *Find_Parameterized_Option( char *optionname )
INPUTS
optionname -- the name of the option to search for.
RESULT
NULL if the option is not found, a pointer to the value otherwise.
NOTES
Results in a Panic if the option is found but no value is specified.
SOURCE
{ return General_Find_Parameterized_Option( configuration.options.number, &( configuration.options. names[0] ), optionname ); }
Fix_Path
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Add a "./" to a path if it does not start with a "./" or does not contain a ":". If the path was "." just add a "/". Adding a "./" simplifies the creating of relative links during the generation process.
SYNOPSIS
static char *Fix_Path( char *path )
INPUTS
- path -- the path to be fixed.
RESULT
A pointer to a newly allocated string containing the path.
SOURCE
{ char *result = 0; if ( !PathBegin_Check( path ) ) { char *prefix = "./"; if ( strcmp( path, "." ) == 0 ) { result = RB_StrDup( prefix ); } else { int l = strlen( path ); l += strlen( prefix ) + 1; result = malloc( l ); assert( result ); result[0] = '\0'; strcat( result, prefix ); strcat( result, path ); } } else { result = RB_StrDup( path ); } return result; }
General_Find_Parameterized_Option
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Search for an option of the form
--a_option_name a_value
SYNOPSIS
static char *General_Find_Parameterized_Option( int n, char **options, char *optionname )
INPUTS
- n -- the number of options in the options array.
- options -- the options array
- optionname -- the name of the option to search for.
RESULT
NULL if the option is not found, a pointer to the value otherwise.
NOTES
Results in a Panic if the option is found but no value is specified.
SOURCE
{ int parameter_nr; char *value = NULL; for ( parameter_nr = 0; parameter_nr < n; parameter_nr++ ) { if ( !RB_Str_Case_Cmp( options[parameter_nr], optionname ) ) { if ( parameter_nr < n - 1 ) { value = options[parameter_nr + 1]; if ( ( value[0] == '-' ) && ( value[1] == '-' ) ) { value = NULL; } } else { /* to few parameters. */ } if ( !value ) { RB_Panic( "you must be more specific" " with the %s option\n", optionname ); } } } return value; }
main
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Get and parse the arguments. Analyse document and generate the documentation. Everything starts from here.
TODO
This function is too long.
SYNOPSIS
int main( int argc, char **argv )
SOURCE
{ struct RB_Document *document = NULL; struct RB_Directory *srctree = NULL; char *optstr = NULL; char *used_rc_file = NULL; long debug = 0; /* TODO, make setlocale work. char * loc; if ( (loc = getenv("LC_CTYPE") ) != NULL ) { printf( ".... %s\n", loc ); setlocale( LC_ALL, loc); } else { setlocale(LC_ALL, ""); } */ whoami = argv[0]; /* global me,myself&i */ /* Init Actions global */ course_of_action = No_Actions( ); /* Read the configuration file. This might contain addition options. */ RB_SetCurrentFile( NULL ); used_rc_file = ReadConfiguration( argc, argv, RB_Find_In_Argv_Parameterized_Option ( argc, argv, "--rc" ) ); /* Force debug mode early if the user wants the debug mode */ debugmode = Find_DebugMode( ); if ( Check_Options( ) == EXIT_FAILURE ) { return EXIT_FAILURE; } if ( Find_Option( "-c" ) ) { printf( "%s", copying ); return EXIT_SUCCESS; } if ( Find_Option( "--version" ) ) { dump_version( ); return EXIT_SUCCESS; } if ( Find_Option( "--config" ) ) { dump_config( ); return EXIT_SUCCESS; } if ( Find_Option( "--help" ) ) { printf( "%s%s%s%s%s%s", use, use_usage, use_options1, use_options2, use_options3, use_authors ); return EXIT_SUCCESS; } output_mode = Find_DocType( ); /* one of the globals that are still left */ if ( output_mode == UNKNOWN ) { Print_Short_Use( ); return EXIT_SUCCESS; } /* First the basics. */ document = RB_Get_RB_Document( ); document->doctype = output_mode; document->actions = Find_Actions( ); debug = document->debugmode = Find_DebugMode( ); document->charset = Find_Parameterized_Option( "--charset" ); document->extension = Find_Parameterized_Option( "--ext" ); document->css = Find_Parameterized_Option( "--css" ); document->compress = Find_Parameterized_Option( "--compress" ); document->section = Find_Parameterized_Option( "--mansection" ); document_title = Find_Parameterized_Option( "--documenttitle" ); optstr = Find_Parameterized_Option( "--first_section_level" ); if ( optstr ) { document->first_section_level = atoi( optstr ); } course_of_action = document->actions; /* a global */ debugmode = document->debugmode; /* a global */ RB_Say( "Using %s for defaults\n", SAY_INFO, used_rc_file ); free( used_rc_file ); /* No longer necessary */ used_rc_file = NULL; if ( document->css ) { document->css = Path_Convert_Win32_to_Unix( document->css ); } if ( ( document->actions.do_index ) && output_mode == TROFF ) { RB_Warning( "Index generation not supported for TROFF format.\n" ); document->actions.do_index = FALSE; } if ( Find_Parameterized_Option( "--doctype_name" ) && Find_Parameterized_Option( "--doctype_location" ) ) { document->doctype_name = Find_Parameterized_Option( "--doctype_name" ); document->doctype_location = Find_Parameterized_Option( "--doctype_location" ); } /* Find tab sizes and tab stops */ Find_Tabstops( ); /* Find master index file name */ Find_And_Install_Document_Name( "--masterindex", HT_MASTERINDEXTYPE ); /* Find source index file name */ Find_And_Install_Document_Name( "--sourceindex", HT_SOURCEHEADERTYPE ); /* Find DOT tool name */ optstr = Find_Parameterized_Option( "--dotname" ); if ( optstr ) { dot_name = optstr; } /* Find number of headers before linebreak */ optstr = Find_Parameterized_Option( "--header_breaks" ); if ( optstr ) { int breaks = atoi( optstr ); if ( breaks == 0 ) { breaks = MAX_HEADER_BREAKS; } header_breaks = breaks; } /* Get extension */ if ( !document->extension ) { document->extension = RB_Get_Default_Extension( document->doctype ); } /* Test if there is a --src and --doc */ if ( !Find_Parameterized_Option( "--src" ) ) { printf( "Error: you need to specify a source" " file or directory with --src.\n" ); Print_Short_Use( ); return EXIT_FAILURE; } if ( !Find_Parameterized_Option( "--doc" ) ) { printf( "Error: you need to specify a documentation file" " or directory with --doc.\n" ); Print_Short_Use( ); return EXIT_FAILURE; } /* What mode are we using? */ if ( Find_Option( "--multidoc" ) ) { char *srcrootname; /* directory */ char *docrootname; srcrootname = Find_And_Fix_Path( "--src" ); if ( !Stat_Path( 'e', srcrootname ) ) { printf( "Error: %s does not exists\n", srcrootname ); Print_Short_Use( ); return EXIT_FAILURE; } if ( !Stat_Path( 'd', srcrootname ) ) { printf( "Error: %s is not a directory\n", srcrootname ); Print_Short_Use( ); return EXIT_FAILURE; } document->srcroot = RB_Get_RB_Path( srcrootname ); docrootname = Find_And_Fix_Path( "--doc" ); Path_Check( srcrootname, docrootname ); document->docroot = RB_Get_RB_Path( docrootname ); srctree = RB_Get_RB_Directory( srcrootname, docrootname ); document->srctree = srctree; RB_Document_Create_Parts( document ); RB_Analyse_Document( document ); RB_Generate_Documentation( document ); RB_Free_RB_Path( document->srcroot ); document->srcroot = 0; RB_Free_RB_Path( document->docroot ); document->docroot = 0; RB_Free_RB_Directory( srctree ); document->srctree = 0; } else if ( output_mode == TROFF ) { RB_Panic( "Only --multidoc is supported for TROFF output.\n" ); } else if ( Find_Option( "--singledoc" ) ) { char *srcrootname; /* directory */ srcrootname = Find_And_Fix_Path( "--src" ); if ( !Stat_Path( 'e', srcrootname ) ) { printf( "Error: %s does not exists\n", srcrootname ); Print_Short_Use( ); return EXIT_FAILURE; } if ( !Stat_Path( 'd', srcrootname ) ) { printf( "Error: %s is not a directory\n", srcrootname ); Print_Short_Use( ); return EXIT_FAILURE; }; document->srcroot = RB_Get_RB_Path( srcrootname ); document->docroot = 0; document->singledoc_name = Find_And_Fix_Path( "--doc" ); srctree = RB_Get_RB_Directory( srcrootname, NULL ); document->srctree = srctree; RB_Document_Create_Parts( document ); RB_Analyse_Document( document ); RB_Generate_Documentation( document ); RB_Free_RB_Directory( srctree ); } else if ( Find_Option( "--singlefile" ) ) { char *srcfile; /* file */ char *docfile; /* file */ document->docroot = 0; docfile = Find_And_Fix_Path( "--doc" ); document->singledoc_name = docfile; srcfile = Find_And_Fix_Path( "--src" ); if ( !Stat_Path( 'e', srcfile ) ) { printf( "Error: %s does not exists\n", srcfile ); Print_Short_Use( ); return EXIT_FAILURE; }; if ( !Stat_Path( 'f', srcfile ) ) { printf( "Error: %s is not a file\n", srcfile ); Print_Short_Use( ); return EXIT_FAILURE; }; document->srctree = RB_Get_RB_SingleFileDirectory( srcfile ); document->srcroot = RB_Get_RB_Path( document->srctree->first_path->name ); RB_Document_Create_Parts( document ); RB_Analyse_Document( document ); RB_Generate_Documentation( document ); RB_Free_RB_Directory( document->srctree ); } else { Print_Short_Use( ); printf ( "\n\nError: Use either --multidoc, --singledoc, or --singlefile\n" ); return EXIT_FAILURE; } RB_Summary( document ); RB_Free_RB_Document( document ); Free_Configuration( ); #ifdef __APPLE__ /* Mac OS X specific: print memory leaks */ if ( debug & SAY_DEBUG ) { char cmd[32]; sprintf( cmd, "/usr/bin/leaks %d", getpid( ) ); system( cmd ); } #endif /* __APPLE__ */ return EXIT_SUCCESS; }
Path_Check
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Test the validity of the doc and source path. The doc path should not be a sub directory of the source path otherwise the generated documentation will be part of the generated documentation if robodoc is run more than once.
SYNOPSIS
static void Path_Check( char *sourcepath, char *docpath )
INPUTS
- sourcepath -- the path to the source files.
- docpath -- the path to the documentation files.
OUTPUT
- error messages
SOURCE
{ if ( docpath ) { int dl; int sl; dl = strlen( docpath ); sl = strlen( sourcepath ); if ( dl >= sl ) { int i; int equal = TRUE; for ( i = 0; i < sl; ++i ) { if ( docpath[i] != sourcepath[i] ) { equal = FALSE; break; } } if ( equal && ( dl == sl ) ) { RB_Panic ( "The source path and document path can not be equal\n" ); } else { /* OK */ } } } }
Path_Convert_Win32_to_Unix
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Although people are supposed to specify all paths with a '/' as seperator, sometimes people on Win32 use '\', this causes problems later on in some other function of robodoc that expect a '/'. So to prevent this we replace all the '\' in a path with '/'
In addition people sometimes add a '/' at the end of the path. We remove it.
SYNOPSIS
static char *Path_Convert_Win32_to_Unix( char *path )
INPUTS
- path -- the path.
RESULT
- path -- the converted path (in a newly allocated block of memory).
SOURCE
{ size_t i; /* First make a copy */ path = RB_StrDup( path ); for ( i = 0; i < strlen( path ); ++i ) { if ( path[i] == '\\' ) { path[i] = '/'; } } /* Remove trailing '/' if there is one. */ if ( path[strlen( path ) - 1] == '/' ) { path[strlen( path ) - 1] = '\0'; } return path; }
PathBegin_Check
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Checks the validity of a path. A path should start with
./
or
/
or
have a ':' some where
SYNOPSIS
static int PathBegin_Check( char *path )
INPUTS
- path -- the path to be cheked.
RESULT
- FALSE -- path is not OK.
- TRUE -- path is OK.
SOURCE
{ int result = FALSE; int l = strlen( path ); if ( l == 1 ) { result = ( path[0] == '.' ); } else if ( l >= 2 ) { result = ( ( path[0] == '.' ) && ( path[1] == '/' ) ) || ( path[0] == '/' ) || ( strchr( path, ':' ) != NULL ); } else { /* Empty */ } return result; }
RB_Find_In_Argv_Parameterized_Option
[ Top ] [ UserInterface ] [ Functions ]
FUNCTION
Search for an option of the form
--a_option_name a_value
in argv. The function is used to look for the
--rc
option that can be used to specify an alternate robodoc configuration file.
SYNOPSIS
char *RB_Find_In_Argv_Parameterized_Option( int argc, char **argv, char *optionname )
INPUTS
- argc -- the argument count as received by main().
- argv -- the array of argument values as received by main()
- optionname -- the name of the option to search for.
RESULT
NULL if the option is not found, a pointer to the value otherwise.
NOTES
Results in a Panic if the option is found but no value is specified.
SOURCE
{ return General_Find_Parameterized_Option( argc, argv, optionname ); }
use
[ Top ] [ UserInterface ] [ Variables ]
NAME
use -- usage string
FUNCTION
Inform the user how to use ROBODoc.
AUTHOR
Koessi
SOURCE
char use[] = /* 1 2 3 4 5 6 7 8 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */ "ROBODoc Version " VERSION " autodocs formatter ($Revision: 1.115 $)\n" "(c) 1994-2010 Frans Slothouber, Petteri Kettunen, \n" " Gergely Budai and Jacco van Weert\n" "ROBODoc comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it\n" "under certain conditions; type `robodoc -c' for details.\n" "\n"; char use_usage[] = "Usage:\n" " robodoc --src <directory> --doc <directory> --multidoc [type] [options]\n" " robodoc --src <directory> --doc <file> --singledoc [type] [options]\n" " robodoc --src <file> --doc <file> --singlefile [type] [options]\n" "\n" "Type:\n" " --html, --rtf, --latex, --ascii, --dbxml, --troff\n" "\n"; char use_options1[] = "Options:\n" " --charset NAME Add character encoding information (html only).\n" " --cmode Use ANSI C grammar in source items (html only).\n" " --config Print configuration info and exit.\n" " --css Specify the stylesheet to use.\n" " --ext EXTENSION Set extension for generated files.\n" " --footless Do not create the foot of a document.\n" " --headless Do not create the head of a document.\n" " --index Add an index.\n"; char use_options2[] = " --internal Also include internal headers.\n" " --internalonly Only include internal headers.\n" " --lock Recognize only one header marker per file.\n" " --nodesc Do not descent into subdirectories.\n" " --no_subdirectories\n" " Do no create documentation subdirectories.\n" " --nopre Do not use <PRE> </PRE> in the HTML output.\n" " --nosort Do not sort the headers.\n" " --nosource Do not include SOURCE items.\n" " --nogeneratedwith\n" " Do not add the 'generated by robodoc' message\n" " at the top of each documentation file.\n" " --ignore_case_when_linking\n" " Ignore the case of the symbols when trying\n" " to create crosslinks.\n"; char use_options3[] = " --rc Specify an alternate configuration file.\n" " --sections Add sections and subsections.\n" " --first_section_level NUMBER\n" " Start the first section not at 1 but at \n" " level NUMBER.\n" " --tabsize NUMBER Set the tab size.\n" " --tabstops a,b,..,n\n" " Set TAB stops \n" " --tell ROBODoc will tell you what it is doing.\n" " --debug same as --tell, but with lots more details.\n" " --toc Add a table of contents.\n" " --version Print version info and exit.\n" " --sectionnameonly\n" " Generate section header with name only.\n" " --compress Only supported by TROFF output format. Defines by which\n" " program manpages will be compressed. Either bzip2 or gzip.\n" " --mansection Manual section where pages will be inserted (default: 3).\n" " --documenttitle TITLE\n" " Set the document title\n" " --altlatex Alternate LaTeX file format (bigger / clearer than normal)\n" " --latexparts Make the first module level as PART in LaTeX output\n" " --syntaxcolors Turn on all syntax highlighting features in SOURCE items\n" " (html only)\n" " --syntaxcolors_enable quotes,squotes,line_comments,block_comments,\n" " keywords,non_alpha\n" " Enable only specific syntax highlighting features in\n" " SOURCE items (html only)\n" " --dotname NAME Specify the name (and path / options) of DOT tool\n" " --masterindex title,filename\n" " Specify the tile and filename for master index page\n" " --sourceindex title,filename\n" " Specify the tile and filename for source files index page\n" " --one_file_per_header\n" " Create a separate documentation file for each header\n" " --header_breaks NUMBER\n" " Insert a linebreak after every NUMBER header names\n" " (default value: 2, set to zero to disable)\n" " --source_line_numbers\n" " Display original source line numbers for SOURCE items\n" " --use_source_comments ITEM\n" " Add found source comment lines to documenatation of ITEM\n" "\n"; char use_authors[] = "Authors/Contributors:\n" " Frans Slothouber, Jacco van Weert, Petteri Kettunen, Bernd Koesling,\n" " Thomas Aglassinger, Anthon Pang, Stefan Kost, David Druffner, Sasha Vasko,\n" " Kai Hofmann, Thierry Pierron, Friedrich Haase, Gergely Budai.\n";