Generator
[ Top ] [ ROBODoc ] [ Modules ]
FUNCTION
This contains routines to generate the documentation from the headers collected from the source code. It contains functionality common for all document types (HTML, RTF etc). The specifics are handled in the modules for each of the several document types.
The behaviour of many of the functions in this module are modified by the global output_mode.
The general call sequence is as follows:
RB_Generate_Documentation +> RB_Generate_SingleDoc +> RB_Generate_Part +> Generate_Header +> Generate_Item_Line +> Generate_Char
BUGS
- Confusing use of doctype and output mode.
NOTES
Might be a good idea to replace all the switch statements with function pointers. So instead of:
switch (output_mode) { case HTML: RB_HTML_Generate_Doc_Start(dest_doc, src_name, name, toc); break; case LATEX: RB_LaTeX_Generate_Doc_Start(dest_doc, src_name, name, toc); break; case RTF: RB_RTF_Generate_Doc_Start(dest_doc, src_name, name, toc); break; case ASCII: RB_ASCII_Generate_Doc_Start(dest_doc, src_name, name, toc); break; case TROFF: RB_TROFF_Generate_Doc_Start(dest_doc, src_name, name, toc); break; default: break; }
we will have
(*rb_generate_doc_start)(dest_doc, src_name, name, toc);
were the function pointers are initialized at program start based on the output mode.
Generate_Char
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate a single character in the current output mode. The individual generators will make sure that special characters are escaped.
SYNOPSIS
void Generate_Char( FILE *dest_doc, int cur_char )
INPUTS
- dest_doc -- destination file.
- cur_char -- character to be generated.
Generate_Header
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate the documentation for all the items found in a header except for any items specified in configuration.ignore_items.
SYNOPSIS
static void Generate_Header( FILE *f, struct RB_header *header, char *docname )
INPUTS
- f -- destination file
- header -- header to be searched.
- srcname -- name of the source file the header was found in.
- docname -- name of the documentation file.
BUGS
This skips the first item body if the first item name was not correctly spelled.
SOURCE
{ struct RB_Item *cur_item; for ( cur_item = header->items; cur_item; cur_item = cur_item->next ) { enum ItemType item_type = cur_item->type; char *name = configuration.items.names[item_type]; if ( Is_Ignore_Item( name ) ) { /* User does not want this item */ } else if ( Works_Like_SourceItem( item_type ) && ( course_of_action.do_nosource ) ) { /* User does not want source items */ } else { Generate_Item( f, header, cur_item, docname ); } } }
Generate_Index
[ Top ] [ Generator ] [ Functions ]
NAME
Generate_Index -- generate index file based on xref files.
SYNOPSIS
static void Generate_Index( struct RB_Document *document )
FUNCTION
Create a master index file. It contains pointers to the documentation generated for each source file, as well as all "objects" found in the source files.
SOURCE
{ switch ( output_mode ) { case TEST: break; case XMLDOCBOOK: break; case HTML: RB_HTML_Generate_Index( document ); break; case LATEX: /* Latex has a index by default */ break; case UNKNOWN: case ASCII: case TROFF: case RTF: default: break; } }
Generate_Item
[ Top ] [ Generator ] [ Functions ]
SYNOPSIS
static void Generate_Item( FILE *f, struct RB_header *header, struct RB_Item *cur_item, char *docname )
FUNCTION
Generate the documentation for a single item.
NOTE
This function is way too long...
SOURCE
{ static int dot_nr = 1; int line_nr; char *dot_type = NULL; FILE *tool = NULL; /* Pipe handler to the tool we use */ enum ItemType item_type = cur_item->type; char *name = configuration.items.names[item_type]; Generate_Item_Name( f, item_type ); RB_Generate_Item_Begin( f, name ); for ( line_nr = 0; line_nr < cur_item->no_lines; ++line_nr ) { struct RB_Item_Line *item_line = cur_item->lines[line_nr]; char *line = item_line->line; /* Plain item lines */ if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_PLAIN ) ) { Format_Line( f, item_line->format ); Generate_Item_Line( f, line, item_type, docname, header ); } /* Last line */ else if ( item_line->kind == ITEM_LINE_END ) { Format_Line( f, item_line->format ); } /* Normal Pipes */ else if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_PIPE ) ) { Format_Line( f, item_line->format ); if ( item_line->pipe_mode == output_mode ) { Pipe_Line( f, line ); } } /* Tool start */ else if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_TOOL_START ) ) { Format_Line( f, item_line->format ); /* Change to docdir */ RB_Change_To_Docdir( docname ); /* Open pipe to tool */ tool = RB_Open_Pipe( line ); /* Get back to working dir */ RB_Change_Back_To_CWD( ); } /* Tool (or DOT) body */ else if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_TOOL_BODY ) ) { if ( tool != NULL ) { fprintf( tool, "%s\n", line ); } } /* Tool end */ else if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_TOOL_END ) ) { /* Close pipe */ RB_Close_Pipe( tool ); tool = NULL; } /* DOT start */ else if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_DOT_START ) ) { Format_Line( f, item_line->format ); /* Get DOT file type */ dot_type = RB_Get_DOT_Type( ); if ( dot_type ) { char pipe_str[TEMP_BUF_SIZE]; /* Change to docdir */ RB_Change_To_Docdir( docname ); snprintf( pipe_str, sizeof( pipe_str ), "%s -T%s -o%s%d.%s", dot_name, dot_type, DOT_GRAPH_NAME, dot_nr, dot_type ); tool = RB_Open_Pipe( pipe_str ); } } /* DOT end */ else if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_DOT_END ) ) { if ( tool ) { /* Close pipe */ RB_Close_Pipe( tool ); tool = NULL; /* Generate link to image */ RB_Generate_DOT_Image_Link( f, dot_nr, dot_type ); /* Get back to working dir */ RB_Change_Back_To_CWD( ); /* Increment dot file number */ dot_nr++; } } /* DOT file include */ else if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_DOT_FILE ) ) { Format_Line( f, item_line->format ); /* Get DOT file type */ dot_type = RB_Get_DOT_Type( ); if ( dot_type ) { FILE *in = NULL, *dot_pipe = NULL; char str[TEMP_BUF_SIZE]; /* Open the dot source */ snprintf( str, sizeof( str ), "%s%s", header->owner->filename->path->name, line ); in = RB_Open_File( str, "r" ); /* Change to docdir */ RB_Change_To_Docdir( docname ); /* Open a pipe to DOT */ snprintf( str, sizeof( str ), "%s -T%s -o%s%d.%s", dot_name, dot_type, DOT_GRAPH_NAME, dot_nr, dot_type ); dot_pipe = RB_Open_Pipe( str ); /* Pipe data to DOT */ while ( fgets( str, sizeof( str ), in ) != NULL ) fputs( str, dot_pipe ); /* Close file handlers */ RB_Close_File( in ); RB_Close_Pipe( dot_pipe ); /* Generate link to image */ RB_Generate_DOT_Image_Link( f, dot_nr, dot_type ); /* Get back to working dir */ RB_Change_Back_To_CWD( ); /* Increment dot file number */ dot_nr++; } } /* Exec item */ else if ( !Works_Like_SourceItem( item_type ) && ( item_line->kind == ITEM_LINE_EXEC ) ) { Format_Line( f, item_line->format ); /* Change to docdir */ RB_Change_To_Docdir( docname ); /* Execute line */ system( line ); /* Get back to working dir */ RB_Change_Back_To_CWD( ); } /* Source lines */ else if ( Works_Like_SourceItem( item_type ) ) { Format_Line( f, item_line->format ); /* Generate line numbers for SOURCE like items */ RB_Generate_Item_Line_Number( f, item_line->line_number, cur_item->max_line_number ); /* Generate item line */ Generate_Item_Line( f, line, item_type, docname, header ); } else { /* This item line is ignored */ } } RB_Generate_Item_End( f, name ); }
Generate_Item_Name
[ Top ] [ Generator ] [ Functions ]
NAME
Generate_Item_Name -- fast&easy
SYNOPSIS
void Generate_Item_Name( FILE *dest_doc, int item_type )
FUNCTION
write the item's name to the doc
INPUTS
- FILE* dest_doc -- destination file
- int item_type -- the type of item
AUTHOR
Koessi
NOTES
uses globals: output_mode
SOURCE
{ char *name = configuration.items.names[item_type]; switch ( output_mode ) { case TEST: RB_TEST_Generate_Item_Name( dest_doc, name ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Item_Name( dest_doc, name ); break; case HTML: RB_HTML_Generate_Item_Name( dest_doc, name ); break; case LATEX: RB_LaTeX_Generate_Item_Name( dest_doc, name ); break; case RTF: RB_RTF_Generate_Item_Name( dest_doc, name ); break; case ASCII: RB_ASCII_Generate_Item_Name( dest_doc, name ); break; case TROFF: RB_TROFF_Generate_Item_Name( dest_doc, name, Works_Like_SourceItem(item_type) ); break; break; case UNKNOWN: default: assert( 0 ); } }
Generate_Label
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate a label that can be used for a link. For instance in HTML this is <a name="label">
SYNOPSIS
void Generate_Label( FILE *dest_doc, char *name )
INPUTS
- dest_doc -- file to be written to
- name -- the label's name.
- output_mode -- global with the current output mode
SOURCE
{ switch ( output_mode ) { case TEST: RB_TEST_Generate_Label( dest_doc, name ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Label( dest_doc, name ); break; case HTML: RB_HTML_Generate_Label( dest_doc, name ); break; case LATEX: /* lowtexx 21.09.2005 11:33 */ RB_LaTeX_Generate_Label( dest_doc, name ); break; case RTF: RB_RTF_Generate_Label( dest_doc, name ); break; case ASCII: /* Doesn't apply */ break; case TROFF: /* Doesn't apply */ break; case UNKNOWN: default: assert( 0 ); } }
Generate_Link
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate a link to another headers documentation.
SYNOPSIS
void Generate_Link( FILE *dest_doc, char *docname, char *file_name, char *label_name, char *function_name )
INPUTS
- dest_doc -- the output file
- docname -- the name of the output file
- file_name -- the name of the file that contains the link's body
- label_name -- the label for the link
- function_name -- the name that is shown for the link in the documentation
SOURCE
{ switch ( output_mode ) { case TEST: RB_TEST_Generate_Link( dest_doc, docname, file_name, label_name, function_name ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Link( dest_doc, docname, file_name, label_name, function_name ); break; case HTML: RB_HTML_Generate_Link( dest_doc, docname, file_name, label_name, function_name, NULL ); break; case RTF: RB_RTF_Generate_Link( dest_doc, docname, file_name, label_name, function_name ); break; case LATEX: RB_LaTeX_Generate_String( dest_doc, function_name ); /* lowtexx 21.09.2005 11:43 */ /* generate a simple link here */ RB_LaTeX_Generate_Link( dest_doc, docname, file_name, label_name, function_name ); break; case UNKNOWN: case ASCII: case TROFF: default: fprintf( dest_doc, "%s", function_name ); } }
RB_Add_Extension
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Add an extension to the filename base based on on the current output mode.
INPUTS
- doctype -- output mode
- name -- the name of the file without extension and with enough room left to add the extension.
OUTPUT
name -- the name of the file including the extension.
SOURCE
void RB_Add_Extension( char *extension, char *name ) { if ( *extension != '.' ) strcat( name, "." ); strcat( name, extension ); }
RB_Generate_BeginSection
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate a section of level depth in the current output mode. This is used for the --sections option. Where each header is placed in a section based on the header hierarchy.
INPUTS
- dest_doc -- the destination file.
- doctype -- document type
- depth -- the level of the section
- name -- the name of the section
- header -- pointer to the header structure
- output_mode -- global with the current output mode.
SOURCE
void RB_Generate_BeginSection( FILE *dest_doc, int depth, char *name, struct RB_header *header ) { switch ( output_mode ) { case TEST: RB_TEST_Generate_BeginSection( dest_doc, depth, name ); break; case XMLDOCBOOK: RB_XMLDB_Generate_BeginSection( dest_doc, depth, name ); break; case HTML: RB_HTML_Generate_BeginSection( dest_doc, depth, name, header ); break; case LATEX: RB_LaTeX_Generate_BeginSection( dest_doc, depth, name, header ); break; case RTF: RB_RTF_Generate_BeginSection( dest_doc, depth, name ); break; case TROFF: /* RB_TROFF_Generate_BeginSection( dest_doc, depth, name ); */ break; case ASCII: RB_ASCII_Generate_BeginSection( dest_doc, depth, name, header ); break; case UNKNOWN: default: assert( 0 ); } }
RB_Generate_Doc_End
[ Top ] [ Generator ] [ Functions ]
NAME
RB_Generate_Doc_End -- generate document trailer.
SYNOPSIS
void RB_Generate_Doc_End( FILE *dest_doc, char *name, char *src_name )
FUNCTION
Generates for depending on the output_mode the text that will be at the end of a document.
INPUTS
- dest_doc - pointer to the file to which the output will be written.
- name - the name of this file.
- output_mode - global variable that indicates the output mode.
NOTES
Doesn't do anything with its arguments, but that might change in the future.
BUGS
SOURCE
{ switch ( output_mode ) { case TEST: RB_TEST_Generate_Doc_End( dest_doc, name ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Doc_End( dest_doc, name ); break; case HTML: RB_HTML_Generate_Doc_End( dest_doc, name, src_name ); break; case LATEX: RB_LaTeX_Generate_Doc_End( dest_doc, name ); break; case RTF: RB_RTF_Generate_Doc_End( dest_doc, name ); break; case TROFF: break; case ASCII: break; case UNKNOWN: default: assert( 0 ); } }
RB_Generate_Doc_Start
[ Top ] [ Generator ] [ Functions ]
NAME
RB_Generate_Doc_Start -- Generate document header.
SYNOPSIS
void RB_Generate_Doc_Start( struct RB_Document *document, FILE *dest_doc, char *src_name, char *title, char toc, char *dest_name, char *charset )
FUNCTION
Generates for depending on the output_mode the text that will be at the start of a document. Including the table of contents.
INPUTS
- dest_doc - pointer to the file to which the output will be written.
- src_name - the name of the source file or directory.
- name - the name of this file.
- output_mode - global variable that indicates the output mode.
- toc - generate table of contens
SEE ALSO
SOURCE
{ switch ( output_mode ) { case TEST: RB_TEST_Generate_Doc_Start( dest_doc, src_name, title, toc ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Doc_Start( document, dest_doc, charset ); break; case HTML: RB_HTML_Generate_Doc_Start( dest_doc, src_name, title, dest_name, charset ); break; case LATEX: RB_LaTeX_Generate_Doc_Start( dest_doc, src_name, title, charset ); break; case RTF: RB_RTF_Generate_Doc_Start( dest_doc, src_name, title, toc ); break; case ASCII: RB_ASCII_Generate_Doc_Start( dest_doc, src_name, title, toc ); break; case TROFF: /* */ ; break; case UNKNOWN: default: ; } }
RB_Generate_Documentation
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate the documentation for all the information contained in a RB_Document structure.
SYNOPSIS
void RB_Generate_Documentation( struct RB_Document *document )
INPUTS
document -- pointer to the RB_Document structure.
SOURCE
{ RB_SetCurrentFile( NULL ); if ( document->actions.do_singledoc ) { RB_Generate_SingleDoc( document ); } else if ( document->actions.do_multidoc ) { RB_Generate_MultiDoc( document ); } else if ( document->actions.do_singlefile ) { RB_Generate_SingleDoc( document ); } }
RB_Generate_DOT_Image_Link
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generates the image link for the created dot graphics
SOURCE
void RB_Generate_DOT_Image_Link( FILE *f, int dot_nr, char *dot_type ) { switch ( output_mode ) { case HTML: fprintf( f, "<img src=\"%s%d.%s\">\n", DOT_GRAPH_NAME, dot_nr, dot_type ); break; case LATEX: fprintf( f, "\\includegraphics{%s%d}\n", DOT_GRAPH_NAME, dot_nr ); break; default: break; } }
RB_Generate_EndSection
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate the end of a section base on the current output mode. The functions is used for the --section option. It closes a section in the current output mode.
INPUTS
- dest_doc -- the destination file.
- doctype --
- depth -- the level of the section
- name -- the name of the section
- output_mode -- global with the current output mode.
SOURCE
void RB_Generate_EndSection( FILE *dest_doc, int depth, char *name ) { switch ( output_mode ) { case TEST: RB_TEST_Generate_EndSection( dest_doc, depth, name ); break; case XMLDOCBOOK: RB_XMLDB_Generate_EndSection( dest_doc, depth, name ); break; case HTML: RB_HTML_Generate_EndSection( dest_doc, depth, name ); break; case LATEX: RB_LaTeX_Generate_EndSection( dest_doc, depth, name ); break; case RTF: RB_RTF_Generate_EndSection( dest_doc, depth, name ); break; case TROFF: /* doesn't apply */ break; case ASCII: RB_HTML_Generate_EndSection( dest_doc, depth, name ); break; case UNKNOWN: default: assert( 0 ); } }
RB_Generate_Header_End
[ Top ] [ Generator ] [ Functions ]
NAME
RB_Generate_Header_End
SYNOPSIS
void RB_Generate_Header_End( FILE *dest_doc, struct RB_header *cur_header )
FUNCTION
Generates for depending on the output_mode the text that will be at the end of a header. This function is used if the option --section is _not_ used.
INPUTS
- dest_doc - pointer to the file to which the output will be written.
- cur_header - pointer to a RB_header structure.
SEE ALSO
RB_Generate_Header_Start, RB_Generate_EndSection, RB_Generate_BeginSection
SOURCE
{ switch ( output_mode ) { /* switch by *koessi */ case TEST: RB_TEST_Generate_Header_End( dest_doc, cur_header ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Header_End( dest_doc, cur_header ); break; case HTML: RB_HTML_Generate_Header_End( dest_doc, cur_header ); break; case LATEX: RB_LaTeX_Generate_Header_End( dest_doc, cur_header ); break; case RTF: RB_RTF_Generate_Header_End( dest_doc, cur_header ); break; case ASCII: RB_ASCII_Generate_Header_End( dest_doc, cur_header ); break; case TROFF: RB_TROFF_Generate_Header_End( dest_doc, cur_header ); break; case UNKNOWN: default: break; } }
RB_Generate_Header_Start
[ Top ] [ Generator ] [ Functions ]
NAME
RB_Generate_Header_Start -- generate header start text.
SYNOPSIS
FILE *RB_Generate_Header_Start( FILE *dest_doc, struct RB_header *cur_header )
FUNCTION
Generates depending on the output_mode the text that will be at the end of each header.
INPUTS
- dest_doc - pointer to the file to which the output will be written.
- cur_header - pointer to a RB_header structure.
SEE ALSO
SOURCE
{ switch ( output_mode ) { case TEST: RB_TEST_Generate_Header_Start( dest_doc, cur_header ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Header_Start( dest_doc, cur_header ); break; case HTML: RB_HTML_Generate_Header_Start( dest_doc, cur_header ); break; case LATEX: RB_LaTeX_Generate_Header_Start( dest_doc, cur_header ); break; case RTF: RB_RTF_Generate_Header_Start( dest_doc, cur_header ); break; case ASCII: RB_ASCII_Generate_Header_Start( dest_doc, cur_header ); break; case TROFF: dest_doc = RB_TROFF_Generate_Header_Start( dest_doc, cur_header ); break; case UNKNOWN: default: assert( 0 ); } return dest_doc; }
RB_Generate_Index_Entry
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate an entry for an auto generated index. This works only for output modes that support this, LaTeX for instance. This has nothting to do with the master index.
SYNOPSIS
void RB_Generate_Index_Entry( FILE *dest_doc, T_RB_DocType doctype, struct RB_header *header )
INPUTS
- dest_doc -- the destination file.
- header -- pointer to the header the index entry is for.
- output_mode -- global with the current output mode.
SOURCE
{ switch ( doctype ) { case TEST: /* TODO */ break; case XMLDOCBOOK: /* TODO */ break; case HTML: /* TODO */ break; case LATEX: RB_LaTeX_Generate_Index_Entry( dest_doc, header ); break; case RTF: /* TODO */ break; case ASCII: /* No index available */ break; case TROFF: /* No index available */ break; case UNKNOWN: default: assert( 0 ); } }
RB_Generate_Item_Begin
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate the begin of an item. This should switch to some preformatted output mode, similar to HTML's <PRE>.
SYNOPSIS
void RB_Generate_Item_Begin( FILE *dest_doc, char *name )
INPUTS
dest_doc -- file to be written to output_mode -- global with the current output mode
SOURCE
{ switch ( output_mode ) { case TEST: RB_TEST_Generate_Item_Begin( dest_doc ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Item_Begin( dest_doc ); break; case HTML: RB_HTML_Generate_Item_Begin( dest_doc, name ); break; case LATEX: RB_LaTeX_Generate_Item_Begin( dest_doc ); break; case RTF: RB_RTF_Generate_Item_Begin( dest_doc ); break; case ASCII: RB_ASCII_Generate_Item_Begin( dest_doc ); break; case TROFF: /* nothing */ break; case UNKNOWN: default: assert( 0 ); } }
RB_Generate_Item_End
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate the end of an item. This should switch back from the preformatted mode. So in HTML it generates the </PRE> of a <PRE> </PRE> pair.
INPUTS
- dest_doc -- file to be written to
- output_mode -- global with the current output mode
SOURCE
void RB_Generate_Item_End( FILE *dest_doc, char *name ) { switch ( output_mode ) { case TEST: RB_TEST_Generate_Item_End( dest_doc ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Item_End( dest_doc ); break; case HTML: RB_HTML_Generate_Item_End( dest_doc, name ); break; case LATEX: if ( piping == TRUE ) { fprintf( dest_doc, "\\begin{verbatim}\n" ); piping = FALSE; } RB_LaTeX_Generate_Item_End( dest_doc ); break; case RTF: RB_RTF_Generate_Item_End( dest_doc ); break; case ASCII: RB_ASCII_Generate_Item_End( dest_doc ); break; case TROFF: /* Doesn't apply */ break; case UNKNOWN: default: assert( 0 ); } }
RB_Generate_Item_Line_Number
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate line numbers for SOURCE like items
SYNOPSIS
void RB_Generate_Item_Line_Number( FILE *dest_doc, int arg_line_number, int max_lines )
INPUTS
- dest_doc -- the file to write to.
- line_number -- the actual line number.
- max_lines -- the maximal line number in this item.
SOURCE
{ /* First check if we should generate line numbers at all */ if ( course_of_action.do_source_line_numbers ) { char fmt[TEMP_BUF_SIZE], str[TEMP_BUF_SIZE]; int len; /* produce the maximal line number as a string */ snprintf( str, sizeof( str ), "%d", max_lines ); /* get the length of the maximal line number */ len = strlen( str ); /* create the formatting string for the line numbers */ snprintf( fmt, sizeof( fmt ), "%%%dd ", len ); /* and create the line number as a string */ snprintf( str, sizeof( str ), fmt, arg_line_number ); /* handle the various output modes */ switch ( output_mode ) { case ASCII: RB_ASCII_Generate_Item_Line_Number( dest_doc, str ); break; case HTML: RB_HTML_Generate_Item_Line_Number( dest_doc, str ); break; case LATEX: RB_LaTeX_Generate_Item_Line_Number( dest_doc, str ); break; case RTF: RB_RTF_Generate_Item_Line_Number( dest_doc, str ); break; case TROFF: RB_TROFF_Generate_Item_Line_Number( dest_doc, str ); break; case XMLDOCBOOK: RB_XMLDB_Generate_Item_Line_Number( dest_doc, str ); break; default: break; } } }
RB_Generate_MultiDoc
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Create documentation by creating a file for each individual source file that was scanned.
SYNOPSIS
void RB_Generate_MultiDoc( struct RB_Document *document )
INPUTS
document -- pointer to the RB_Document structure.
SOURCE
{ struct RB_Part *i_part; FILE *document_file = NULL; RB_Document_Determine_DocFilePaths( document ); RB_Document_Create_DocFilePaths( document ); if ( document->actions.do_one_file_per_header ) { RB_Document_Split_Parts( document ); } RB_Document_Determine_DocFileNames( document ); RB_Document_Collect_Headers( document ); if ( document->actions.do_nosort ) { /* Nothing */ } else { RB_Document_Sort_Headers( document ); } RB_Document_Link_Headers( document ); RB_Loop_Check( document ); RB_Fill_Header_Filename( document ); RB_Name_Headers( document->headers, document->no_headers ); RB_Sort_Items( document->headers, document->no_headers ); RB_CollectLinks( document, document->headers, document->no_headers ); if ( output_mode == HTML ) { RB_Create_CSS( document ); } for ( i_part = document->parts; i_part != NULL; i_part = i_part->next ) { char *srcname = Get_Fullname( i_part->filename ); char *docname = RB_Get_FullDocname( i_part->filename ); /* Nothing found in this part, do not generate it */ if ( i_part->headers == 0 ) continue; if ( output_mode != TROFF ) { document_file = RB_Open_Documentation( i_part ); RB_Generate_Doc_Start( document, document_file, srcname, srcname, 1, docname, document->charset ); Generate_Begin_Navigation( document_file ); if ( document->actions.do_one_file_per_header ) { RB_HTML_Generate_Nav_Bar_One_File_Per_Header( document, document_file, i_part-> headers ); } else { Generate_IndexMenu( document_file, docname, document ); } Generate_End_Navigation( document_file ); Generate_Begin_Content( document_file ); if ( ( document->actions.do_toc ) && document->no_headers ) { RB_Generate_TOC_2( document_file, document->headers, document->no_headers, i_part, docname ); } RB_Generate_Part( document_file, document, i_part ); Generate_End_Content( document_file ); RB_Generate_Doc_End( document_file, docname, srcname ); fclose( document_file ); } else { RB_Generate_Part( document_file, document, i_part ); } } if ( document->actions.do_index ) { Generate_Index( document ); } RB_Free_Links( ); }
RB_Generate_Part
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate the documention for all the headers found in a single source file.
SYNOPSIS
void RB_Generate_Part( FILE *document_file, struct RB_Document *document, struct RB_Part *part )
INPUTS
- document_file -- The file were it stored.
- document -- All the documentation.
- part -- pointer to a RB_Part that contains all the headers found in a single source file.
SOURCE
{ struct RB_header *i_header; char *docname = NULL; char *srcname = Get_Fullname( part->filename ); RB_Say( "generating documentation for file \"%s\"\n", SAY_INFO, srcname ); if ( document->actions.do_singledoc ) { docname = document->singledoc_name; } else if ( document->actions.do_multidoc ) { docname = RB_Get_FullDocname( part->filename ); } else if ( document->actions.do_singlefile ) { docname = document->singledoc_name; } else { assert( 0 ); } if ( output_mode == TROFF ) { RB_TROFF_Set_Param( document->compress, document->section ); } for ( i_header = part->headers; i_header; i_header = i_header->next ) { RB_Say( "generating documentation for header \"%s\"\n", SAY_INFO, i_header->name ); document_file = RB_Generate_Header_Start( document_file, i_header ); RB_Generate_Nav_Bar( document, document_file, i_header ); RB_Generate_Index_Entry( document_file, document->doctype, i_header ); Generate_Header( document_file, i_header, docname ); RB_Generate_Header_End( document_file, i_header ); } }
RB_Generate_Section
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Generate the documentation for a header and all its childern.
INPUTS
- document_file -- destination file
- parent -- the parent of the header for which the documentation is to be generated.
- document -- pointer to the RB_Document structure.
- depth -- level of sectioning ( 1 1.1 1.1.1 etc)
SYNOPSIS
void RB_Generate_Section( FILE *document_file, struct RB_header *parent, struct RB_Document *document, int depth )
NOTE
This is a recursive function.
SEE ALSO
SOURCE
{ unsigned long i; char *headername; /* We pass either modulename/name or just the name */ if ( course_of_action.do_sectionnameonly ) { headername = parent->function_name; } else { headername = parent->name; } switch ( output_mode ) { case XMLDOCBOOK: { RB_Generate_BeginSection( document_file, depth, headername, parent ); /* Docbook output does not like the labels to be * generated before the <section> part */ Generate_Label( document_file, parent->unique_name ); Generate_Label( document_file, parent->name ); } break; /* lowtexx 21.09.2005 11:37 */ case LATEX: { RB_Generate_BeginSection( document_file, depth, headername, parent ); /* We have to start section before labeling in latex */ Generate_Label( document_file, parent->unique_name ); Generate_Label( document_file, parent->name ); } break; /* --- */ default: { Generate_Label( document_file, parent->unique_name ); Generate_Label( document_file, parent->name ); RB_Generate_BeginSection( document_file, depth, headername, parent ); } break; } RB_Generate_Nav_Bar( document, document_file, parent ); RB_Generate_Index_Entry( document_file, document->doctype, parent ); Generate_Header( document_file, parent, document->singledoc_name ); for ( i = 0; i < document->no_headers; ++i ) { struct RB_header *header = ( document->headers )[i]; if ( header->parent == parent ) { RB_Generate_Section( document_file, header, document, depth + 1 ); } else { /* Leeg */ } } RB_Generate_EndSection( document_file, depth, parent->name ); }
RB_Generate_Sections
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Creates the documentation for all headers found in all source files. The order in which they are generated depends on the header hierarchy. First the top level header's documentation is generated then, the documentation for all it's childern, then the next top level header's documentation is generated. This is a recursive proces. The idea is to create something like:
1. Parentheader1 1.1 Child1 1.2 Child2 1.2.1 Child's child1 2. Parentheader2
etc
SYNOPSIS
void RB_Generate_Sections( FILE *document_file, struct RB_Document *document )
INPUTS
- document_file -- destination file.
- document -- pointer to the RB_Document structure.
SOURCE
{ unsigned long i; int depth = 1; struct RB_header *header; depth = document->first_section_level; RB_Say( "Generating Sections\n", SAY_INFO ); for ( i = 0; i < document->no_headers; ++i ) { header = ( document->headers )[i]; if ( header->parent ) { /* This will be in one of the subsections */ } else { RB_Generate_Section( document_file, header, document, depth ); } } }
RB_Generate_SingleDoc
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Create documentation by creating a single file for all individual source file that were scanned.
This function is called when the option --singledoc is used. Based on whether the option --sections is used this function then calls RB_Generate_Sections or RB_Generate_Part
SYNOPSIS
void RB_Generate_SingleDoc( struct RB_Document *document )
INPUTS
document -- pointer to the RB_Document structure.
SOURCE
{ FILE *document_file; struct RB_Part *i_part; RB_Document_Collect_Headers( document ); if ( document->actions.do_nosort ) { /* Nothing */ } else { RB_Document_Sort_Headers( document ); } RB_Document_Link_Headers( document ); RB_Loop_Check( document ); RB_Fill_Header_Filename( document ); RB_Name_Headers( document->headers, document->no_headers ); RB_Sort_Items( document->headers, document->no_headers ); RB_CollectLinks( document, document->headers, document->no_headers ); for ( i_part = document->parts; i_part != NULL; i_part = i_part->next ) { RB_Set_FullDocname( i_part->filename, document->singledoc_name ); } if ( output_mode == HTML ) { RB_Create_CSS( document ); } document_file = RB_Open_SingleDocumentation( document ); assert( document->parts->filename->name ); RB_Generate_Doc_Start( document, document_file, document->srcroot->name, document->singledoc_name, 1, document->singledoc_name, document->charset ); if ( ( document->actions.do_toc ) && document->no_headers ) { RB_Generate_TOC_2( document_file, document->headers, document->no_headers, NULL, document->parts->filename->name ); } if ( document->actions.do_sections ) { RB_Generate_Sections( document_file, document ); } else { for ( i_part = document->parts; i_part != NULL; i_part = i_part->next ) { RB_Generate_Part( document_file, document, i_part ); } } RB_Generate_Doc_End( document_file, "singledoc", document->srcroot->name ); fclose( document_file ); RB_Free_Links( ); }
RB_Generate_TOC_2
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Create a Table of Contents based on the headers found in _all_ source files. There is also a function to create a table of contents based on the headers found in a single source file RB_Generate_TOC_1
SYNOPSIS
void RB_Generate_TOC_2( FILE *dest_doc, struct RB_header **headers, int count, struct RB_Part *owner, char *dest_name )
INPUTS
- dest_doc -- the destination file.
- headers -- an array of pointers to all the headers.
- count -- the number of pointers in the array.
- output_mode -- global with the current output mode.
- owner -- The owner of the TOC. Only the headers that are owned by this owner are included in the TOC. Can be NULL, in which case all headers are included.
SOURCE
{ switch ( output_mode ) { case TEST: break; case TROFF: break; case XMLDOCBOOK: break; case HTML: RB_HTML_Generate_TOC_2( dest_doc, headers, count, owner, dest_name ); break; case LATEX: /* LaTeX has it's own mechanism for creating * a table of content */ break; case RTF: RB_RTF_Generate_TOC_2( dest_doc, headers, count ); break; case ASCII: /* TODO: No TOC in ASCII mode */ break; case UNKNOWN: default: assert( 0 ); } }
RB_Get_DOT_Type
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Returns the type of the DOT file for the given output mode
SOURCE
char *RB_Get_DOT_Type( void ) { switch ( output_mode ) { case HTML: return DOT_HTML_TYPE; break; case LATEX: return DOT_LATEX_TYPE; break; default: break; } return NULL; }
RB_Get_SubIndex_FileName
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Get the name of the master index file for a specific header_type.
SYNOPSIS
char *RB_Get_SubIndex_FileName( char *docroot, char *extension, struct RB_HeaderType *header_type )
INPUTS
- docroot -- the path to the documentation directory.
- extension -- the extension for the file
- header_type -- the header type
RESULT
a pointer to a freshly allocated string.
NOTES
Has too many parameters.
SOURCE
{ size_t l; char *filename; assert( docroot ); l = strlen( docroot ); l += RB_Get_Len_Extension( extension ); l += strlen( docroot ); l += strlen( header_type->fileName ); filename = ( char * ) malloc( l + 2 ); assert( filename ); filename[0] = '\0'; strcat( filename, docroot ); strcat( filename, header_type->fileName ); RB_Add_Extension( extension, filename ); return filename; }
RB_Name_Headers
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Give all headers a unique name. This makes sure that if two headers have the same name linking to one of the headers still works.
SYNOPSIS
void RB_Name_Headers( struct RB_header **headers, long count )
SOURCE
#define MAX_UNIQUE_ID_LENGTH 80
{
int i;
char id[MAX_UNIQUE_ID_LENGTH + 1];
RB_Say( "Assigning headers a unique name.\n", SAY_DEBUG );
for ( i = 0; i < count; ++i )
{
struct RB_header *header;
header = headers[i];
sprintf( id, "robo%d", i );
header->unique_name = RB_StrDup( id );
}
}
RB_Sort_Items
[ Top ] [ Generator ] [ Functions ]
FUNCTION
Sort the items in all the headers according to the order specified in the 'item order' block in the robodoc.rc file.
SYNOPSIS
static void RB_Sort_Items( struct RB_header **headers, long header_count )
SOURCE
{ int n_order = configuration.item_order.number; if ( n_order ) { int i = 0; int j = 0; int max_number_of_items = 0; struct RB_Item **items = NULL; struct RB_Item **items_sorted = NULL; RB_Say( "Sorting items in %d headers.\n", SAY_DEBUG, header_count ); /* Compute the maximum number of items in any given header */ for ( j = 0; j < header_count; ++j ) { struct RB_header *header; struct RB_Item *item; int item_count = 0; header = headers[j]; for ( item = header->items; item; item = item->next ) { ++item_count; } if ( item_count > max_number_of_items ) { max_number_of_items = item_count; } } /* Allocate an array for the items, this makes it easier to * sort. */ RB_Say( "Largest header has %d items.\n", SAY_DEBUG, max_number_of_items ); if ( max_number_of_items == 0 ) { /* No items in any of the headers, do nothing */ } else { items = calloc( max_number_of_items, sizeof( struct RB_Item * ) ); items_sorted = calloc( max_number_of_items, sizeof( struct RB_Item * ) ); /* Sort items */ for ( j = 0; j < header_count; ++j ) { struct RB_header *header = NULL; struct RB_Item *item = NULL; int item_index = 0; int sorted_item_index = 0; int item_count = 0; header = headers[j]; /* Copy item pointers to array */ for ( item = header->items; item; item = item->next, ++item_index ) { items[item_index] = item; items_sorted[item_index] = item; }; item_count = item_index; if ( item_count == 0 ) { /* No items in this header, do nothing. */ } else { assert( item_count <= max_number_of_items ); /* First copy the items in the order that is defined in * item_order[] to sorted_items[] */ sorted_item_index = 0; for ( i = 0; i < n_order; ++i ) { for ( item_index = 0; item_index < item_count; ++item_index ) { if ( items[item_index] ) { if ( strcmp ( configuration.items. names[items[item_index]->type], configuration.item_order.names[i] ) == 0 ) { /* copy to items_sorted */ items_sorted[sorted_item_index] = items[item_index]; ++sorted_item_index; items[item_index] = NULL; } } } } /* Then copy the remaining items to items_sorted[] */ for ( item_index = 0; item_index < item_count; ++item_index ) { if ( items[item_index] ) { /* copy to items_sorted */ items_sorted[sorted_item_index] = items[item_index]; ++sorted_item_index; items[item_index] = NULL; } } assert( sorted_item_index == item_count ); /* Now copy the items in items_sorted[] back into the linked list in * the header */ if ( item_count > 1 ) { /* Chain all the items */ for ( item_index = 0; item_index < item_count - 1; ++item_index ) { items_sorted[item_index]->next = items_sorted[item_index + 1]; } } assert( item_count > 0 ); items_sorted[item_count - 1]->next = NULL; /* now link the first item to the header. */ header->items = items_sorted[0]; } } free( items_sorted ); free( items ); } } RB_Say( "Done sorting items in %d headers.\n", SAY_DEBUG, header_count ); }