Links
[ Top ] [ ROBODoc ] [ Modules ]
FUNCTION
This module contains functions to manipulate links. Links are derived from headers. They are used to create links in the documentation between a word and the part of the documentation that explains something about that word. (For instance a function name or variable name). In addition to the links derived from the headers links are also derived from the names of all the sourcefiles.
MODIFICATION HISTORY
????-??-?? Frans Slothouber V1.0 2003-02-03 Frans Slothouber Refactoring
Find_Link
[ Top ] [ Links ] [ Functions ]
NAME
Find_Link -- try to match word with a link
FUNCTION
Searches for the given word in the list of links and headers. There are three passes (or four, when the C option is selected). Each pass uses a different definition of "word":
- In the first pass it is any thing that ends with a 'space', a '.' or a ','.
- In the second pass it is any string that consists of alpha numerics, '_', ':', '.', or '-'.
- In the third pass (for C) it is any string that consists of alpha numerics or '_'.
SYNOPSIS
int Find_Link( char *word_begin, char **object_name, char **label_name, char **file_name )
INPUTS
- word_begin - pointer to a word (a string).
- object_name - pointer to a pointer to a string
- file_name - pointer to a pointer to a string
SIDE EFFECTS
label_name & file_name are modified
RESULT
- object_name -- points to the object if a match was found, NULL otherwise.
- file_name -- points to the file name if a match was found, NULL otherwise.
- label_name -- points to the labelname if a match was found,
- TRUE -- a match was found.
- FALSE -- no match was found.
NOTES
This is a rather sensitive algorithm. Don't mess with it too much.
SOURCE
{ char *cur_char = NULL, old_char; int low_index, high_index, cur_index, state, pass; unsigned int length = 0; for ( pass = 0; pass < 3; pass++ ) { switch ( pass ) { case 0: { for ( cur_char = word_begin; ( *cur_char == '_' ) || utf8_isalnum( *cur_char ) || utf8_ispunct( *cur_char ); cur_char++ ); break; } case 1: { for ( cur_char = word_begin; utf8_isalnum( *cur_char ) || ( *cur_char == '_' ) || ( *cur_char == '-' ) || ( *cur_char == '.' ) || ( *cur_char == ':' ); cur_char++ ); break; } case 2: { for ( cur_char = word_begin; utf8_isalnum( *cur_char ) || ( *cur_char == '_'); cur_char++ ); break; } } if ( ( ( *( cur_char - 1 ) ) == ',' ) || ( ( *( cur_char - 1 ) ) == '.' ) ) { cur_char--; } old_char = *cur_char; *cur_char = '\0'; /* * End the word with a '\0' */ if ( strlen( word_begin ) == length ) { /* Do not test the same word over and over. If * the current string and the string of the previous * pass are the same length, they are the same. */ /* RB_Say ("Skipping (pass %d) \"%s\"\n", SAY_INFO, pass, word_begin); */ } else { length = strlen( word_begin ); /* RB_Say ("Testing (pass %d) \"%s\"\n", SAY_INFO, pass, word_begin); */ /* * Search case sensitive for a link */ for ( cur_index = 0, low_index = 0, high_index = link_index_size - 1; high_index >= low_index; ) { cur_index = ( high_index - low_index ) / 2 + low_index; state = strcmp( word_begin, case_sensitive_link_index[cur_index]->object_name ); if ( state < 0 ) { high_index = cur_index - 1; } else if ( state == 0 ) { *object_name = case_sensitive_link_index[cur_index]->object_name; *label_name = case_sensitive_link_index[cur_index]->label_name; *file_name = case_sensitive_link_index[cur_index]->file_name; RB_Say( "linking \"%s\"->\"%s\" from \"%s\"\n", SAY_DEBUG, word_begin, *object_name, *file_name ); *cur_char = old_char; return ( TRUE ); } else if ( state > 0 ) { low_index = cur_index + 1; } } /* * Search case insensitive for a link. * But only when the user asks for this. */ if ( course_of_action.do_ignore_case_when_linking ) { for ( cur_index = 0, low_index = 0, high_index = link_index_size - 1; high_index >= low_index; ) { cur_index = ( high_index - low_index ) / 2 + low_index; state = RB_Str_Case_Cmp( word_begin, link_index[cur_index]->object_name ); if ( state < 0 ) { high_index = cur_index - 1; } else if ( state == 0 ) { *object_name = link_index[cur_index]->object_name; *label_name = link_index[cur_index]->label_name; *file_name = link_index[cur_index]->file_name; RB_Say( "linking \"%s\"->\"%s\" from \"%s\"\n", SAY_DEBUG, word_begin, *object_name, *file_name ); *cur_char = old_char; return ( TRUE ); } else if ( state > 0 ) { low_index = cur_index + 1; } } } } *cur_char = old_char; *file_name = NULL; *object_name = NULL; *label_name = NULL; } return ( FALSE ); }
RB_Alloc_Link
[ Top ] [ Links ] [ Functions ]
NAME
RB_Alloc_Link -- oop
FUNCTION
allocate struct + strings
SYNOPSIS
static struct RB_link * RB_Alloc_Link( char *label_name, char *object_name, char *file_name )
INPUTS
char *label_name -- strings to copy into the link char *file_name
RESULT
struct RB_link * -- ready-to-use
AUTHOR
Koessi
SEE ALSO
RB_StrDup(), RB_Free_Link()
SOURCE
{ struct RB_link *new_link; assert( object_name ); assert( label_name ); assert( file_name ); RB_Say( "Allocating a link (%s %s %s)\n", SAY_DEBUG, object_name, label_name, file_name ); new_link = malloc( sizeof( struct RB_link ) ); memset( new_link, 0, sizeof( struct RB_link ) ); new_link->file_name = RB_StrDup( file_name ); new_link->object_name = RB_StrDup( object_name ); new_link->label_name = RB_StrDup( label_name ); return ( new_link ); }
RB_CollectLinks
[ Top ] [ Links ] [ Functions ]
FUNCTION
Convert header information into link information.
RB_header -> RB_link conversion
SYNOPSIS
void RB_CollectLinks( struct RB_Document *document, struct RB_header **headers, unsigned long count )
INPUTS
- document --
- headers -- the array with headers.
- count -- number of headers in the array
OUTPUT
- link_index -- an array with links
- link_index_size -- the number of links in the array.
SOURCE
{ unsigned long i, j; int k; struct RB_Part *i_part; for ( i = j = 0; i < count; ++i ) { j += headers[i]->no_names - 1; } link_index_size = count + j; if ( ( document->actions.do_multidoc ) && ! ( document->actions.do_one_file_per_header ) ) { for ( i_part = document->parts; i_part; i_part = i_part->next ) { if ( i_part->headers ) { link_index_size++; } } } link_index = ( struct RB_link ** ) calloc( link_index_size, sizeof( struct RB_link ** ) ); case_sensitive_link_index = ( struct RB_link ** ) calloc( link_index_size, sizeof( struct RB_link ** ) ); for ( i = j = 0; i < count; ++i ) { struct RB_link *link; struct RB_header *header; header = headers[i]; assert( header->unique_name ); assert( header->file_name ); for( k = 0; k < header->no_names; j++, k++ ) { link = RB_Alloc_Link( header->unique_name, function_name(header->names[k]), header->file_name ); link->htype = header->htype; link->is_internal = header->is_internal; link_index[j] = link; case_sensitive_link_index[j] = link; } } /* If we are in multidoc mode, we also create links * for all the source files. */ if ( ( document->actions.do_multidoc ) && /* but not for one file per header multidocs */ ! ( document->actions.do_one_file_per_header ) ) { for ( i_part = document->parts; i_part; i_part = i_part->next ) { if ( i_part->headers ) { struct RB_link *link; link = RB_Alloc_Link( "robo_top_of_doc", i_part->filename->name, RB_Get_FullDocname( i_part->filename ) ); i_part->filename->link = link; link->htype = RB_FindHeaderType( HT_SOURCEHEADERTYPE ); link_index[j] = link; case_sensitive_link_index[j] = link; ++j; } else { i_part->filename->link = NULL; } } } /* Sort all the links so we can use a binary search */ RB_QuickSort( (void **)link_index, 0, link_index_size - 1, link_cmp ); RB_QuickSort( (void **)case_sensitive_link_index, 0, link_index_size - 1, case_sensitive_link_cmp ); }
RB_Free_Link
[ Top ] [ Links ] [ Functions ]
NAME
RB_Free_Link -- oop
FUNCTION
free struct + strings
SYNOPSIS
void RB_Free_Link( struct RB_link *arg_link )
INPUTS
struct RB_link *link
AUTHOR
Koessi
SEE ALSO
RB_Alloc_Link(), RB_Close_The_Shop()
SOURCE
{ if ( arg_link ) { if ( arg_link->label_name ) { free( arg_link->label_name ); } if ( arg_link->file_name ) { free( arg_link->file_name ); } free( arg_link ); } }
RB_Free_Links
[ Top ] [ Links ] [ Functions ]
FUNCTION
Deallocate all the memory used to store the links.
SYNOPSIS
void RB_Free_Links( void )
INPUTS
- link_index_size
- link_index[]
BUGS
Should use RB_Free_Link instead of doing everything by it self.
SOURCE
{ struct RB_link *cur_link; unsigned int i; for ( i = 0; i < link_index_size; ++i ) { cur_link = link_index[i]; free( cur_link->object_name ); free( cur_link->label_name ); free( cur_link->file_name ); free( cur_link ); } free( link_index ); }