Configuration
[ Top ] [ ROBODoc ] [ Modules ]
FUNCTION
Functions to access the ROBODoc configuration and configuration file (robodoc.rc) or the file specified with the --rc option.
The robodoc.rc file consists of a number of blocks. Each block starts with a line of the form
<block name>:
This is followed by a number of lines of data. Each line starts with at least one space followed by the actual data.
This module parses this data and stores it in the global configuration.
NOTES
Is missing a lot of documentation.
You can not use RB_Say() in this module since the --tell flag won't be parsed until after this module has finished.
add_keywords_to_hash_table
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Initalize hash table and add all keywords from configuration.keywords to the hash table
SOURCE
void add_keywords_to_hash_table( void ) { unsigned int i; /* If nothing to add, exit */ if ( !configuration.keywords.number ) return; /* Make some allocations */ allocate_keywords_hash_table( ); /* Add keywords to hash table */ for ( i = 0; i < configuration.keywords.number; i++ ) { add_to_keywords_hash_table( configuration.keywords.names[i] ); } }
add_to_keywords_hash_table
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Add a keyword to the hash table
SYNOPSIS
void add_to_keywords_hash_table( char *keyword )
INPUTS
keyword -- The keyword string
SOURCE
{ struct keywords_hash_s *tmp, **curr; unsigned long hash; /* Allocate space for new entry in hash table */ tmp = RB_malloc( sizeof( struct keywords_hash_s ) ); /* and initialise it */ tmp->keyword = keyword; tmp->next = NULL; /* Calculate hash value */ hash = Hash_Keyword( keyword, strlen( keyword ) ); /* Seek to last element in hash table row */ for ( curr = &( keywords_hash[hash] ); *curr; curr = &( ( *curr )->next ) ); /* Insert entry into hash table */ *curr = tmp; }
allocate_keywords_hash_table
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Allocates space for the keyword hash table.
The size of the table depends on the number of keywords rounded up to the next power of two.
SYNOPSIS
void allocate_keywords_hash_table( void )
SOURCE
{ unsigned int i; /* Calculate hash table size (powers of two) */ for ( keywords_hash_mask = 2; keywords_hash_mask < configuration.keywords.number; keywords_hash_mask <<= 1 ); keywords_hash_mask -= 1; /* Allocate space for hash table */ keywords_hash = RB_malloc( ( keywords_hash_mask + 1 ) * sizeof( struct keywords_hash_s * ) ); /* Zero out all rows */ for ( i = 0; i <= keywords_hash_mask; i++ ) { keywords_hash[i] = NULL; } }
c_keywords
[ Top ] [ Configuration ] [ Variables ]
FUNCTION
The default C keywords.
SOURCE
static char *c_keywords[] = { /* ANSI C Keywords */ "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while", /* Some preprocessor directives */ "#include", "#define", "#undef", "#if", "#else", "#elif", "#endif", "#ifdef", "#ifndef", "#pragma", NULL, /* don't delete, so we can count how many there are... */ }; /* C comments */ #define C_LINE_COMMENT "//" #define C_BLOCK_COMMENT_START "/*" #define C_BLOCK_COMMENT_END "*/"
configuration
[ Top ] [ Configuration ] [ Variables ]
FUNCTION
This global stores all the configuration parameters specified on the command line and in the robodoc.rc file.
SOURCE
struct RB_Configuration configuration;
default_item_names
[ Top ] [ Configuration ] [ Variables ]
FUNCTION
Defines the names of items that ROBODoc recognized as items by default if none are specified in the robodoc.rc file.
SOURCE
static char *default_item_names[] = { "SOURCE", /* source code inclusion */ "NAME", /* Item name + short description */ "COPYRIGHT", /* who own the copyright : "(c) <year>-<year> by <company/person>" */ "SYNOPSIS", "USAGE", /* how to use it */ "FUNCTION", "DESCRIPTION", "PURPOSE", /* what does it */ "AUTHOR", /* who wrote it */ "CREATION DATE", /* when did the work start */ "MODIFICATION HISTORY", "HISTORY", /* who done what changes when */ "INPUTS", "ARGUMENTS", "OPTIONS", "PARAMETERS", "SWITCHES", /* what can we feed into it */ "OUTPUT", "SIDE EFFECTS", /* what output will be made */ "RESULT", "RETURN VALUE", /* what do we get returned */ "EXAMPLE", /* a clear example of the items use */ "NOTES", /* any annotations */ "DIAGNOSTICS", /* diagnostical output */ "WARNINGS", "ERRORS", /* warning & error-messages */ "BUGS", /* known bugs */ "TODO", "IDEAS", /* what to implement next & ideas */ "PORTABILITY", /* where does it come from, where will it work */ "SEE ALSO", /* references */ "METHODS", "NEW METHODS", /* oop methods */ "ATTRIBUTES", "NEW ATTRIBUTES", /* oop attributes */ "TAGS", /* tagitem description */ "COMMANDS", /* command description */ "DERIVED FROM", /* oop super class */ "DERIVED BY", /* oop sub class */ "USES", "CHILDREN", /* what modules are used by this one */ "USED BY", "PARENTS", /* which modules do use this */ NULL, /* don't delete, so we can count how many there are... */ };
Find_Keyword
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Find a keyword in the hash table
SYNOPSIS
char *Find_Keyword( char *keyword, int len )
INPUTS
- keyword -- The keyword string
- len -- The length of the keyword string
RETURN VALUE
- pointer to the found keyword string in hash table or
- NULL if the keyword is not found
SOURCE
{ unsigned long hash; struct keywords_hash_s *curr; /* Calculate hash value */ hash = Hash_Keyword( keyword, len ); /* Seek through hash table row */ for ( curr = keywords_hash[hash]; curr; curr = curr->next ) { /* Check for keyword in row element */ if ( !strncmp( keyword, curr->keyword, len ) ) { /* Found it! */ return curr->keyword; } } /* Keyword not found */ return NULL; }
Find_Parameter_Char
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Checks for the existence of a given configuration parameter (Character match)
SOURCE
char *Find_Parameter_Char( struct Parameters *params, char param ) { unsigned int i; for ( i = 0; i < params->number; i++ ) { if ( params->names[i][0] == param ) { /* found it */ return params->names[i]; } } /* parameter not found */ return NULL; }
Find_Parameter_Exact
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Checks for the existence of a given configuration parameter (exact string match)
SOURCE
char *Find_Parameter_Exact( struct Parameters *params, char *paramname ) { unsigned int i; /* we are looking for an exact match */ for ( i = 0; i < params->number; i++ ) { if ( !strcmp( params->names[i], paramname ) ) { /* found it */ return params->names[i]; } } /* parameter not found */ return NULL; }
Find_Parameter_Partial
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Checks for the existence of a given configuration parameter (partial string match)
SOURCE
char *Find_Parameter_Partial( struct Parameters *params, char *paramname ) { unsigned int i; /* we are looking for a not exact match */ for ( i = 0; i < params->number; i++ ) { if ( !strncmp ( params->names[i], paramname, strlen( params->names[i] ) ) ) { /* found it */ return params->names[i]; } } /* parameter not found */ return NULL; }
GetParameters
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Parse a line of text and store the individual words in a Parameters structure. Words are seperated by spaces, the exception are words surrounded by quotes. So:
aap noot mies "back to the future"
contains four words.
INPUTS
- line -- the line of text.
- parameters -- the set of parameters
SOURCE
static void GetParameters( char *line, struct Parameters *parameters ) { int i; int n = strlen( line ); /* Remove any spaces at the end of the line */ for ( i = n - 1; i >= 0 && utf8_isspace( line[i] ); --i ) { line[i] = '\0'; } assert( i > 0 ); /* If i <= 0 then the line was empty and that cannot be, because this is supposed to be a parameter */ /* Skip any white space at the begin of the line. */ n = strlen( line ); for ( i = 0; i < n && utf8_isspace( line[i] ); ++i ) { /* Empty */ } line += i; n = strlen( line ); for ( i = 0; i < n; /* empty */ ) { char *name = line; if ( line[i] == '"' ) { /* It is quoted string, fetch everything until * the next quote */ ++name; /* skip the double quote */ for ( ++i; ( i < n ) && ( line[i] != '"' ); ++i ) { /* empty */ } if ( i == n ) { RB_Panic( "Missing quote in your .rc file in line:\n %s\n", line ); } else { #if defined(__APPLE__) /* hacked because of error when compiling on Mac OS X */ assert( line[i] == 34 ); #else assert( line[i] == '"' ); #endif line[i] = '\0'; AddParameter( name, parameters ); } } else { /* a single word, find the next space */ for ( ; ( i < n ) && !utf8_isspace( line[i] ); ++i ) { /* empty */ } if ( i < n ) { line[i] = '\0'; } AddParameter( name, parameters ); } /* Is there anything left? */ if ( i < n ) { /* skip any spaces until the next parameter */ ++i; /* first skip the nul character */ line += i; n = strlen( line ); for ( i = 0; ( i < n ) && utf8_isspace( line[i] ); ++i ) { /* empty */ } line += i; n = strlen( line ); i = 0; } } }
Hash_Keyword
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Calculate the hash value for a string
The hash value is a 32 bit integer based on the hash function written by Bob Jenkins. It is then reduced by an AND operation to the actual size of the hash table.
SYNOPSIS
unsigned long Hash_Keyword( char *key, unsigned long keylen )
INPUTS
- key -- The keyword string
- keylen -- The length of the keyword string
RETURN VALUE
The hash value for the keyword.
SOURCE
{ unsigned long bkt, i, j, k; bkt = 0xfeedbeef; i = j = 0x9e3779b9; k = keylen; while ( k >= 12 ) { i += ( key[0] + ( ( unsigned ) key[1] << 8 ) + ( ( unsigned ) key[2] << 16 ) + ( ( unsigned ) key[3] << 24 ) ); j += ( key[4] + ( ( unsigned ) key[5] << 8 ) + ( ( unsigned ) key[6] << 16 ) + ( ( unsigned ) key[7] << 24 ) ); bkt += ( key[8] + ( ( unsigned ) key[9] << 8 ) + ( ( unsigned ) key[10] << 16 ) + ( ( unsigned ) key[11] << 24 ) ); HASH_MIX( i, j, bkt ); key += 12; k -= 12; } bkt += keylen; switch ( k ) { case 11: bkt += ( ( unsigned ) key[10] << 24 ); case 10: bkt += ( ( unsigned ) key[9] << 16 ); case 9: bkt += ( ( unsigned ) key[8] << 8 ); case 8: j += ( ( unsigned ) key[7] << 24 ); case 7: j += ( ( unsigned ) key[6] << 16 ); case 6: j += ( ( unsigned ) key[5] << 8 ); case 5: j += key[4]; case 4: i += ( ( unsigned ) key[3] << 24 ); case 3: i += ( ( unsigned ) key[2] << 16 ); case 2: i += ( ( unsigned ) key[1] << 8 ); case 1: i += key[0]; } HASH_MIX( i, j, bkt ); return ( bkt & keywords_hash_mask ); }
HASH_MIX
[ Top ] [ Hash_Keyword ] [ Functions ]
FUNCTION
Helper macro for the function Hash_Keyword( )
SOURCE
#define HASH_MIX(a,b,c) \
{ \
a -= b; a -= c; a ^= ( c >> 13 ); \
b -= c; b -= a; b ^= ( a << 8 ); \
c -= a; c -= b; c ^= ( b >> 13 ); \
a -= b; a -= c; a ^= ( c >> 12 ); \
b -= c; b -= a; b ^= ( a << 16 ); \
c -= a; c -= b; c ^= ( b >> 5 ); \
a -= b; a -= c; a ^= ( c >> 3 ); \
b -= c; b -= a; b ^= ( a << 10 ); \
c -= a; c -= b; c ^= ( b >> 15 ); \
}
Install_C_Syntax
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Install default C keywords and comments
SOURCE
void Install_C_Syntax( void ) { unsigned int i; /* Check if we can install our default C keywords */ if ( !configuration.keywords.number ) { for ( i = 0; c_keywords[i]; i++ ) { AddParameter( c_keywords[i], &( configuration.keywords ) ); } /* Make keywords hash table (if necessarry) */ add_keywords_to_hash_table( ); } /* Make sure that C line comment is present */ if ( Find_Parameter_Exact ( &( configuration.source_line_comments ), C_LINE_COMMENT ) == NULL ) { AddParameter( C_LINE_COMMENT, &( configuration.source_line_comments ) ); } /* Make sure that C block comment start is present */ if ( Find_Parameter_Exact ( &( configuration.remark_begin_markers ), C_BLOCK_COMMENT_START ) == NULL ) { AddParameter( C_BLOCK_COMMENT_START, &( configuration.remark_begin_markers ) ); } /* Make sure that C block comment end is present */ if ( Find_Parameter_Exact ( &( configuration.remark_end_markers ), C_BLOCK_COMMENT_END ) == NULL ) { AddParameter( C_BLOCK_COMMENT_END, &( configuration.remark_end_markers ) ); } }
keywords_hash
[ Top ] [ Configuration ] [ Variables ]
FUNCTION
This is the hash table for the keywords. See keywords_hash_s.
SOURCE
static struct keywords_hash_s **keywords_hash;
keywords_hash_mask
[ Top ] [ Configuration ] [ Variables ]
FUNCTION
Mask for keyword hash function. This mask reduces the hash value for the actual hash table size. Also the size of the hash table can be derived from this mask:
hash table size = keywords_hash_mask + 1
SOURCE
static unsigned int keywords_hash_mask;
ReadConfiguration
[ Top ] [ Configuration ] [ Functions ]
FUNCTION
Read the robodoc configuration file, and create a RB_Configuration structure.
SYNOPSIS
char *ReadConfiguration( unsigned int argc, char **argv, char *filename )
INPUTS
- argc -- the arg count as received by main()
- argv -- the arg valules as received by main()
- filename -- an optional filename. If none is given, "robodoc.rc" is used.
RESULT
An initialized configuration (a global).
SOURCE
{ FILE *f = NULL; char *path = NULL; if ( filename ) { path = Get_rc( filename ); if ( path ) { f = fopen( path, "r" ); } if ( !f ) { /* It should open as the user claimed it exists somewhere */ RB_Panic( "Can't open %s\n", filename ); } } else { /* Try the default rc file */ path = Get_rc( "robodoc.rc" ); if ( path ) { f = fopen( path, "r" ); } } AllocOptions( argc, argv ); Alloc_Parameters( &( configuration.items ), 10 ); Alloc_Parameters( &( configuration.ignore_items ), 10 ); Alloc_Parameters( &( configuration.source_items ), 10 ); Alloc_Parameters( &( configuration.preformatted_items ), 10 ); Alloc_Parameters( &( configuration.format_items ), 10 ); Alloc_Parameters( &( configuration.item_order ), 10 ); Alloc_Parameters( &( configuration.custom_headertypes ), 10 ); Alloc_Parameters( &( configuration.ignore_files ), 10 ); Alloc_Parameters( &( configuration.accept_files ), 10 ); Alloc_Parameters( &( configuration.header_markers ), 10 ); Alloc_Parameters( &( configuration.remark_markers ), 10 ); Alloc_Parameters( &( configuration.end_markers ), 10 ); Alloc_Parameters( &( configuration.remark_begin_markers ), 10 ); Alloc_Parameters( &( configuration.remark_end_markers ), 10 ); Alloc_Parameters( &( configuration.keywords ), 10 ); Alloc_Parameters( &( configuration.source_line_comments ), 10 ); Alloc_Parameters( &( configuration.header_ignore_chars ), 10 ); Alloc_Parameters( &( configuration.header_separate_chars ), 10 ); if ( f ) { SecondScan( f ); fclose( f ); } else { /* No .rc file found. That's OK */ } ComplementItemNames( ); ComplementHeaderMarkers( ); Complement_Remark_Markers( ); Install_Custom_HeaderTypes( ); /* Make keywords hash table (if necessarry) */ add_keywords_to_hash_table( ); assert( configuration.items.number ); return path; }