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

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


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

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

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

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

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

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

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

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

SEE ALSO

RB_Generate_Doc_End

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

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

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

SEE ALSO

RB_Generate_Header_End

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

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

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

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

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

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

RB_Generate_Sections

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

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

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

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 );
}