diff --git a/Packages/Manual_tools/src/cc_extract_html.C b/Packages/Manual_tools/src/cc_extract_html.C new file mode 100644 index 00000000000..04a6f8084d4 --- /dev/null +++ b/Packages/Manual_tools/src/cc_extract_html.C @@ -0,0 +1,2110 @@ +/************************************************************************** + + cgal_extract_html.cc + ============================================================= + Project : CGAL merger tool for the specification task + Function : main program, command line parameter parsing + System : bison, flex, C++ (g++) + Author : (c) 1995 Lutz Kettner + Revision : $Revision$ + Date : $Date$ + +**************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef char Switch; + +#define NO_SWITCH 0 +#define MINUS_SWITCH 1 +#define PLUS_SWITCH 2 + +Switch trace_switch = NO_SWITCH; +Switch line_switch = NO_SWITCH; + + +/* A couple of strings for tayloring */ +/* ================================= */ +// no newlines in here (because it is used in the index file) !! +const char* general_comment = + ""; + +const char* general_navigation = + "Table of Contents,\n" + "Bibliography,\n" + "Index,\n" + "Title Page"; + +// no newlines in here (because it is used in the index file) !! +const char* html_address_trailer = + "
The " + "CGAL Project.
"; + +/* table size and font size constants */ +/* ================================== */ +const int table_width = 550; +const int table_first_col = 25; // in percent +const int table_second_col = 25; // in percent +const int table_third_col = 50; // in percent +const int table_2c_first_col = 30; // in percent +const int table_2c_second_col = 70; // in percent + +const double width_per_character = 5.5; + +// This factor is multiplied to the actual width of an C++ declaration +// right before the test for multiple lines formatting occurs. +// A greater value forces declarations to be printed in multiple lines. +double stretch_factor = 1.6; + +/* An empty List as empty comment for global declarations */ +/* ====================================================== */ +Text empty_comment; + +/* for the bibliography */ +/* ==================== */ +bool first_bibitem = true; + +/* Declarations from syntax.y */ +/* ========================== */ +extern int yydebug; +void yyparse(); + +/* Declarations from lex.yy */ +/* ========================== */ +void init_scanner( FILE* in); +extern char* creationvariable; +extern char* formatted_creationvariable; + + +/* File and filename handling */ +/* ========================== */ +const char* in_filename = 0; +char* main_filename = ""; +char* current_filename = ""; +char* chapter_title = 0; +char* class_filename = 0; +char* class_name = 0; +char* template_class_name = 0; +char* formatted_class_name = 0; +char* formatted_template_class_name = 0; + +char* html_suffix = ".html"; +char* chapter_prefix = "Chapter_"; +char* anchor_filename = "anchor_rules"; +char* contents_filename = "contents.html"; +char* bib_filename = "biblio.html"; +char* index_filename = "manual_index.html"; + +ostream* main_stream = 0; +ostream* class_stream = 0; +ostream* current_stream = 0; +ostream* anchor_stream = 0; +ostream* contents_stream = 0; +ostream* index_stream = 0; + +char* addSuffix( const char* name, const char* suffix) { + char *fullname = new char[ strlen( name) + strlen( suffix) + 1]; + strcpy( fullname, name); + strcat( fullname, suffix); + return fullname; +} + +// return the position of a suffix dot `.'. Return the terminating +// zero `\0' position if no dot `.' is in the whole filename. +int suffixPosition( const char* name) { + int l = strlen( name); + int i = l; + while( i > 0) { + --i; + if ( name[i] == '.') + return i; + } + return l; +} + +char* replaceSuffix( const char* name, const char* suffix) { + int l = suffixPosition( name); + char *fullname = new char[ l + strlen( suffix) + 1]; + strncpy( fullname, name, l); + fullname[ l] = '\0'; + strcat( fullname, suffix); + return fullname; +} + +char* addPrefix( const char* prefix, const char* name) { + char *fullname = new char[ strlen( name) + strlen( prefix) + 1]; + strcpy( fullname, prefix); + strcat( fullname, name); + return fullname; +} + + +/* HTML generating functions */ +/* ========================= */ + +void open_html( ostream& out, const char* classname) { + out << "\nThe CGAL Kernel Manual: " + << classname << "\n" + << general_comment + << "\n\n\n"; +} + +void close_html( ostream& out) { + out << "\n\n" << html_address_trailer << "\n\n" << endl; +} + +bool is_html_multi_character( char c) { + return c == '"' || c == '&' || c == '<' || c == '>'; +} + +const char* html_multi_character( char c) { + static char *s = " "; + switch ( c) { + case '"': return """; + case '&': return "&"; + case '<': return "<"; + case '>': return ">"; + default: *s = c; + } + return s; +} + +void print_ascii_to_html( ostream& out, const char* txt) { + while( *txt) { + if ( is_html_multi_character( *txt)) + out << html_multi_character( *txt); + else + out << *txt; + ++txt; + } +} + +// This version eliminates multiple spaces. +void print_ascii_to_html_spc( ostream& out, const char* txt) { + while( *txt) { + if ( is_html_multi_character( *txt)) + out << html_multi_character( *txt); + else + if ( *txt > ' ' || txt[1] > ' ') + out << *txt; + ++txt; + } +} + +int strlen_ascii_to_html( const char* txt) { + int len = 0; + while( *txt) { + if ( is_html_multi_character( *txt)) + len += strlen( html_multi_character( *txt)); + else + len++; + ++txt; + } + return len; +} + +char* convert_ascii_to_html( const char* txt) { + char* s = new char[ strlen_ascii_to_html( txt) + 1]; + char* p = s; + while( *txt) { + if ( is_html_multi_character( *txt)) { + const char* q = html_multi_character( *txt); + while ( *q) + *p++ = *q++; + } else + *p++ = *txt; + ++txt; + } + *p = '\0'; + return s; +} + +double estimate_html_size( const char* s) { + int n = 0; + while ( *s) { + if ( *s > ' ' || s[1] > ' ') + n++; + ++s; + } + return width_per_character * n; +} + + +void three_cols_html_begin( ostream& out, bool big_col1) { + out << indent << indent << indNewline + << "" << indNewline + << ""; + if ( big_col1) + out << ""; + out << ""; + if ( big_col2 && ! empty_col3) + out << ""; + out << ""; + out << "" << indNewline + << "
" : ">") + << indNewline << "" << outdent << indNewline; +} + +void three_cols_html_second( ostream& out, bool big_col1, bool big_col2) { + out << indent << indNewline <<"" << indNewline << "
" : ">") + << indNewline << "" << outdent << indNewline; +} + +void three_cols_html_third( ostream& out, bool big_col2, bool empty_col3) { + out << indent << indNewline << "" << indNewline << "
" ; + out << outdent << indNewline; +} + +void three_cols_html_end( ostream& out, bool big_col2, bool empty_col3) { + out << indent << indNewline; + if ( ! big_col2 || ! empty_col3) + out << "
" << outdent << outdent << indNewline; +} + +void two_cols_html_begin( ostream& out) { + out << indent << indent << indNewline + << "" << indNewline + << ""; + if ( ! empty_col2) + out << "" << indNewline; + out << "
" + << indNewline << "" << outdent << indNewline; +} + +void two_cols_html_second( ostream& out, bool empty_col2) { + out << indent << indNewline << "" << indNewline << "
"; + out << outdent << indNewline; +} + +void two_cols_html_end( ostream& out, bool empty_col2) { + out << indent << indNewline; + if ( ! empty_col2) + out << "
" << outdent << outdent << indNewline; +} + +int text_block_length( const Text& T) { + int l = 0; + InListFIter< TextToken> words( (Text&)T); + ForAll( words) { + if ( words->isSpace) + ++l; + else + l += (*words).len; + } + return l; +} + +char* text_block_to_string( const Text& T) { + char* string = new char[ text_block_length( T) + 1]; + string[0] = '\0'; + InListFIter< TextToken> words( (Text&)T); + ForAll( words) { + if ( words->isSpace) + strcat( string, " "); + else + strcat( string, (*words).string); + } + return string; +} + +bool is_text_block_empty( const Text& T) { + InListFIter< TextToken> words( (Text&)T); + ForAll( words) { + if ( !words->isSpace) + return false; + } + return true; +} + +int print_html_text_block( ostream &out, const Text& T, + bool leadingParagraph = false) { + InListFIter< TextToken> words( (Text&)T); + int width = MaxTextWidth - indentation_number() - 3; + int w = width; + int state = 0; // 0 = start, 1 = after token, 2 = spaces + // 3 = one newline (and spaces), 4 = newlines + ForAll( words) { + switch ( state) { + case 0: + if ( !words->isSpace) { + if ( leadingParagraph) { + out << indNewline << "

\n" << indNewline; + } + out << words->string; + w -= words->len; + state = 1; + } + break; + case 1: + if ( !words->isSpace || words->len > 0) { + if ( !words->isSpace) { + if ((words->len > w) && (w != width)) { + w = width; + out << indNewline; + } + out << words->string; + w -= words->len; + } else { + if ( words->string[0] == '\n') + state = 3; + else + state = 2; + } + } + break; + case 2: + if ( !words->isSpace || words->len > 0) { + if ( !words->isSpace) { + if ((words->len >= w) && (w != width)) { + w = width; + out << indNewline; + } else { + out << ' '; + w--; + } + out << words->string; + w -= words->len; + state = 1; + } else { + if ( words->string[0] == '\n') + state = 3; + } + } + break; + case 3: + if ( !words->isSpace || words->len > 0) { + if ( !words->isSpace) { + if ((words->len >= w) && (w != width)) { + w = width; + out << indNewline; + } else { + out << ' '; + w--; + } + out << words->string; + w -= words->len; + state = 1; + } else { + if ( words->string[0] == '\n') + state = 4; + } + } + break; + case 4: + if ( !words->isSpace || words->len > 0) { + if ( !words->isSpace) { + out << indNewline << "

\n" << indNewline; + w = width; + out << words->string; + w -= words->len; + state = 1; + } + } + break; + } + } + return state; +} + + +/* Formatting functions that work like the cgal_manual.sty */ +/* ======================================================= */ + +// This function separates the return value from the scope, the function name, +// the parameter list (without paranthesis) and the rest of the signature.. +// Therefore, the string in signature will be parsed from the end +// looking for the first ')' and then for the matching '(', using +// a nesting count for '(', ')', '{', '}', '<', '>'. Then, the next token is +// assumed to be the function name. After that, a scope can be a list of +// '::' and identifiers. The rest is assumed to be the return value. All parts +// might be empty. The parantheses for the parameters are not allowed to be +// omitted. The function name token might be an opearator !! +// For the special case of enumerators the last parameter enum_decl +// changes the parsing to look for braces `{}' instead of parantheses `()'. +void split_function_declaration( const char* signature, + char*& return_value, + char*& scope, + char*& function_name, + char*& parameter_list, + const char*& rest, + bool enum_decl = false) { + char opening = '('; + char closing = ')'; + if ( enum_decl) { + opening = '{'; + closing = '}'; + } + const char* s = signature + strlen( signature) - 1; + + // Note that the string processing pointer s can point one character + // in front of signature (where it should never be dereferenced). + // This is checked using the s_end pointer. + const char* s_end = signature - 1; + + // skip the rest + while ( s != s_end && *s != closing) + --s; + rest = s + 1; + while ( *rest > 0 && *rest <= ' ') + ++rest; + if ( s != s_end) + --s; + while ( s != s_end && *s <= ' ') + --s; + + // scan the parameter list + const char* q = s; + int nesting = 0; + while ( s != s_end && ( nesting || *s != opening)) { + switch ( *s) { + case ')': + case '}': + case '>': + ++nesting; + break; + case '(': + case '{': + case '<': + --nesting; + break; + + } + --s; + } + const char* p = s + 1; + while ( *p > 0 && *p <= ' ') + ++p; + if ( q - p >= 0) { + parameter_list = new char[ q - p + 2]; + strncpy( parameter_list, p, q - p + 1); + parameter_list[ q - p + 1] = '\0'; + } else + parameter_list = 0; + + if ( s != s_end) // read over the '(' + --s; + while ( s != s_end && *s <= ' ') + --s; + if ( s == s_end || nesting) { + printErrorMessage( MalformedFunctionDeclaration); + exit( 1); + } + q = s; + + // scan function name + // skip possible operator symbols and white spaces + while ( s != s_end && ( ! isalnum( *s)) && ( *s != '_')) + --s; + // parse first identifier for the function_name + while ( s != s_end && ( isalnum( *s) || *s == '_')) + --s; + // check the possibilty that the function is a cast operator + // like `operator int', or an idfier as operator like `operator new' + // so check whether the next identifier is equal to `operator' + p = s; + while ( s != s_end && *s <= ' ') + --s; + while ( s != s_end && ( isalnum( *s) || *s == '_')) + --s; + if ( strncmp( s + 1, "operator", 8) != 0) + // it's not the cast operator, restore old positiom + s = p; + if ( q - s) { + function_name = new char[ q - s + 1]; + strncpy( function_name, s + 1, q - s); + function_name[ q - s] = '\0'; + } else + function_name = 0; + + // check for a scope operator + while ( s != s_end && *s <= ' ') + --s; + q = s; + while ( (s - s_end) > 0 && *s == ':' && *(s-1) == ':') { + s -= 2; + while ( s != s_end && *s <= ' ') + --s; + while ( s != s_end && ( isalnum( *s) || *s == '_')) + --s; + } + if ( q - s > 0) { + scope = new char[ q - s + 1]; + strncpy( scope, s + 1, q - s); + scope[ q - s] = '\0'; + } else + scope = 0; + + // The rest is the return type + while ( s != s_end && *s <= ' ') + --s; + q = signature; + while ( *q && *q <= ' ') + ++q; + if ( s - q >= 0) { + return_value = new char[ s - q + 2]; + strncpy( return_value, q, s - q + 1); + return_value[ s - q + 1] = '\0'; + } else + return_value = 0; +} + +// This function separates a varible declaration around the variable name. +// The rest might contain `)', array subscripts or an assignment. +// The scope might be empty, the return_value should not be empty. +// No fancy tricks like operators. +void split_variable_declaration( const char* signature, + char*& return_value, + char*& scope, + char*& variable_name, + char*& rest) { + const char* s = signature + strlen( signature) - 1; + + // Note that the string processing pointer s can point one character + // in front of signature (where it should never be dereferenced). + // This is checked using the s_end pointer. + const char* s_end = signature - 1; + + // skip the `;' + while ( s != s_end && *s != ';') + --s; + if ( s != s_end) + --s; + + // skip the rest + const char* q = s; + + // look out for an assignment (including nesting) + int nesting = 0; + while ( s != s_end && ( nesting || *s != '=')) { + if ( *s == '}' || *s == ')' || *s == ']' || *s == '>') + ++nesting; + if ( *s == '{' || *s == '(' || *s == '[' || *s == '<') + --nesting; + --s; + } + if ( s != s_end) { + // assignment found + --s; + } else { + // not found, restore old position + s = q; + } + + // skip possible operator symbols and white spaces + while ( s != s_end && ( ! isalnum( *s)) && ( *s != '_')) + --s; + const char* p = s + 1; + while ( *p > 0 && *p <= ' ') + ++p; + if ( q - p >= 0) { + rest = new char[ q - p + 2]; + strncpy( rest, p, q - p + 1); + rest[ q - p + 1] = '\0'; + } else + rest = 0; + + if ( s == s_end) { + printErrorMessage( MalformedFunctionDeclaration); + exit( 1); + } + q = s; + + // scan function name + // parse first identifier for the function_name + while ( s != s_end && ( isalnum( *s) || *s == '_')) + --s; + if ( q - s) { + variable_name = new char[ q - s + 1]; + strncpy( variable_name, s + 1, q - s); + variable_name[ q - s] = '\0'; + } else + variable_name = 0; + + // check for a scope operator + while ( s != s_end && *s <= ' ') + --s; + q = s; + while ( (s - s_end) > 0 && *s == ':' && *(s-1) == ':') { + s -= 2; + while ( s != s_end && *s <= ' ') + --s; + while ( s != s_end && ( isalnum( *s) || *s == '_')) + --s; + } + if ( q - s > 0) { + scope = new char[ q - s + 1]; + strncpy( scope, s + 1, q - s); + scope[ q - s] = '\0'; + } else + scope = 0; + + // The rest is the return type + while ( s != s_end && *s <= ' ') + --s; + q = signature; + while ( *q && *q <= ' ') + ++q; + if ( s - q >= 0) { + return_value = new char[ s - q + 2]; + strncpy( return_value, q, s - q + 1); + return_value[ s - q + 1] = '\0'; + } else + return_value = 0; +} + +void remove_const_ref_pair( char* s) { + int state = 0; // 0 = no const, 1 = c, 2 = co, 3 = con, 4 = cons, 5 = const + int nesting = 0; + char* q; // position of recently found const + int nest; // nesting level of recently found const + while( *s) { + switch( state) { + case 0: + if ( *s == '(' || *s == '<' || *s == '[' || *s == '{') + ++nesting; + if ( *s == ')' || *s == '>' || *s == ']' || *s == '}') + --nesting; + if ( *s == 'c') { + state = 1; + nest = nesting; + q = s; + } + ++s; + break; + case 1: + if ( *s == 'o') { + ++s; + state = 2; + } else + state = 0; + break; + case 2: + if ( *s == 'n') { + ++s; + state = 3; + } else + state = 0; + break; + case 3: + if ( *s == 's') { + ++s; + state = 4; + } else + state = 0; + break; + case 4: + if ( *s == 't') { + ++s; + state = 5; + } else + state = 0; + break; + case 5: + if ( *s == '(' || *s == '<' || *s == '[' || *s == '{') + ++nesting; + if ( *s == ')' || *s == '>' || *s == ']' || *s == '}') + --nesting; + if ( *s == '&' && nest == nesting) { + q[0] = ' '; + q[1] = ' '; + q[2] = ' '; + q[3] = ' '; + q[4] = ' '; + s[0] = ' '; + return; + } + ++s; + break; + } + } + return; +} + +void remove_own_classname( char* s, const char* classname) { + if ( ! classname) + return; + int nesting = 0; // prepare to remove template params if necessary + int l = strlen( classname); + if ( ! l) + return; + while( *s) { + if ( strncmp( s, classname, l) == 0) { + while( l--) + *s++ = ' '; + while( *s && *s <= ' ') + ++s; + if ( *s == '<') { + // Classname with template params detected. Remove them. + while ( *s) { + if ( *s == '(' || *s == '<' || *s == '[' || *s == '{') + ++nesting; + if ( *s == ')' || *s == '>' || *s == ']' || *s == '}') + --nesting; + if (*s == '>' && nesting == 0) + break; + *s++ = ' '; + } + if ( nesting || *s != '>') { + printErrorMessage( MalformedTemplateParamError); + exit( 1); + } + *s = ' '; + } + break; + } + ++s; + } + return; +} + +// This function separates each parameter in a parameter list. +// It replaces therefore the separating commatas by `\0'. +// The returnvalue states the number of parameters found. +// The parsing process takes nesting in account. +int separate_parameter_list( char* s) { + if ( ! s) + return 0; + char* s_start = s - 1; + int n = 1; + int nesting = 0; + while( *s) { + if ( *s == '(' || *s == '<' || *s == '[' || *s == '{') + ++nesting; + if ( *s == ')' || *s == '>' || *s == ']' || *s == '}') + --nesting; + if ( *s == ',' && nesting == 0) { + ++n; + // remove trailing spaces + *s = ' '; + char* q = s - 1; + while ( q != s_start && *q && *q <= ' ') + --q; + ++q; + *q = '\0'; + } + ++s; + } + if ( nesting ) { + printErrorMessage( MalformedFunctionDeclaration); + exit( 1); + } + return n; +} + +// Compute the operator layout. Assume reasonable values in all parameters. +// Actually, exp_size just counts all parameters and operator characters. +// Only exceptional cases has to recompute exp_size. The boolean +// ignore_params can be set true in which case the parameters will not +// be printed, even not the creationvariable for methods. (Used +// for the new and the delete operators.) +// The parantheses operator has to format its own parantheses and +// the first commata between the first and second parameter (if +// more than one parameter exists). +// As an exceptional case for ++ and -- the number of parameters +// is reduced from two to one to hide the second int parameter +// neccessary to indicate that the postincrement is meant. (Hack!! ;--> ) +// Returns: false if failed, true for success. +bool format_operators( int n, int& modifiable_n, + char* op, + const char*& praefix, + const char*& infix, + const char*& postfix, + double& exp_size, + bool& ignore_params) { + // Assume that the syntax is not malformed (error messages are + // provided elsewhere, namely compiler or cgal_manual.sty). + // Non matching operators are printed in functional notation. + if ( *op <= ' ') + return false; + if ( op[1] <= ' ') { // one character operators + if ( n == 1) { // with one parameter + switch ( *op) { + case '~': + case '!': + case '-': + case '+': + case '&': + case '*': + praefix = op; + break; + default: + return false; + } + } else if ( n == 2) { // with two parameters + switch ( *op) { + case '*': + case '/': + case '%': + case '+': + case '-': + case '<': + case '>': + case '&': + case '^': + case '|': + case '=': + case ',': + infix = op; + break; + default: + return false; + } + } else + return false; + } else if ( op[2] <= ' ') { // two character operators + if ( n == 1) { // with one parameter + switch ( *op) { + case '-': + if ( op[1] == '>') + postfix = op; + else if ( op[1] == '-') + praefix = op; + else + return false; + break; + case '(': + if ( op[1] == ')') { + infix = op; + } else + return false; + break; + case '+': + if ( op[1] == *op) + praefix = op; + else + return false; + break; + default: + return false; + } + } else if ( n == 2) { // with two parameters + switch ( *op) { + case '[': + if ( op[1] == ']') { + infix = "["; + postfix = "]"; + } + else + return false; + break; + case '(': + if ( op[1] == ')') { + infix = "("; + postfix = ")"; + } + else + return false; + break; + case '+': + case '-': + if ( op[1] == *op) { + postfix = op; + modifiable_n--; + exp_size -= estimate_html_size( " int"); + } + else if ( op[1] == '=') + infix = op; + else + return false; + break; + case '>': + case '<': + case '&': + case '|': + if ( op[1] == *op || op[1] == '=') + infix = op; + else + return false; + break; + case '=': + case '!': + case '*': + case '/': + case '%': + case '^': + if ( op[1] == '=') + infix = op; + else + return false; + break; + default: + return false; + } + } else + return false; + } else { // three or more character operators + if ( strcmp( op, "->*") == 0) + postfix = op; + else if ( strcmp( op, "<<=") == 0) + infix = op; + else if ( strcmp( op, ">>=") == 0) + infix = op; + else if ( strcmp( op, "new") == 0) { + ignore_params = true; + exp_size = estimate_html_size( " new "); + exp_size += estimate_html_size( template_class_name); + praefix = "new"; + infix = template_class_name; + } else if ( strcmp( op, "delete") == 0) { + ignore_params = true; + exp_size = estimate_html_size( " delete void*"); + praefix = "delete void*"; + } else if ( strcmp( op, "delete[]") == 0) { + ignore_params = true; + exp_size = estimate_html_size( " delete[] void*"); + praefix = "delete[] void*"; + } else + return false; + } + return true; +} + +void format_function( bool method, const char* signature, const Text& T) { + char* return_value; + char* scope; + char* function_name; + char* parameter_list; + const char* rest; + + bool normal_operator = false; // either operator ... + bool conversion_operator = false; // ... or conversion operator + // or (normal) function + char* op_symbols; + + split_function_declaration( signature, + return_value, + scope, + function_name, + parameter_list, + rest); + + // check function_name for operator + if ( strncmp( function_name, "operator", 8) == 0 + && ! isalnum(function_name[8]) + && function_name[8] != '_') { + op_symbols = function_name + 8; + while ( *op_symbols && *op_symbols <= ' ') + ++op_symbols; + normal_operator = return_value; + conversion_operator = ! return_value; + } + + double exp_size_ret = 0.0; + double exp_size = 0.0; + if ( return_value) { + remove_const_ref_pair( return_value); + exp_size_ret += estimate_html_size( return_value); + } + if ( conversion_operator) + exp_size_ret += estimate_html_size( op_symbols); + + three_cols_html_begin( *current_stream, + exp_size_ret > table_width*table_first_col/100.0); + + if ( return_value) + print_ascii_to_html_spc( *current_stream, return_value); + if ( conversion_operator) + print_ascii_to_html_spc( *current_stream, op_symbols); + + // handle function body or operation signature + // first, estimate size + if ( method) + exp_size = estimate_html_size( creationvariable) + width_per_character; + int n = 0; + if ( conversion_operator) { + exp_size += estimate_html_size( op_symbols); + } else if ( parameter_list) { + n = separate_parameter_list( parameter_list); + char* p = parameter_list; + int m = n; + while ( m--) { + remove_const_ref_pair( p); + remove_own_classname( p, class_name); + exp_size += estimate_html_size( p) + width_per_character; + p += strlen( p) + 1; // skip to next parameter + } + } + bool failed = false; + if ( normal_operator) { + exp_size += estimate_html_size( op_symbols); + bool ignore_params = false; // exception for new and delete operators + const char* praefix = ""; + const char* infix = ""; + const char* postfix = ""; + failed = ! format_operators( ( method ? n + 1 : n), n, + op_symbols, + praefix, infix, postfix, + exp_size, ignore_params); + if ( ! failed) { + // print the operator + three_cols_html_second( + *current_stream, + exp_size_ret > table_width * table_first_col / 100.0, + exp_size > table_width * table_second_col / 100.0 + ); + print_ascii_to_html_spc( *current_stream, praefix); + *current_stream << " "; + char* p = parameter_list; + if ( ! ignore_params) { + if ( method) + print_ascii_to_html_spc(*current_stream, creationvariable); + else if (n) { + --n; + print_ascii_to_html_spc(*current_stream, p); + p += strlen( p) + 1; // skip to next parameter + } + } + *current_stream << " "; + print_ascii_to_html_spc( *current_stream, infix); + *current_stream << " "; + if ( ! ignore_params && n) { + while ( n--) { + print_ascii_to_html_spc(*current_stream, p); + p += strlen( p) + 1; // skip to next parameter + if ( n) + *current_stream << ", "; + } + } + print_ascii_to_html_spc( *current_stream, postfix); + } + } + if ( ! normal_operator || failed) { + if ( scope) + exp_size += estimate_html_size( scope); + exp_size += estimate_html_size( function_name); + exp_size += 3 * width_per_character; // for parameter list parantheses + + // then, do the printing + three_cols_html_second( + *current_stream, + exp_size_ret > table_width * table_first_col / 100.0, + exp_size > table_width * table_second_col / 100.0 + ); + if ( conversion_operator) { + print_ascii_to_html_spc( *current_stream, op_symbols); + *current_stream << " ( "; + print_ascii_to_html_spc( *current_stream, creationvariable); + *current_stream << ")"; + } else { + double dd_width = table_width * ( 1.0 - table_first_col / 100.0); + dd_width /= stretch_factor; + if ( exp_size > dd_width && parameter_list) + *current_stream<<"" + "
" + << indNewline; + if ( method) { + print_ascii_to_html_spc( *current_stream, creationvariable); + *current_stream << '.'; + } + if ( scope) + print_ascii_to_html_spc( *current_stream, scope); + print_ascii_to_html_spc( *current_stream, function_name); + if ( parameter_list) { + *current_stream << " ( "; + if ( exp_size > dd_width) + *current_stream <<"" + << indNewline; + char* p = parameter_list; + while ( n--) { + print_ascii_to_html_spc( *current_stream, p); + p += strlen( p) + 1; // skip to next parameter + if ( n) { + *current_stream << ", "; + if ( exp_size > dd_width) + *current_stream << "
" << indNewline; + } + } + *current_stream << ")"; + if ( exp_size > dd_width) + *current_stream << "
" << indNewline; + } else + *current_stream << " ()"; + } + } + bool is_empty_comment = is_text_block_empty( T); + three_cols_html_third( *current_stream, + exp_size > table_width * table_second_col / 100.0, + is_empty_comment); + delete[] return_value; + delete[] scope; + delete[] function_name; + delete[] parameter_list; + print_html_text_block( *current_stream, T); + three_cols_html_end( *current_stream, + exp_size > table_width * table_second_col / 100.0, + is_empty_comment); +} + +void format_variable( const char* signature, const Text& T) { + char* return_value; + char* scope; + char* variable_name; + char* rest; // possibly including assignment + + split_variable_declaration( signature, + return_value, + scope, + variable_name, + rest); + char* formatted_var = convert_ascii_to_html( variable_name); + + if ( &T == &empty_comment) { + // generate a substitution rule for hyperlinking + *anchor_stream << "[a-zA-Z0-9_]\"" << formatted_var + << "\" { ECHO; }" << endl; + *anchor_stream << "\"" << formatted_var + << "\"[a-zA-Z0-9_] { ECHO; }" << endl; + *anchor_stream << '"' << formatted_var + << "\" { fputs( \"" << formatted_var << "\", stdout); }" + << endl; + + *current_stream << "" << endl; + + // index + *index_stream << "

  • " << formatted_var + << "
" << endl; + } + + double exp_size_ret = 0.0; + double exp_size = 0.0; + if ( return_value) { + remove_const_ref_pair( return_value); + exp_size_ret += estimate_html_size( return_value); + } + + three_cols_html_begin( *current_stream, + exp_size_ret > table_width*table_first_col/100.0); + + if ( return_value) + print_ascii_to_html_spc( *current_stream, return_value); + + // handle function body or operation signature + // first, estimate size + if ( scope) + exp_size += estimate_html_size( scope); + exp_size += estimate_html_size( variable_name); + if ( rest) + exp_size += estimate_html_size( rest); + + // then, do the printing + three_cols_html_second( + *current_stream, + exp_size_ret > table_width * table_first_col / 100.0, + exp_size > table_width * table_second_col / 100.0 + ); + if ( scope) + print_ascii_to_html_spc( *current_stream, scope); + *current_stream << formatted_var; + if ( rest) { + *current_stream << ' '; + print_ascii_to_html_spc( *current_stream, rest); + } + *current_stream << ';'; + + bool is_empty_comment = is_text_block_empty( T); + three_cols_html_third( *current_stream, + exp_size > table_width * table_second_col / 100.0, + is_empty_comment); + delete[] return_value; + delete[] scope; + delete[] formatted_var; + delete[] variable_name; + delete[] rest; + print_html_text_block( *current_stream, T); + three_cols_html_end( *current_stream, + exp_size > table_width * table_second_col / 100.0, + is_empty_comment); +} + +void format_constructor( const char* signature, const Text& T) { + char* return_value; + char* scope; + char* function_name; + char* parameter_list; + const char* rest; + + split_function_declaration( signature, + return_value, + scope, + function_name, + parameter_list, + rest); + + two_cols_html_begin( *current_stream); + // first, estimate size + double exp_size = 0.0; + if ( scope) + exp_size += estimate_html_size( scope); + exp_size += estimate_html_size( creationvariable) + + estimate_html_size( template_class_name) + + width_per_character; + int n = 0; + if ( parameter_list) { + exp_size += 2 * width_per_character; + n = separate_parameter_list( parameter_list); + char* p = parameter_list; + int m = n; + while ( m--) { + remove_const_ref_pair( p); + remove_own_classname( p, class_name); + exp_size += estimate_html_size( p) + width_per_character; + p += strlen( p) + 1; // skip to next parameter + } + } + exp_size *= stretch_factor; + if ( exp_size > table_width && parameter_list) + *current_stream << "" + "
" + << indNewline; + + if ( scope) + print_ascii_to_html_spc( *current_stream, scope); + print_ascii_to_html_spc( *current_stream, template_class_name); + *current_stream << ' '; + print_ascii_to_html_spc( *current_stream, creationvariable); + + if ( parameter_list) { + *current_stream << " ( "; + if ( exp_size > table_width) + *current_stream << "" + << indNewline; + char* p = parameter_list; + while ( n--) { + print_ascii_to_html_spc( *current_stream, p); + p += strlen( p) + 1; // skip to next parameter + if ( n) { + *current_stream << ", "; + if ( exp_size > table_width) + *current_stream << "
" << indNewline; + } + } + *current_stream << ");"; + if ( exp_size > table_width) + *current_stream << "
" << indNewline; + } else + *current_stream << ';'; + + bool is_empty_comment = is_text_block_empty( T); + two_cols_html_second( *current_stream, is_empty_comment); + delete[] return_value; + delete[] scope; + delete[] function_name; + delete[] parameter_list; + print_html_text_block( *current_stream, T); + *current_stream << indNewline << "

"; + two_cols_html_end( *current_stream, is_empty_comment); +} + +void format_enum( const char* signature, const Text& T) { + char* return_value; + char* scope; + char* enum_name; + char* parameter_list; + const char* rest; + + split_function_declaration( signature, + return_value, + scope, + enum_name, + parameter_list, + rest, + true); + + char* formatted_enum = convert_ascii_to_html( enum_name); + + if ( &T == &empty_comment) { + // generate a substitution rule for hyperlinking + *anchor_stream << "[a-zA-Z0-9_]\"" << formatted_enum + << "\" { ECHO; }" << endl; + *anchor_stream << "\"" << formatted_enum + << "\"[a-zA-Z0-9_] { ECHO; }" << endl; + *anchor_stream << '"' << formatted_enum + << "\" { fputs( \"" + << formatted_enum << "\", stdout); }" + << endl; + + *current_stream << "" << endl; + + // index + *index_stream << "

  • " << formatted_enum + << "
" << endl; + } + + two_cols_html_begin( *current_stream); + // first, estimate size + double exp_size = 0.0; + if ( scope) + exp_size += estimate_html_size( scope); + if ( return_value) + exp_size += estimate_html_size( return_value); + + + exp_size += estimate_html_size( formatted_enum) + + 3.0 * width_per_character; + int n = 0; + if ( parameter_list) { + exp_size += 2 * width_per_character; + n = separate_parameter_list( parameter_list); + char* p = parameter_list; + int m = n; + while ( m--) { + exp_size += estimate_html_size( p) + width_per_character; + p += strlen( p) + 1; // skip to next parameter + } + } + exp_size *= stretch_factor; + if ( exp_size > table_width && parameter_list) + *current_stream << "" + "
" + << indNewline; + + if ( return_value) { + print_ascii_to_html_spc( *current_stream, return_value); + *current_stream << ' '; + } + if ( scope) + print_ascii_to_html_spc( *current_stream, scope); + *current_stream << formatted_enum; + if ( parameter_list) { + *current_stream << " { "; + if ( exp_size > table_width) + *current_stream << "" + << indNewline; + char* p = parameter_list; + while ( n--) { + while ( *p && *p <= ' ') + ++p; + print_ascii_to_html_spc( *current_stream, p); + + if ( &T == &empty_comment) { + // index: print enum tags with their (possible) initializers + *index_stream << "
  • "; + print_ascii_to_html_spc( *index_stream, p); + *index_stream << "
" << endl; + + // generate a substitution rule for hyperlinking + // Here, the initializer has to suppressed + char* q = p; + while( *q && *q != '=') + ++q; + while ( q>p && q[-1] <= ' ') + --q; + char c_tmp = *q; + *q = '\0'; + char *tmp_param = convert_ascii_to_html( p); + *anchor_stream << "[a-zA-Z0-9_]\"" << tmp_param + << "\" { ECHO; }" << endl; + *anchor_stream << "\"" << tmp_param + << "\"[a-zA-Z0-9_] { ECHO; }" << endl; + *anchor_stream << '"' << tmp_param + << "\" { fputs( \"" + << tmp_param << "\", stdout); }" + << endl; + delete[] tmp_param; + *q = c_tmp; // restore initializer + } + + p += strlen( p) + 1; // skip to next parameter + if ( n) { + *current_stream << ", "; + if ( exp_size > table_width) + *current_stream << "
" << indNewline; + } + } + *current_stream << "};"; + if ( exp_size > table_width) + *current_stream << "
" << indNewline; + } else + *current_stream << ';'; + + bool is_empty_comment = is_text_block_empty( T); + two_cols_html_second( *current_stream, is_empty_comment); + delete[] return_value; + delete[] scope; + delete[] formatted_enum; + delete[] enum_name; + delete[] parameter_list; + print_html_text_block( *current_stream, T); + *current_stream << indNewline << "

"; + two_cols_html_end( *current_stream, is_empty_comment); +} + + +/* Taylored semantic functions used in syntax.y */ +/* ============================================ */ + +void handleMainComment( const Text& T) { + // *current_stream << indNewline << "

" << endl << indNewline; + if ( print_html_text_block( *current_stream, T, true)) + *current_stream << indNewline << "

" << endl; +} + +// void handleComment( const Text& T) { +// print_html_text_block( *current_stream, T); +// three_cols_html_end( *current_stream); +// } + +// void handleConstructorComment( const Text& T) { +// print_html_text_block( *current_stream, T); +// *current_stream << indNewline << "

"; +// two_cols_html_end( *current_stream); +// } + +void handleChapter( const Text& T) { + char* tmp_name = replaceSuffix( in_filename, html_suffix); + char* new_main_filename = addPrefix( chapter_prefix, tmp_name); + delete[] tmp_name; + if ( strcmp( new_main_filename, main_filename) == 0) { + printErrorMessage( ChapterStructureError); + delete[] new_main_filename; + return; + } + if ( class_stream != 0) { + if ( chapter_title) + // navigation footer + *class_stream << "


Return to chapter: " << chapter_title << "" << endl; + close_html( *class_stream); + if ( ! *class_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to file `" + << class_filename << "'." << endl; + exit(1); + } + delete class_stream; + delete[] class_filename; + class_stream = 0; + class_filename = 0; + } + delete[] chapter_title; + chapter_title = text_block_to_string( T); + if ( main_stream != &cout) { + // navigation footer + *main_stream << "
Next chapter: " << chapter_title << "" << endl; + close_html( *main_stream); + if ( ! *main_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to file `" + << main_filename << "'." << endl; + exit(1); + } + delete main_stream; + delete[] main_filename; + main_stream = 0; + main_filename = 0; + } + main_filename = new_main_filename; + main_stream = new ofstream( main_filename); + if ( ! main_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot open main chapter file `" + << main_filename << "'." << endl; + exit(1); + } + current_stream = main_stream; + current_filename = main_filename; + open_html( *main_stream, chapter_title); + // print navigation header + *main_stream << general_navigation << "\n
\n" << endl; + + *main_stream << "

" << chapter_title << "

" << endl; + + // table of contents + *contents_stream << "
  • " << chapter_title << "" << endl; + +} + +void handleBiblio( const Text& T) { + first_bibitem = true; + ofstream out( bib_filename); + if ( ! out) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot open bibliography file `" + << bib_filename << "'." << endl; + exit(1); + } + open_html( out, "Bibliography"); + + // print navigation header + out << general_navigation << "\n
    \n" << endl; + out << "

    Bibliography

    " << endl; + + out << "" << endl; + print_html_text_block( out, T); + + out << "
    " << endl; + close_html( out); + if ( ! out) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to file `" + << bib_filename << "'." << endl; + exit(1); + } +} + +Buffer* handleCite( const char* l) { + Buffer* buf = new Buffer; + buf->add( '['); + while ( *l != '{' && *l != '[') + ++l; + const char* comment = 0; + const char* end_comment = 0; + if ( *l == '[') { + comment = l + 1; + while ( *l != ']') + ++l; + end_comment = l; + while ( *l != '{') + ++l; + } + ++l; + while( *l != '}') { + const char* p = l; + while ( *p != '}' && *p != ',') + ++p; + buf->add( "add( bib_filename); + buf->add( "#Biblio_"); + const char* q = l; + while ( q != p) + buf->add( *q++); + buf->add( "\">"); + q = l; + while ( q != p) + buf->add( *q++); + buf->add( ""); + l = p; + if ( *l == ',') { + ++l; + buf->add( ", "); + } + } + if ( comment) + while ( comment != end_comment) + buf->add( *comment++); + buf->add( ']'); + return buf; +} + +// for an empty item name use the key name as item name +Buffer* handleBibItem( const char* key_name, const char* item_name) { + const char* name = key_name; + if ( item_name) + name = item_name; + Buffer* buf = new Buffer; + if ( ! first_bibitem) { + first_bibitem = false; + buf->add( ""); + } + buf->add( "add( key_name); + buf->add( "\">["); + buf->add( name); + buf->add( "]"); + if ( item_name) { + *anchor_stream << "\"#Biblio_" << key_name + << "\"[\"]\">" << key_name + << "\" { fputs( \"#Biblio_" + << key_name << "\\\">" << item_name + << "\", stdout); }" + << endl; + } + return buf; +} + + +void handleSection( const Text& T) { + static int section_counter = 1; + char* section = text_block_to_string( T); + *current_stream << "" + << endl; + *current_stream << "

    " << section << "

    " << endl; + + // table of contents + *contents_stream << " " << endl; + + ++ section_counter; + delete[] section; +} + +void handleLabel( const char* l) { + /* The lexical processing has removed the prantheses around */ + /* \ref{...} macros from TeX, so here is the correct pattern match */ + /* to find them in the pre-HTML text */ + *anchor_stream << "[\\\\](page)?ref[ \\t]*\"" << l + << "\" { fputs( \"here\", stdout); }" << endl; + // There are two special ref commands defined within the manual + *anchor_stream << "[\\\\]Chapter[ \\t]*\"" << l + << "\" { fputs( \"This Chapter\", stdout); }" + << endl; + *anchor_stream << "[\\\\]Section[ \\t]*\"" << l + << "\" { fputs( \"This Section\", stdout); }" + << endl; + // index + /* ... + *index_stream << "
    • " << l << "
    " << endl; + ... */ +} + +void handleText( const Text& T, bool check_nlnl) { + if ( ! print_html_text_block( *current_stream, T)) { + if ( check_nlnl) { + int count = 0; + InListFIter< TextToken> words( (Text&)T); + ForAll( words) { + if ( (*words).string[0] == '\n') + ++count; + } + if ( count > 1) + *current_stream << "

    \n" << endl; + else if ( count > 0) + *current_stream << '\n'; + else + *current_stream << ' '; + } else + *current_stream << ' '; + } +} + +void handleBuffer( const Buffer& B) { + *current_stream << B.string(); +} + +void handleTextToken( const TextToken& TT) { + *current_stream << TT.string; +} + +void handleString( const char* s) { + *current_stream << s; +} + +void handleChar( char c) { + *current_stream << c; +} + + +void handleClasses( const char* classname, const char* template_cls) { + if ( template_cls) + template_class_name = newstr( template_cls); + else + template_class_name = newstr( classname); + char* t_tmp_name = convert_ascii_to_html( template_class_name); + formatted_template_class_name = new char[ strlen( t_tmp_name) + 12]; + strcpy( formatted_template_class_name, ""); + strcat( formatted_template_class_name, t_tmp_name); + strcat( formatted_template_class_name, ""); + delete[] t_tmp_name; + + if ( class_stream != 0) { + // navigation footer + *class_stream << "


    Next class declaration: " + << formatted_template_class_name << endl; + close_html( *class_stream); + if ( ! *class_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to file `" + << class_filename << "'." << endl; + exit(1); + } + delete class_stream; + delete[] class_filename; + class_stream = 0; + } + class_name = newstr( classname); + + char *tmp_name = convert_ascii_to_html( classname); + formatted_class_name = new char[ strlen( tmp_name) + 12]; + strcpy( formatted_class_name, ""); + strcat( formatted_class_name, tmp_name); + strcat( formatted_class_name, ""); + + class_filename = addSuffix( classname, html_suffix); + class_stream = new ofstream( class_filename); + if ( ! class_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot open class file `" + << class_filename << "'." << endl; + exit(1); + } + open_html( *class_stream, classname); + // print navigation header + if ( main_stream != &cout) { + *main_stream << "
    • \nClass declaration for " + << formatted_template_class_name + << ".
    \n" << endl; + *class_stream << "Chapter,\n"; + } + *class_stream << general_navigation << "\n
    \n" << endl; + + // table of contents + *contents_stream << "
    • Class declaration of " + << formatted_template_class_name << "
    " << endl; + + // index + *index_stream << "
    • " << formatted_template_class_name + << "
    " << endl; + + current_stream = class_stream; + current_filename = class_filename; + + // generate a substitution rule for hyperlinking + *anchor_stream << '"' << class_filename + << "\" { ECHO; }" << endl; + *anchor_stream << "[a-zA-Z0-9_]\"" << tmp_name + << "\" { ECHO; }" << endl; + *anchor_stream << "\"" << tmp_name + << "\"[a-zA-Z0-9_] { ECHO; }" << endl; + if ( template_cls) { + *anchor_stream << '"' << tmp_name + << "\"[ ]*\"<\" {\n" + << " fputs( \"\", stdout);\n" + << " nesting = 1;\n" + << " yymore();\n" + << " BEGIN( PARAMMODE); }\n" + << endl; + } + *anchor_stream << '"' << tmp_name + << "\" { fputs( \"" + << tmp_name << "\", stdout); }" + << endl; + delete[] tmp_name; + creationvariable = newstr( "this"); + formatted_creationvariable = newstr( "this"); +} + +void handleClass( const char* classname) { + handleClasses( classname, 0); +} + +void handleClassEnd( void) { + delete[] class_name; + delete[] template_class_name; + delete[] formatted_class_name; + delete[] formatted_template_class_name; + class_name = 0; + formatted_class_name = 0; + template_class_name = 0; + formatted_template_class_name = 0; + /* ... Hack to implement the link from one class to the next class + close_html( *class_stream); + if ( ! *class_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to file `" + << class_filename << "'." << endl; + exit(1); + } + delete class_stream; + delete[] class_filename; + class_stream = 0; + class_filename = 0; + ... */ + current_stream = main_stream; + current_filename = main_filename; +} + +void handleClassTemplate( const char* classname) { + char* s = (char *)classname; + while ( *s != 0 && *s != '<') s++; + if ( *s == 0) + printErrorMessage( TemplateParamExpectedError); + char c_tmp = *s; + *s = 0; + char *classname_tmp = newstr( classname); + *s = c_tmp; + handleClasses( classname_tmp, classname); + delete[] classname_tmp; +} + +void handleClassTemplateEnd( void) { + handleClassEnd(); +} + + +void handleDeclaration( const char* ) {} + +void handleMethodDeclaration( const char* decl, const Text& T) { + format_function( true, decl, T); +} + +void handleFunctionDeclaration( const char* decl, const Text& T) { + format_function( false, decl, T); +} + +void handleConstructorDeclaration( const char* decl, const Text& T) { + format_constructor( decl, T); +} + +void handleFunctionTemplateDeclaration( const char* , + const char* decl, + const Text& T) { + handleFunctionDeclaration( decl, T); +} + +void handleVariableDeclaration( const char* decl, const Text& T) { + format_variable( decl, T); +} + +void handleEnumDeclaration( const char* decl, const Text& T) { + format_enum( decl, T); +} + + +/* main */ +/* ==== */ + +#define MaxParameters 1000 +#define MaxOptionalParameters 999 +#define ErrParameters 10000 + +/* this macro opens a block, in which the switch is detected */ +/* it must be closed with the macro endDetect() */ +#define detectSwitch( var, text) \ + if ( (( argv[i][0] == '/' ) || ( argv[i][0] == '-' ) || \ + ( argv[i][0] == '+' )) && ( strcmp( text, argv[i]+1) == 0)) { \ + if ( argv[i][0] == '+' ) \ + var = PLUS_SWITCH; \ + else \ + var = MINUS_SWITCH; + +#define endDetect() \ + if ( nParameters <= MaxParameters ) \ + continue; \ + else \ + break; \ + } + + + +/* >main: main function with standard unix parameter input */ +/* ------------------------------------------------------- */ + +main( int argc, char **argv) { + int i; + int nParameters = 0; + char *parameters[ MaxParameters + 1]; + + Switch help_switch = NO_SWITCH; + + for (i = 1; i < argc; i++) { + + /* check switches */ + detectSwitch( trace_switch, "trace"); + yydebug = 1; + endDetect(); + detectSwitch( line_switch, "line"); + endDetect(); + + detectSwitch( help_switch, "h"); + endDetect(); + detectSwitch( help_switch, "H"); + endDetect(); + detectSwitch( help_switch, "help"); + endDetect(); + + /* else get standard or optional paramters */ + if ( nParameters < MaxParameters ) { + parameters[nParameters ++] = argv[i]; + continue; + } + + nParameters = ErrParameters; + break; + } + + if ((nParameters < MaxParameters - MaxOptionalParameters) || + (nParameters > MaxParameters) || (help_switch != NO_SWITCH)) { + if (help_switch == NO_SWITCH) + cerr << "Error: in parameter list" << endl; + cerr << "Usage: cgal_extract_html [] [...]" << endl; + cerr << " -trace sets the `yydebug' variable of bison" + << endl; + cerr << " -line prints parsed line numbers to cerr" + << endl; + cerr << " Infiles including suffixes." + << endl; + exit(1); + } + + // anchor_stream = new ofstream( anchor_filename, ios::out | ios::app); + anchor_stream = new ofstream( anchor_filename); + if ( ! *anchor_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot open anchor file `" + << anchor_filename << "'." << endl; + exit(1); + } + contents_stream = new ofstream( contents_filename); + if ( ! *contents_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot open contents file `" + << contents_filename << "'." << endl; + exit(1); + } + open_html( *contents_stream, "Table of Contents"); + *contents_stream << "

    The CGAL Kernel User Manual
    \n" + " Table of Contents


    \n" << endl; + *contents_stream << "
      " << endl; + *contents_stream << "
    1. Title Page" + << endl; + *contents_stream << "
    2. Table of Contents" << endl; + + index_stream = new ofstream( index_filename); + if ( ! *index_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot open index file `" + << index_filename << "'." << endl; + exit(1); + } + *index_stream << "The CGAL Kernel Manual: Index" + "" << general_comment << "" << endl; + *index_stream << "

      Index


      " << endl; + *index_stream << "" << endl; + *index_stream << "
        " << endl; + + for ( i = 0; i < nParameters; i++) { + FILE* in; + if ( (in = fopen( parameters[i], "r")) == NULL) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot open infile `" + << parameters[i] << "'." << endl; + exit(1); + } + in_filename = parameters[i]; + + main_stream = &cout; + current_stream = main_stream; + current_filename = main_filename; + + init_scanner( in); + yyparse(); + fclose( in); + + if ( class_stream != 0) { + close_html( *class_stream); + if ( ! *class_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to file `" + << class_filename << "'." << endl; + exit(1); + } + delete class_stream; + delete[] class_filename; + class_stream = 0; + class_filename = 0; + } + if ( ! *main_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to file `" + << main_filename << "'." << endl; + exit(1); + } + if ( main_stream != &cout) { + close_html( *main_stream); + if ( ! *main_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to file `" + << main_filename << "'." << endl; + exit(1); + } + delete main_stream; + delete[] main_filename; + main_stream = &cout; + main_filename = ""; + } + } + + // The index is organized in a set of fixed topics. + *index_stream << "
      • Classes

        " << endl; + *index_stream << "

      • Variables and Consts

        " + << endl; + *index_stream << "

      • Enums

        " << endl; + *index_stream << "

      • Enum Tags

        " << endl; + /* ... + *index_stream << "

      • References

        " << endl; + ... */ + *index_stream << "

      • " + "Table of Contents

        " << endl; + *index_stream << "

      • " + "Bibliography" << endl; + *index_stream << "
      " << endl; + *index_stream << "" << endl; + *index_stream << "" << html_address_trailer << endl; + *index_stream << "" << endl; + + if ( ! *index_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to index file `" + << index_filename << "'." << endl; + exit(1); + } + delete index_stream; + + *contents_stream << "
    3. Bibliography" << endl; + *contents_stream << "
    4. Index" << endl; + *contents_stream << "
    " << endl; + close_html( *contents_stream); + if ( ! *contents_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to contents file `" + << contents_filename << "'." << endl; + exit(1); + } + delete contents_stream; + if ( ! *anchor_stream) { + cerr << ' ' << endl + << "cgal_extract_html: error: cannot write to anchor file `" + << anchor_filename << "'." << endl; + exit(1); + } + delete anchor_stream; + delete chapter_title; + + cout << endl; + return 0; +} + +// EOF // + diff --git a/Packages/Manual_tools/src/html_config.h b/Packages/Manual_tools/src/html_config.h new file mode 100644 index 00000000000..1852a55d0b8 --- /dev/null +++ b/Packages/Manual_tools/src/html_config.h @@ -0,0 +1,91 @@ +/************************************************************************** + + confightml.h + ============================================================= + Project : CGAL merger tool for the specification task + Function : Configuration constants and variables + System : C++ (g++) + Author : (c) 1995 Lutz Kettner + Revision : $Revision$ + Date : $Date$ + +**************************************************************************/ + +#if ! defined( MODULE_CONFIG) +#define MODULE_CONFIG 1 + + +// Global declarations that are implemented in the main module. +// There they can be taylored to the specific application, i.e. +// extraction or checker. + +/* An empty List as empty comment for global declarations */ +/* ====================================================== */ +extern Text empty_comment; + +// void handleComment( const Text& T); +// void handleConstructorComment( const Text& T); +void handleMainComment( const Text& T); + +void handleChapter( const Text& T); +void handleSection( const Text& T); +void handleLabel( const char* l); + +void handleText( const Text& T, bool check_nlnl = false); +void handleBuffer( const Buffer& B); +void handleTextToken( const TextToken& TT); +void handleString( const char* s); +void handleChar( char c); + +void handleBiblio( const Text& T); +Buffer* handleCite( const char* l); +// for an empty item name use the key name as item name +Buffer* handleBibItem( const char* key_name, const char* item_name = 0); + +void handleClass( const char* classname); +void handleClassEnd( void); +void handleClassTemplate( const char* classname); +void handleClassTemplateEnd( void); + +void handleDeclaration( const char* decl); + +void handleMethodDeclaration( const char* decl, + const Text& T = empty_comment); +void handleConstructorDeclaration( const char* decl, + const Text& T = empty_comment); +void handleFunctionDeclaration( const char* decl, + const Text& T = empty_comment); +void handleFunctionTemplateDeclaration( const char* templ, + const char* decl, + const Text& T = empty_comment); +void handleVariableDeclaration( const char* decl, + const Text& T = empty_comment); +void handleEnumDeclaration( const char* decl, + const Text& T = empty_comment); + + +// Error messages and Numbers +// ========================== +enum ErrorNumber { + NoError, + ParseError, // must stay at position 1 + VariableUsedError, + ClassnameUsedError, + TemplateParamExpectedError, + MalformedTemplateParamError, + MalformedFunctionDeclaration, + SemicolonMissingError, + IncludeNestingTooDeepError, + IncludeOpenError, + ChapterStructureError +}; + + +// Functions belonging to the Error messages +// ----------------------------------------- +// See their implementations in syntax.y + +const char* errorMessage( ErrorNumber n); +void printErrorMessage( ErrorNumber n); + +#endif // MODULE_CONFIG // diff --git a/Packages/Manual_tools/src/html_lex.yy b/Packages/Manual_tools/src/html_lex.yy new file mode 100644 index 00000000000..02c0d01e7db --- /dev/null +++ b/Packages/Manual_tools/src/html_lex.yy @@ -0,0 +1,1069 @@ +/************************************************************************** + + lexhtml.yy + ============================================================= + Project : CGAL merger tool for the specification task + Function : lexical scanner for TeX and C++ code mixed files. + Taylored for HTML manual generation. + System : flex, bison, C++ (g++) + Author : (c) 1996 Lutz Kettner + Revision : $Revision$ + Date : $Date$ + +**************************************************************************/ + +%{ +extern "C" int yylex( void ); + +#include +#include +#include +#include +#include +#include + +/* Set this flag to 1 to switch immediately to CCMode. */ +int set_CCMode = 0; +/* Set this flag to 1 to switch immediately to NestingMode. */ +int set_NestingMode = 0; +/* Set this flag to 1 to switch back to INITIAL. */ +int set_INITIAL = 0; +int set_HTMLMODE = 0; +int set_MMODE = 0; + +/* Tag to mark the unchecked keyword */ +int unchecked_tag = 0; + +/* Count the linenumber for better errormessages. */ +int line_number = 1; + +/* store the creationvariable */ +char* creationvariable = NULL; +char* formatted_creationvariable = NULL; +extern char* class_name; +extern char* template_class_name; +extern char* formatted_class_name; +extern char* formatted_template_class_name; + +/* match math mode delimiters */ +bool math_mode_toggle = false; + +/* remember the necessary stop character for \verb"..." */ +char stop_character; + +/* prototypes */ +bool is_html_multi_character( char c); +const char* html_multi_character( char c); +char* addSuffix( const char* name, const char* suffix); + +/* enable line number printing to cerr */ +extern char line_switch; + +/* Hack, to get rid of the yywrap. */ +#define YY_SKIP_YYWRAP 1 +#define yywrap() 1 + +void skipspaces( void); +void skipoptionalparam( void); + +/* Include file handling */ +FILE* current_in_stream; +extern const char* in_filename; +#define MAX_INCLUDE_DEPTH 32 +YY_BUFFER_STATE buffer_stack[ MAX_INCLUDE_DEPTH]; +const char* file_name_stack[ MAX_INCLUDE_DEPTH]; +FILE* in_stream_stack[ MAX_INCLUDE_DEPTH]; +int line_number_stack[ MAX_INCLUDE_DEPTH]; +int stack_ptr = 0; + + +#define SET( s) ((yylval.string.text = (s)), ( yylval.string.len = -1)) +%} + +/* The normal scanning mode parses TeX conventions. */ +/* In CCMode, it parses C++ conventions. */ +/* The NestingMode parses only (){}[] nested expressions */ +/* The VerbMode parses LaTeX \verb"..." statements as */ +/* a sequence of characters */ +%x CCMode +%x NestingMode +%x VerbMode +%x CPROGMode +%x ITEMMODE +%x INCLUDEMODE +%x TEXONLYMODE +%x HTMLMODE +%x HTMLGROUPMode +%x MMODE + +letter [a-zA-Z] +noletter [^a-zA-Z] +digit [0-9] +CCletter [a-zA-Z_] +idfier {letter}+ +CCidfier ({CCletter}({CCletter}|{digit})*) +filename [^ \t\n/\\\{\}\[\]()]+ +space [\t ] +w {space}* +ws {space}+ +escchar [\\] +sign [+-] +exp [eE] +number {digit}+ +signNumber ({sign}?{number}) +floatNumber ({signNumber}\.|{signNumber}\.{number}) +expNumber ({floatNumber}|{signNumber}){exp}{signNumber} +No ({signNumber}|{floatNumber}|{expNumber}) +operator [^a-zA-Z_0-9\n\r\t \\] +ttblockintro [\{][\\](tt) +emblockintro [\{][\\](em) +itblockintro [\{][\\]((it)|(sl)) +scblockintro [\{][\\](sc) +bfblockintro [\{][\\](bf) + +%% + /* Mode switching can be triggered from the parser */ + /* ----------------------------------------------- */ + if (set_CCMode) { + BEGIN( CCMode); + set_CCMode = 0; + } + if (set_NestingMode) { + BEGIN( NestingMode); + set_NestingMode = 0; + } + if (set_INITIAL) { + BEGIN( INITIAL); + set_INITIAL = 0; + } + if (set_HTMLMODE) { + BEGIN( HTMLMODE); + set_HTMLMODE = 0; + } + if (set_MMODE) { + BEGIN( MMODE); + set_MMODE = 0; + } + + /* Count line numbers in all modes for better error messages */ + /* --------------------------------------------------------- */ +[\n] { + line_number++; + if ( line_switch) + cerr << "src-line " << line_number << endl; + return NEWLINE; + } +[\\]"\n" { + line_number++; + if ( line_switch) + cerr << "src-line " << line_number << endl; + yylval.string.text = " "; + yylval.string.len = 1; + return SPACE; +} + + /* Handle include files */ + /* ------------------------- */ + +[\\]((include)|(input))[\{]{w} { BEGIN ( INCLUDEMODE); } +{filename} { + /* remove trailing characters from the input/include statement */ + int c = yyinput(); + while( c && c != '}') + c = yyinput(); + if ( stack_ptr >= MAX_INCLUDE_DEPTH) + printErrorMessage( IncludeNestingTooDeepError); + else { + buffer_stack[ stack_ptr] = YY_CURRENT_BUFFER; + file_name_stack[ stack_ptr] = in_filename; + in_stream_stack[ stack_ptr] = current_in_stream; + line_number_stack[ stack_ptr] = line_number; + ++stack_ptr; + /* check whether any suffix is already there or not */ + int i = 0; + while ( i < yyleng && yytext[i] != '.') + ++i; + char* tmp_name; + if ( i < yyleng) + /* this is done to get a 'delete'able copy */ + tmp_name = addSuffix( yytext, ""); + else + tmp_name = addSuffix( yytext, ".tex"); + current_in_stream = fopen( tmp_name, "r"); + if ( ! current_in_stream) { + int j; + printErrorMessage( IncludeOpenError); + delete[] tmp_name; + --stack_ptr; + for ( j = stack_ptr; j >= 0; j--) { + cerr << "file include from `" << file_name_stack[ j] + << "'" << endl; + } + } else { + yyin = current_in_stream; + in_filename = tmp_name; + yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE)); + line_number = 1; + } + } + BEGIN( INITIAL); +} +<> { + if ( stack_ptr <= 0) { + yyterminate(); + } else { + -- stack_ptr; + delete[] (char*)in_filename; + line_number = line_number_stack[ stack_ptr]; + in_filename = file_name_stack[ stack_ptr]; + current_in_stream = in_stream_stack[ stack_ptr]; + yy_switch_to_buffer( buffer_stack[ stack_ptr]); + } +} + + + /* Rules for TeX conventions */ + /* ------------------------- */ +[\\]"%" { /* Avoid the quoted comment symbol */ + yylval.character = '%'; + return CHAR; + } +"%".*[\n]{w} { /* Match one line TeX comments */ + /* remove spaces in next line */ + unput( '\n'); + } +"%".* { /* Match one line TeX comments */ + /* at the last line in file */ + } +[\\]verb{noletter} { /* match LaTeX \verb"..." constructs */ + BEGIN( VerbMode); + stop_character = yytext[ yyleng-1]; + yylval.string.text = "
    ";
    +		    yylval.string.len  = 5;
    +	  	    return STRING;
    +                }
    +{ws}	{
    +	            yylval.string.text = yytext;
    +		    yylval.string.len  = yyleng;
    +	  	    return SPACE;
    +		}
    +.	{
    +		    if ( yytext[0] == stop_character) {
    +		        BEGIN( INITIAL);
    +	                yylval.string.text = "
    "; + yylval.string.len = 6; + return STRING; + } + if ( yytext[0] == '\n') { + line_number++; + if ( line_switch) + cerr << "src-line " << line_number << endl; + } + yylval.character = yytext[0]; + return CHAR; + } + + /* Chapter and labels triggering new file and linking */ + /* -------------------------------------------------- */ +[\\]chapter{w}[\{] { + skipspaces(); + return CHAPTER; +} +[\\]section[*]?{w}[\{] { + return SECTION; +} +[\\]subsection[*]?{w}[\{] { + return SUBSECTION; +} +[\\]subsubsection[*]?{w}[\{] { + return SUBSUBSECTION; +} +[\\]label{w}[\{][^\}]+/[\}] { + yyinput(); + char* s = yytext; + while( *s != '{') + ++s; + ++s; + while( *s && *s <= ' ') + ++s; + yylval.string.text = s; + yylval.string.len = -1; + return LABEL; +} + + + /* Different keywords from the manual style triggering C++ formatting */ + /* ------------------------------------------------------------------ */ +[\\]begin{w}[\{]class[\}]{w} { + BEGIN( CCMode); + return BEGINCLASS; + } +[\\]end{w}[\{]class[\}] { + return ENDCLASS; + } +[\\]begin{w}[\{]classtemplate[\}]{w} { + BEGIN( CCMode); + return BEGINCLASSTEMPLATE; + } +[\\]end{w}[\{]classtemplate[\}] { + return ENDCLASSTEMPLATE; + } +[\\]creationvariable{w}[\{]{w}[^\}]*{w}[\}] { + char *s = yytext + yyleng - 2; + while (( *s == ' ') || ( *s == '\t')) + s--; + char *r = yytext; + while ( *r != '{') + r++; + r++; + while (( *r == ' ') || ( *r == '\t')) + r++; + s[1] = 0; + delete[] creationvariable; + if ( formatted_creationvariable) + delete[] formatted_creationvariable; + creationvariable = newstr( r); + formatted_creationvariable = new char[ strlen( + creationvariable) + 12]; + strcpy( formatted_creationvariable, ""); + strcat( formatted_creationvariable, creationvariable); + strcat( formatted_creationvariable, ""); + yylval.string.text = r; + yylval.string.len = s - r + 1; + return CREATIONVARIABLE; + } +[\\]constructor/{noletter} { /* constructor declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return CONSTRUCTOR; + } +[\\]method/{noletter} { /* method declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return METHOD; + } +[\\]function/{noletter} { /* function declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return FUNCTION; + } +[\\]functiontemplate/{noletter} { /* function template declaration: + change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return FUNCTIONTEMPLATE; + } +[\\]variable/{noletter} { /* variable declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return VARIABLE; + } +[\\]typedef/{noletter} { /* typedef declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return TYPEDEF; + } +[\\]enum/{noletter} { /* enum declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return ENUM; + } +[\\]globalfunction/{noletter} { /* function declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return GLOBALFUNCTION; + } +[\\]globalfunctiontemplate/{noletter} { /* function template declaration: + change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return GLOBALFUNCTIONTEMPLATE; + } +[\\]globalvariable/{noletter} { /* variable declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return GLOBALVARIABLE; + } +[\\]globaltypedef/{noletter} { /* typedef declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return GLOBALTYPEDEF; + } +[\\]globalenum/{noletter} { /* enum declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return GLOBALENUM; + } +[\\]declaration/{noletter} { /* general declaration: change to CCMode */ + skipspaces(); + BEGIN( CCMode); + return DECLARATION; + } +[\\]hidden/{noletter} { + skipspaces(); + return HIDDEN; + } +[\\]unchecked/{noletter} { + /* trigger a global boolean and treat it like a space */ + skipspaces(); + unchecked_tag = 1; + yylval.string.text = " "; + yylval.string.len = 10; + return SPACE; + } + +[\\]"begin{verbatim}" | +[\\]"begin{cprog}" { + BEGIN( CPROGMode); + return CPROGBEGIN; + } +[\\]"end{verbatim}" | +[\\]"end{cprog}" { + BEGIN( INITIAL); + return CPROGEND; + } + +[\\]"begin{HtmlOnly}" { + BEGIN( HTMLGROUPMode); + return HTMLBEGIN; + } +[\\]"end{HtmlOnly}" { + BEGIN( INITIAL); + return HTMLEND; + } + +[\\]"begin{TexOnly}" { + BEGIN( TEXONLYMODE); + return TEXONLYBEGIN; + } +[\\]"end{TexOnly}" { + BEGIN( INITIAL); + return TEXONLYEND; + } +. { + yylval.character = yytext[0]; + return CHAR; + } +[\\]LatexHtml{w}[\{] { + return LATEXHTML; + } +[\\]Anchor{w}[\{] { + /* The first parameter is the URL, the second is the */ + /* message that will be highlighted */ + BEGIN( HTMLMODE); + return ANCHOR; + } +[\}] { + BEGIN( INITIAL); + return '}'; + } +. { + yylval.character = yytext[0]; + return CHAR; + } + + /* Specialized keywords from the manual style */ + /* -------------------------------------------------------------- */ +[\\]CCstyle/{noletter} { /* CCstyle formatting: change to NestingMode */ + skipspaces(); + BEGIN( NestingMode); + return CCSTYLE; + } +[\\]var/{noletter} { + skipspaces(); + if ( creationvariable) { + yylval.string.text = formatted_creationvariable; + yylval.string.len = strlen( yylval.string.text); + } else { + printErrorMessage( VariableUsedError); + yylval.string.text = "Unknown creationvariable"; + yylval.string.len = strlen( yylval.string.text); + } + return STRING; + } +[\\]purevar/{noletter} { + skipspaces(); + if ( creationvariable) { + yylval.string.text = creationvariable; + yylval.string.len = strlen( yylval.string.text); + } else { + printErrorMessage( VariableUsedError); + yylval.string.text = "Unknown creationvariable"; + yylval.string.len = strlen( yylval.string.text); + } + return STRING; + } +[\\]classname/{noletter} { + skipspaces(); + if ( formatted_class_name) { + yylval.string.text = formatted_class_name; + yylval.string.len = strlen( yylval.string.text); + } else { + printErrorMessage( ClassnameUsedError); + yylval.string.text = "Unknown classname"; + yylval.string.len = strlen( yylval.string.text); + } + return STRING; + } +[\\]pureclassname/{noletter} { + skipspaces(); + if ( class_name) { + yylval.string.text = class_name; + yylval.string.len = strlen( yylval.string.text); + } else { + printErrorMessage( ClassnameUsedError); + yylval.string.text = "Unknown classname"; + yylval.string.len = strlen( yylval.string.text); + } + return STRING; + } +[\\]classtemplatename/{noletter} { + skipspaces(); + if ( formatted_template_class_name) { + yylval.string.text = formatted_template_class_name; + yylval.string.len = strlen( yylval.string.text); + } else { + printErrorMessage( ClassnameUsedError); + yylval.string.text = "Unknown template_classname"; + yylval.string.len = strlen( yylval.string.text); + } + return STRING; + } +[\\]puretemplatename/{noletter} { + skipspaces(); + if ( template_class_name) { + yylval.string.text = template_class_name; + yylval.string.len = strlen( yylval.string.text); + } else { + printErrorMessage( ClassnameUsedError); + yylval.string.text = "Unknown template_classname"; + yylval.string.len = strlen( yylval.string.text); + } + return STRING; + } +[\\]CCsection/{noletter} { + skipspaces(); + return CCSECTION; + } +[\\]CC/{noletter} { + skipspaces(); + yylval.string.text = "C++"; + yylval.string.len = 3; + return STRING; + } +[\\]gg/{noletter} { + skipspaces(); + yylval.string.text = "g++"; + yylval.string.len = 3; + return STRING; + } +[\\]nat/{noletter} { + skipspaces(); + yylval.string.text = "N"; + yylval.string.len = -1; + return STRING; + } +[\\]real/{noletter} { + skipspaces(); + yylval.string.text = "R"; + yylval.string.len = -1; + return STRING; + } +[\\]N/{noletter} { + skipspaces(); + yylval.string.text = "N"; + yylval.string.len = -1; + return STRING; + } +[\\]R/{noletter} { + skipspaces(); + yylval.string.text = "R"; + yylval.string.len = -1; + return STRING; + } +[\\]Z/{noletter} { + skipspaces(); + yylval.string.text = "Z"; + yylval.string.len = -1; + return STRING; + } +[\\]E/{noletter} { + skipspaces(); + yylval.string.text = "E"; + yylval.string.len = -1; + return STRING; + } +[\\]leda/{noletter} { + skipspaces(); + /* yylval.string.text = "LEDA"; */ + yylval.string.text = "LEDA"; + yylval.string.len = -1; + return STRING; + } +[\\]cgal/{noletter} { + skipspaces(); + /* yylval.string.text = "CGAL"; */ + yylval.string.text = "CGAL"; + yylval.string.len = -1; + return STRING; + } +[\\]protocgal/{noletter} { + skipspaces(); + /* yylval.string.text = "C++GAL"; */ + yylval.string.text = "C++GAL"; + yylval.string.len = -1; + return STRING; + } +[\\]plageo/{noletter} { + skipspaces(); + /* yylval.string.text = "PLAGEO"; */ + yylval.string.text = "PLAGEO"; + yylval.string.len = -1; + return STRING; + } +[\\]definition/{noletter} { + skipspaces(); + yylval.string.text = "

    Definition

    "; + yylval.string.len = -1; + return STRING; + } +[\\]creation/{noletter} { + skipspaces(); + yylval.string.text = "

    Creation

    "; + yylval.string.len = -1; + return STRING; + } +[\\]operations/{noletter} { + skipspaces(); + yylval.string.text = "

    Operations

    "; + yylval.string.len = -1; + return STRING; + } +[\\]implementation/{noletter} { + skipspaces(); + yylval.string.text = "

    Implementation

    "; + yylval.string.len = -1; + return STRING; + } +[\\]example/{noletter} { + skipspaces(); + yylval.string.text = "

    Example

    "; + yylval.string.len = -1; + return STRING; + } +[\\]precond/{noletter} { + skipspaces(); + yylval.string.text = "
    Precondition: "; + yylval.string.len = -1; + return STRING; + } +[\\]threecolumns/{noletter} { + skipspaces(); + return GOBBLETWOPARAMS; + } +[\\]constructorcolumn/{noletter} { + skipspaces(); + return GOBBLEONEPARAM; + } + + /* keywords from TeX/LaTeX that have an easy HTML counterpart */ + /* -------------------------------------------------------------- */ + +[\\]begin[\{]itemize[\}] { + yylval.string.text = "
      "; + yylval.string.len = 4; + return STRING; + } +[\\]end[\{]itemize[\}] { + yylval.string.text = "
    "; + yylval.string.len = 5; + return STRING; + } +[\\]item[\[] { + BEGIN( ITEMMODE); + yylval.string.text = "
    "; + yylval.string.len = 7; + return STRING; + } +[\]] { + BEGIN( INITIAL); + yylval.string.text = "
    "; + yylval.string.len = 8; + return STRING; + } +[^\]\n]+ { + yylval.string.text = yytext; + yylval.string.len = yyleng; + return STRING; + } +[\\]item/{noletter} { + skipspaces(); + yylval.string.text = "
  • "; + yylval.string.len = 4; + return STRING; + } +[\\]begin[\{]enumerate[\}] { + yylval.string.text = "
      "; + yylval.string.len = 4; + return STRING; + } +[\\]end[\{]enumerate[\}] { + yylval.string.text = "
    "; + yylval.string.len = 5; + return STRING; + } +[\\]begin[\{]description[\}] { + yylval.string.text = "
    "; + yylval.string.len = 4; + return STRING; + } +[\\]end[\{]description[\}] { + yylval.string.text = "
    "; + yylval.string.len = 5; + return STRING; + } +[\\]begin[\{]quote[\}] { + yylval.string.text = "
    "; + yylval.string.len = -1; + return STRING; + } +[\\]end[\{]quote[\}] { + yylval.string.text = "
    "; + yylval.string.len = -1; + return STRING; + } +[\\]((pagebreak)|(newpage)|(clearpage)|(cleardoublepage))/{noletter} { + skipoptionalparam(); + yylval.string.text = "

    "; + yylval.string.len = 3; + return STRING; + } +[\\]ldots/{noletter} { + skipspaces(); + yylval.string.text = "..."; + yylval.string.len = 3; + return STRING; + } +[\\]leq/{noletter} { + skipspaces(); + yylval.string.text = "<="; // ≤ not yet supported + yylval.string.len = 5; + return STRING; + } +[\\]geq/{noletter} { + skipspaces(); + yylval.string.text = ">="; // ≥ not yet supported + yylval.string.len = 5; + return STRING; + } +[\\]neq/{noletter} { + skipspaces(); + yylval.string.text = "≠"; + yylval.string.len = 4; + return STRING; + } +[\\]((big)|(med))skip/{noletter} { + return NEWLINE; + } +[\\]"&" { + yylval.string.text = "&"; + yylval.string.len = 5; + return STRING; + } +[\\][_^#$] { + yylval.character = yytext[1]; + return CHAR; + } +[~] | +[\\]{space} { + yylval.string.text = " "; + yylval.string.len = 1; + return SPACE; + } +[\\][\\] { + skipoptionalparam(); + yylval.string.text = " "; + yylval.string.len = 1; + return SPACE; + } + + /* Mathmode */ + /* -------------------------------------------------------------- */ +[\\][(\[] | +[$] { + BEGIN (MMODE); + return BEGINMATH; + } +[\\][)\]] | +[$] { + BEGIN (INITIAL); + return ENDMATH; + } +"_"[^\{] { + yylval.character = yytext[1]; + return SINGLESUBSCRIPT; + } +"^"[^\{] { + yylval.character = yytext[1]; + return SINGLESUPERSCRIPT; + } +"_"[\{] { + return BEGINSUBSCRIPT; + } +"^"[\{] { + return BEGINSUPERSCRIPT; + } +\frac/{noletter} { + return FRACTION; + } +[\\][\{\}] { + yylval.character = yytext[1]; + return CHAR; + } +[\{\}] { + return yytext[0]; + } + + /* yet not supported characters ... + [\\]times/{noletter} { SET( "×"); return STRING;} + [\\]delta/{noletter} { SET( "δ"); return STRING;} + [\\]epsilon/{noletter} { SET( "ε"); return STRING;} + [\\]varepsilon/{noletter} { SET( "ε"); return STRING;} + [\\]lambda/{noletter} { SET( "λ"); return STRING;} + [\\]pi/{noletter} { SET( "π"); return STRING;} + [\\]varpi/{noletter} { SET( "ϖ"); return STRING;} + ... */ + +[\\]["]a { SET( "ä"); return STRING;} +[\\]["]o { SET( "ö"); return STRING;} +[\\]["]u { SET( "ü"); return STRING;} +[\\]["]A { SET( "Ä"); return STRING;} +[\\]["]O { SET( "Ö"); return STRING;} +[\\]["]U { SET( "Ü"); return STRING;} +[\\][']a { SET( "á"); return STRING;} +[\\][']e { SET( "é"); return STRING;} +[\\][`]a { SET( "à"); return STRING;} +[\\][`]e { SET( "è"); return STRING;} +[\\]"^"a { SET( "â"); return STRING;} +[\\]"^"e { SET( "ê"); return STRING;} +[\\]ss[\{][\}] { SET( "ß"); return STRING;} +[\\]times/{noletter} { SET( "x"); return STRING;} +[\\]alpha/{noletter} { SET( "α"); return STRING;} +[\\]beta/{noletter} { SET( "β"); return STRING;} +[\\]gamma/{noletter} { SET( "γ"); return STRING;} +[\\]delta/{noletter} { SET( "delta"); return STRING;} +[\\]epsilon/{noletter} { SET( "eps"); return STRING;} +[\\]varepsilon/{noletter} { SET( "eps"); return STRING;} +[\\]zeta/{noletter} { SET( "ζ"); return STRING;} +[\\]eta/{noletter} { SET( "η"); return STRING;} +[\\]theta/{noletter} { SET( "θ"); return STRING;} +[\\]vartheta/{noletter} { SET( "ϑ"); return STRING;} +[\\]iota/{noletter} { SET( "ι"); return STRING;} +[\\]kappa/{noletter} { SET( "κ"); return STRING;} +[\\]lambda/{noletter} { SET( "lambda"); return STRING;} +[\\]mu/{noletter} { SET( "μ"); return STRING;} +[\\]nu/{noletter} { SET( "ν"); return STRING;} +[\\]xi/{noletter} { SET( "ξ"); return STRING;} +[\\]pi/{noletter} { SET( "pi"); return STRING;} +[\\]varpi/{noletter} { SET( "pi"); return STRING;} +[\\]rho/{noletter} { SET( "ρ"); return STRING;} +[\\]varrho/{noletter} { SET( "ρ"); return STRING;} +[\\]sigma/{noletter} { SET( "σ"); return STRING;} +[\\]varsigma/{noletter} { SET( "ς"); return STRING;} +[\\]tau/{noletter} { SET( "τ"); return STRING;} +[\\]upsilon/{noletter} { SET( "υ"); return STRING;} +[\\]phi/{noletter} { SET( "φ"); return STRING;} +[\\]varphi/{noletter} { SET( "ϕ"); return STRING;} +[\\]chi/{noletter} { SET( "χ"); return STRING;} +[\\]psi/{noletter} { SET( "ψ"); return STRING;} +[\\]omega/{noletter} { SET( "ω"); return STRING;} +[\\]Gamma/{noletter} { SET( "Γ"); return STRING;} +[\\]Delta/{noletter} { SET( "Δ"); return STRING;} +[\\]Theta/{noletter} { SET( "Θ"); return STRING;} +[\\]Lambda/{noletter} { SET( "Λ"); return STRING;} +[\\]Xi/{noletter} { SET( "Ξ"); return STRING;} +[\\]Pi/{noletter} { SET( "Π"); return STRING;} +[\\]Sigma/{noletter} { SET( "Σ"); return STRING;} +[\\]Upsilon/{noletter} { SET( "ϒ"); return STRING;} +[\\]Phi/{noletter} { SET( "Φ"); return STRING;} +[\\]Psi/{noletter} { SET( "Ψ"); return STRING;} +[\\]Omega/{noletter} { SET( "Ω"); return STRING;} + + + /* keywords from TeX/LaTeX that should vanish in HTML */ + /* -------------------------------------------------------------- */ +[\\]((smallskip)|(protect)|(sloppy))/{noletter} {} +[\\]((maketitle)|(tableofcontents))/{noletter} {} +[\\]((begin)|(end))[\{]document[\}] {} + +[\\]newsavebox{w}[\{] | +[\\]usebox{w}[\{] | +[\\][*]?hspace{w}[\{] | +[\\][*]?vspace{w}[\{] | +[\\]g?def{w}[\\]{letter}+[^\{]*[\{] { + /* CCstyle formatting: change to NestingMode */ + BEGIN( NestingMode); + return IGNOREBLOCK; + } +[\\]((documentclass)|(documentstyle)|(usepackage)|(pagestyle)|(pagenumbering)|(bibliographystyle)|(bibliography)|(title)|(author)|(date)){w}/{noletter} { + skipoptionalparam(); + yyinput(); /* gobble opening brace */ + BEGIN( NestingMode); + return IGNOREBLOCK; + } +[\\]((textwidth)|(textheight)|(topmargin)|(evensidemargin)|(oddsidemargin)|(headsep)|(parindent)|(parskip)){w}[-+0-9.]+{w}.. {} + +[\\]newcommand{w}[\{][^\}]*[\}]([\[][^\]]*[\]])[\{] { + /* CCstyle formatting: change to NestingMode */ + BEGIN( NestingMode); + return IGNOREBLOCK; + } +[\\]((savebox)|(setlength)|(setcounter)){w}[\{] { + /* CCstyle formatting: change to NestingMode */ + BEGIN( NestingMode); + return IGNORETWOBLOCKS; + } +[\\]begin[\{]minipage[\}] | +[\\]end[\{]minipage[\}] { + skipoptionalparam(); + yylval.string.text = " "; + yylval.string.len = 1; + return SPACE; + } + +[\\](([mvhf]box)|(parbox)|([hv]fill)|(nopagebreak)|(nolinebreak)|(linebreak)|(samepage))/{noletter} { + skipoptionalparam(); + yylval.string.text = " "; + yylval.string.len = 1; + return SPACE; + } + + + /* Support for the Bibliography */ + /* ---------------------------- */ +[\\]begin[\{]thebibliography[\}][\{][^\}]*[\}] { + return BEGINBIBLIO; + } +[\\]end[\{]thebibliography[\}] { + return ENDBIBLIO; + } +[\\]newblock/{noletter} {} +[\\]cite{w}([\[][^\]]*[\]])?[\{][^\}]*[\}] { + yylval.string.text = yytext; + yylval.string.len = yyleng; + return CITE; + } +[\\]bibitem{w}/{noletter} { + BEGIN( NestingMode); + return BIBITEM; + } + + + /* Grouping symbols */ + /* ---------------- */ +[\\][\{] { + yylval.character = '{'; + return CHAR; + } +[\\][\}] { + yylval.character = '}'; + return CHAR; + } +[\\]left. { + yylval.character = yytext[5]; + return CHAR; + } +[\\]right. { + yylval.character = yytext[6]; + return CHAR; + } +[\{] { + return '{'; + } +[\}] { + return '}'; + } + +{ttblockintro} { /* A couple of TeX styles like {\tt ... */ + return TTBLOCKINTRO; + } +{emblockintro} { return EMBLOCKINTRO; } +{itblockintro} { return ITBLOCKINTRO; } +{scblockintro} { return SCBLOCKINTRO; } +{bfblockintro} { return BFBLOCKINTRO; } + +[\[] { + return '['; + } +[\]] { + return ']'; + } + +[\(] { + return '('; + } +[\)] { + return ')'; + } + + /* The rest: spaces and single characters */ + /* -------------------------------------- */ +[\\]?{ws} { + if ( *yytext == '\\') { + yylval.string.text = yytext + 1; + yylval.string.len = yyleng - 1; + } else { + yylval.string.text = yytext; + yylval.string.len = yyleng; + } + return SPACE; + } +{ws} { + yylval.string.text = yytext; + yylval.string.len = yyleng; + return SPACE; + } +. { + yylval.character = yytext[0]; + return CHAR; + } +. { + yylval.character = yytext[0]; + if ( is_html_multi_character( yylval.character)) { + yylval.string.text = html_multi_character( + yylval.character); + yylval.string.len = strlen( yylval.string.text); + return STRING; + } + return CHAR; + } +%% + +void init_scanner( FILE* in){ + line_number = 1; + set_CCMode = 0; + set_NestingMode = 0; + set_INITIAL = 0; + unchecked_tag = 0; + current_in_stream = in; + stack_ptr = 0; + yyrestart( in); +} + +void skipspaces( void) { + int c = yyinput(); + while( c && c <= ' ') + c = yyinput(); + unput( c); +} + +void skipoptionalparam( void) { + int c = yyinput(); + while( c && c <= ' ') + c = yyinput(); + if ( c == '[') + while( c && c != ']') + c = yyinput(); + else + unput( c); +} diff --git a/Packages/Manual_tools/src/html_syntax.y b/Packages/Manual_tools/src/html_syntax.y new file mode 100644 index 00000000000..5ab38e9c0af --- /dev/null +++ b/Packages/Manual_tools/src/html_syntax.y @@ -0,0 +1,920 @@ +/************************************************************************** + + syntax.y + ============================================================= + Project : CGAL merger tool for the specification task + Function : grammatical parser for TeX and C++ code mixed files. + Taylored for HTML manual generation. + System : bison, flex, C++ (g++) + Author : (c) 1996 Lutz Kettner + Revision : $Revision$ + Date : $Date$ + +**************************************************************************/ + +%{ +#include +#include +#include +#include + +/* Declarations from lex.yy */ +/* ======================== */ +extern int set_CCMode; +extern int set_NestingMode; +extern int set_INITIAL; +extern int set_HTMLMODE; +extern int set_MMODE; +extern int line_number; + +extern const char* in_filename; +extern char* creationvariable; + +extern char *yytext; + +extern "C" { +int yylex( void); +void init_scanner( FILE* in); +} + +/* Declarations for the parser */ +/* =========================== */ +/* This variable flags for bison that we are in the CCMode */ +int CCMode = 0; + +/* Datastructures for the parser */ +/* ============================= */ +#include +#include + +/* Declarations from the cgal_extract_html.cc file */ +/* =============================================== */ +extern char* class_name; +extern char* formatted_class_name; +char* text_block_to_string( const Text& T); + +/* for the bibliography */ +/* ==================== */ +extern bool first_bibitem; + +/* Own prototypes */ +/* ============== */ +int yyerror( char *s); +Text* blockintroProcessing( const char* text, int len, Text* t); + +%} + +%union { + struct { + const char* text; /* a (meaningless) chunk of zero terminated text */ + int len; /* its length */ + } string; + char character; /* a (meaningless) character */ + Buffer* pBuffer; /* Buffer for collected strings and characters */ + TextToken* pTextToken; + Text* pText; +} + +/* Elementary data types */ +/* --------------------- */ +%token STRING +%token SPACE +%token CHAR +%token NEWLINE + +/* Keywords to trigger on */ +/* ---------------------- */ +%token CHAPTER +%token SECTION +%token SUBSECTION +%token SUBSUBSECTION +%token BEGINBIBLIO +%token ENDBIBLIO +%token BIBITEM +%token CITE +%token LABEL +%token BEGINCLASS +%token ENDCLASS +%token BEGINCLASSTEMPLATE +%token ENDCLASSTEMPLATE +%token CREATIONVARIABLE +%token CONSTRUCTOR +%token METHOD +%token FUNCTION +%token FUNCTIONTEMPLATE +%token VARIABLE +%token TYPEDEF +%token ENUM +%token GLOBALFUNCTION +%token GLOBALFUNCTIONTEMPLATE +%token GLOBALVARIABLE +%token GLOBALTYPEDEF +%token GLOBALENUM +%token DECLARATION + +/* Special action keywords */ +/* ----------------------- */ +%token CPROGBEGIN +%token CPROGEND +%token HIDDEN + +%token TEXONLYBEGIN +%token TEXONLYEND +%token LATEXHTML +%token ANCHOR +%token HTMLBEGIN +%token HTMLEND + +%token CCSTYLE +%token CCSECTION +%token GOBBLEONEPARAM +%token GOBBLETWOPARAMS +%token IGNOREBLOCK +%token IGNORETWOBLOCKS +%token TTBLOCKINTRO +%token EMBLOCKINTRO +%token ITBLOCKINTRO +%token SCBLOCKINTRO +%token BFBLOCKINTRO + +%token BEGINMATH +%token ENDMATH +%token SINGLESUBSCRIPT +%token SINGLESUPERSCRIPT +%token BEGINSUBSCRIPT +%token BEGINSUPERSCRIPT +%token FRACTION + +/* handle LALR(1) restriction */ +/* -------------------------- */ +%token LALRRESTRICTION + +%type blockintro + +%type string string_token string_with_nl string_with_nl_token +%type string_with_nl_or_mt string_with_spcnl_token +%type verbatim_style +%type math_sequence math_token +%type declaration classname template_params +%type cc_stmts cc_stmt cc_stmts_skip_space +%type comment_group comment_sequence +%type nested_token_sequence nested_token +%type compound_comment full_comment_sequence +%type non_empty_comment_sequence + +%type whitespaces optional_whitespaces + +%type comment_token non_empty_token whitespace + + + +%% +/* Grammar: Top Level */ +/* ================== */ + +input: /* empty */ + | input stmt +; + +stmt: string { handleBuffer( * $1); delete $1;} + | whitespaces { handleText( * $1, true); + delete $1; + } + | verbatim_style { handleBuffer( * $1); delete $1;} + | CHAPTER + comment_sequence + '}' { handleChapter( * $2); delete $2;} + | BEGINCLASS + classname { handleClass( $2->string()); + delete $2;} + decl_sequence + ENDCLASS + { + handleClassEnd(); + free( creationvariable); + creationvariable = NULL; + } + | BEGINCLASSTEMPLATE + classname { handleClassTemplate( $2->string()); + delete $2;} + decl_sequence + ENDCLASSTEMPLATE + { + handleClassTemplateEnd(); + free( creationvariable); + creationvariable = NULL; + } + | CREATIONVARIABLE {} + | CCSTYLE '{' nested_token_sequence '}' { + set_INITIAL = 1; + handleString( ""); + handleText( * $3); + handleString( ""); + delete $3; + } + | global_tagged_declarator + | group +; + +group: '{' + input + '}' + | blockintro + input + '}' {} +; + +/* Auxiliary Rules */ +/* =============================== */ +blockintro: TTBLOCKINTRO { $$.text = "\0"; $$.len = 4; } + | EMBLOCKINTRO { $$.text = "\0"; $$.len = 4; } + | ITBLOCKINTRO { $$.text = "\0"; $$.len = 3; } + | SCBLOCKINTRO { $$.text = "\0"; $$.len = -1; } + | BFBLOCKINTRO { $$.text = "\0"; $$.len = 3; } +; + + +string_with_nl_or_mt: { $$ = new Buffer; /* Empty */ } + | string_with_nl +; + +string_with_nl: string_with_nl_token + | string_with_nl string_with_nl_token { + $$ = $1; + $$->add( $2); + delete $2; + } +; + +string: string_token + | string string_token { + $$ = $1; + $$->add( $2); + delete $2; + } +; + +string_with_spcnl_token: + string_token + | whitespace { + $$ = new Buffer; + $$->add( $1->string, $1->len); + delete $1; + } +; +string_with_nl_token: + string_token + | NEWLINE { + $$ = new Buffer; + $$->add( '\n'); + } +; +string_token: STRING { + $$ = new Buffer; + $$->add( $1.text, $1.len); + } + | LABEL { + handleLabel( $1.text); + $$ = new Buffer; + $$->add( "add( $1.text, $1.len); + $$->add( "\">"); + } + | CITE { $$ = handleCite( $1.text); } + | BIBITEM '{' nested_token_sequence '}' { + set_INITIAL = 1; + char* s = text_block_to_string(* $3); + $$ = handleBibItem( s); + delete[] s; + delete $3; + } + | BIBITEM '[' nested_token_sequence ']' + '{' nested_token_sequence '}' { + set_INITIAL = 1; + char* s = text_block_to_string(* $3); + char* p = text_block_to_string(* $6); + $$ = handleBibItem( p, s); + delete[] s; + delete[] p; + delete $3; + delete $6; + } + | BEGINMATH math_sequence ENDMATH { + $$ = $2; + $$->prepend( "", 6); + $$->add( "", 7); + } + | CHAR { + $$ = new Buffer; + $$->add( $1); + } +; + +non_empty_token: string { $$ = new TextToken( + $1->string(), $1->length()); + delete $1; + } +; + +optional_whitespaces: /* empty */ { $$ = new Text( managed); } + | whitespaces { $$ = $1; } +; + +whitespaces: whitespace { $$ = new Text( * $1, managed); } + | whitespaces whitespace { + $$ = $1; + $$->append( * $2); + } +; + +whitespace: SPACE { $$ = new TextToken( $1.text, $1.len, true); } + | NEWLINE { $$ = new TextToken( "\n", 1, true); } + | GOBBLETWOPARAMS comment_group comment_group + { $$ = new TextToken( " ", 1, true); + delete $2; + delete $3; + } + | GOBBLEONEPARAM comment_group + { $$ = new TextToken( " ", 1, true); + delete $2; + } + | IGNOREBLOCK comment_sequence '}' { + $$ = new TextToken( " ", 1, true); + delete $2; + set_INITIAL = 1; + } + | IGNORETWOBLOCKS comment_sequence '}' + '{' comment_sequence '}' { + $$ = new TextToken( " ", 1, true); + delete $2; + delete $5; + set_INITIAL = 1; + } + | texonly_style + { $$ = new TextToken( " ", 1, true); + } +; + + + +/* Class Declaration with Comments */ +/* =============================== */ +decl_sequence: comment_sequence { + handleMainComment( * $1); + delete $1; + } + | decl_sequence + tagged_declarator + comment_sequence { + handleMainComment( * $3); + delete $3; + } +; + +tagged_declarator: + global_tagged_declarator + | CONSTRUCTOR declaration comment_group { + handleConstructorDeclaration( $2->string(), + * $3); + delete $2; + delete $3; + } + | METHOD declaration comment_group { + handleMethodDeclaration( $2->string(), * $3); + delete $2; + delete $3; + } +; + +global_tagged_declarator: + SECTION + comment_sequence + '}' { handleSection( * $2); delete $2;} + | SUBSECTION + comment_sequence + '}' { + handleString( "

    "); + handleText( * $2); + handleString( "

    \n"); + delete $2; + } + | SUBSUBSECTION + comment_sequence + '}' { + handleString( "

    "); + handleText( * $2); + handleString( "

    \n"); + delete $2; + } + | BEGINBIBLIO + comment_sequence + ENDBIBLIO { handleBiblio( * $2); delete $2;} + | FUNCTION declaration comment_group { + handleFunctionDeclaration( $2->string(), + * $3); + delete $2; + delete $3; + } + | FUNCTIONTEMPLATE + template_params + optional_whitespaces + declaration + comment_group { + handleFunctionTemplateDeclaration( + $2->string(), + $4->string(), + * $5); + delete $2; + delete $3; + delete $4; + delete $5; + } + | VARIABLE declaration comment_group { + handleVariableDeclaration( $2->string(), + * $3); + delete $2; + delete $3; + } + | TYPEDEF declaration comment_group { + handleVariableDeclaration( $2->string(), * $3); + delete $2; + delete $3; + } + | ENUM declaration comment_group { + handleEnumDeclaration( $2->string(), * $3); + delete $2; + delete $3; + } + | GLOBALFUNCTION declaration { + handleFunctionDeclaration( $2->string()); + delete $2; + } + | GLOBALFUNCTIONTEMPLATE + template_params + optional_whitespaces + declaration { + handleFunctionTemplateDeclaration( + $2->string(), + $4->string()); + delete $2; + delete $3; + delete $4; + } + | GLOBALVARIABLE declaration { + handleVariableDeclaration( $2->string()); + delete $2; + } + | GLOBALTYPEDEF declaration { + handleVariableDeclaration( $2->string()); + delete $2; + } + | GLOBALENUM declaration { + handleEnumDeclaration( $2->string()); + delete $2; + } + | DECLARATION declaration { + handleDeclaration( $2->string()); + delete $2; + } + | HIDDEN + optional_whitespaces + hidden_keys + declaration + comment_group { + delete $2; + delete $4; + delete $5; + } +; + +hidden_keys: CONSTRUCTOR + | METHOD + | FUNCTION + | VARIABLE + | TYPEDEF + | ENUM +; + +/* A sequence of words forming a comment */ +/* ===================================== */ +comment_group: optional_whitespaces '{' comment_sequence '}' { + $$ = $3; + delete $1; + } + | optional_whitespaces blockintro comment_sequence '}' { + $$ = blockintroProcessing( $2.text, + $2.len, + $3); + delete $1; + } +; + +comment_sequence: optional_whitespaces { $$ = new Text( managed); } + | optional_whitespaces + non_empty_comment_sequence + optional_whitespaces { $$ = $2; } +; + +full_comment_sequence: /* empty */ { $$ = new Text( managed); } + | whitespaces { $$ = $1; } + | optional_whitespaces + non_empty_comment_sequence + optional_whitespaces { + $$ = $1; + $$->append( * $2); + $$->append( * $3); + } +; + +non_empty_comment_sequence: + comment_token { $$ = new Text( * $1, managed); } + | compound_comment { $$ = $1; } + | non_empty_comment_sequence optional_whitespaces comment_token { + $$ = $1; + $$->append( * $2); + $$->append( * $3); + } + | non_empty_comment_sequence + optional_whitespaces + compound_comment { + $$ = $1; + $$->append( * $2); + $$->append( * $3); + } +; + +comment_token: non_empty_token { $$ = $1; } + | comment_token non_empty_token { + $$ = $1; + $$->add( * $2); + delete $2; + } +; + +compound_comment: '{' full_comment_sequence '}' { + $$ = $2; + /* $$->cons( *new TextToken( "{", 1)); */ + /* $$->append( *new TextToken( "}", 1)); */ + } + | '(' full_comment_sequence ')' { + $$ = $2; + $$->cons( *new TextToken( "(", 1)); + $$->append( *new TextToken( ")", 1)); + } + | '[' full_comment_sequence ']' { + $$ = $2; + $$->cons( *new TextToken( "[", 1)); + $$->append( *new TextToken( "]", 1)); + } + | blockintro full_comment_sequence '}' { + $$ = blockintroProcessing( $1.text, + $1.len, + $2); + } + | CCSTYLE '{' nested_token_sequence '}' { + $$ = $3; + set_INITIAL = 1; + if ( $$->isEmpty() || + $$->head().isSpace) // should not + $$->cons( *new TextToken( "", 1)); + else + $$->head().prepend( ""); + InListFIter< TextToken> ix( * $$); + ForAll( ix) { + if ( ix.isLast()) + if ( ix->isSpace) + $$->append( *new TextToken( + "", 1)); + else + ix->add( ""); + } + } + | verbatim_style { + $$ = new Text( managed); + $$->cons( *new TextToken( $1->string())); + } + | CCSECTION '{' comment_sequence '}' { + $$ = $3; + $$->cons( *new TextToken( " ", 1, true)); + $$->cons( *new TextToken( "

    ")); + $$->cons( *new TextToken( "\n", 1, true)); + $$->append( *new TextToken( " (")); + $$->append( *new TextToken( + formatted_class_name)); + $$->append( *new TextToken( ")

    ")); + $$->append( *new TextToken( "\n", 1, true)); + } + | CREATIONVARIABLE { $$ = new Text( managed);} +; + +/* Parsing of a C++ expression/statement with nested expressions */ +/* ============================================================= */ +nested_token_sequence: + /* empty */ { + $$ = new Text(managed); + } + | nested_token_sequence nested_token + { + $1->append( * $2); + $$ = $1; + } +; + +nested_token: string { + $$ = new Text(*new TextToken( + $1->string(), + $1->length()), + managed); + delete $1; + } + | SPACE { + $$ = new Text(*new TextToken( + $1.text, + $1.len, + true), + managed); + } + | NEWLINE { + $$ = new Text(*new TextToken( "\n", 1, true), + managed); + } + | '{' nested_token_sequence '}' { + $2->cons( *new TextToken( "{", 1)); + $2->append( *new TextToken( "}", 1)); + $$ = $2; + } + | blockintro nested_token_sequence '}' { + $$ = blockintroProcessing( $1.text, + $1.len, + $2); + } + | '[' nested_token_sequence ']' { + $2->cons( *new TextToken( "[", 1)); + $2->append( *new TextToken( "]", 1)); + $$ = $2; + } + | '(' nested_token_sequence ')' { + $2->cons( *new TextToken( "(", 1)); + $2->append( *new TextToken( ")", 1)); + $$ = $2; + } +; + +/* Parsing of a C++ Declaration (function, method ..., not class) */ +/* ============================================================== */ +declaration: '{' { + CCMode = 1; + } + cc_stmts_skip_space + '}' { + set_INITIAL = 1; + CCMode = 0; + $$ = $3; + } +; + +classname: '{' { + CCMode = 1; + } + cc_stmts_skip_space + '}' { + set_INITIAL = 1; + CCMode = 0; + $$ = $3; + } +; + +template_params: '{' { + CCMode = 1; + } + cc_stmts_skip_space + '}' { + /* set_INITIAL = 1; */ + CCMode = 0; + $$ = $3; + } +; + +cc_stmts: /* empty */ + { $$ = new Buffer;} + | cc_stmts cc_stmt { + $$ = $1; + $$->add( $2); + delete $2; + } +; + +cc_stmt: string { $$ = $1; + } + | SPACE { $$ = new Buffer; + $$->add( ' '); + } + | NEWLINE { $$ = new Buffer; + $$->add( ' '); + } + | '{' + cc_stmts + '}' { + $$ = $2; + $$->prepend( '{'); + $$->add( '}'); + } +; + +cc_stmts_skip_space: + /* empty */ + { $$ = new Buffer;} + | string + cc_stmts { $$ = $1; + $$->add( $2); + delete $2; + } + | SPACE cc_stmts { $$ = $2;} + | NEWLINE cc_stmts { $$ = $2;} + | '{' + cc_stmts + '}' + cc_stmts { + $$ = $2; + $$->prepend( '{'); + $$->add( '}'); + $$->add( $4); + delete $4; + } +; + +/* Parsing of the CPROG environment and other verbatim environments */ +/* ================================================================ */ +verbatim_style: CPROGBEGIN string_with_nl_or_mt CPROGEND { + $$ = $2; + $$->prepend( "
    " , 5);
    +				  $$->add(     "
    ", 6); + } + | HTMLBEGIN string_with_nl_or_mt HTMLEND { + $$ = $2; + } + | LATEXHTML + comment_sequence + '}' '{' { + delete $2; + set_HTMLMODE = 1; + } + string_with_nl_or_mt '}' + { + $$ = $6; + } + | ANCHOR + string_with_nl_or_mt + '}' + comment_group + { + $$ = $2; + $$->prepend( "add( "\">"); + char* s = text_block_to_string( * $4); + $$->add( s); + $$->add( ""); + delete s; + delete $4; + } +; +texonly_style: TEXONLYBEGIN string_with_nl TEXONLYEND { + delete $2; + } +; + +/* Parsing of mathematical formulas from TeX */ +/* ========================================= */ +math_sequence: + /* empty */ + { + $$ = new Buffer; + } + | math_sequence + math_token + { + $$ = $1; + $$->add( $2); + delete $2; + } +; + +math_token: + string_with_spcnl_token + | '{' + math_sequence + '}' + { + $$ = $2; + } + | SINGLESUBSCRIPT + { + $$ = new Buffer; + $$->add( "", 5); + $$->add( $1); + $$->add( "", 6); + } + | SINGLESUPERSCRIPT + { + $$ = new Buffer; + $$->add( "", 5); + $$->add( $1); + $$->add( "", 6); + } + | BEGINSUBSCRIPT math_sequence '}' + { + $$ = $2; + $$->prepend( "", 5); + $$->add( "", 6); + } + | BEGINSUPERSCRIPT math_sequence '}' + { + $$ = $2; + $$->prepend( "", 5); + $$->add( "", 6); + } + | FRACTION '{' math_sequence '}' '{' math_sequence '}' + { + $$ = $3; + $$->prepend( "", 5); + $$->add( "", 6); + $$->add( $6); + $$->add( "", 6); + delete $6; + } +; + +/* End if Grammar */ +/* ============== */ +%% + +int yyerror( char *s) { + fprintf( stderr, + "error 1 in line %d in %s: in %s-code: %s.\n", + line_number, + in_filename, + (CCMode ? "CC" : "TeX"), + s); + return 0; +} + +// Functions belonging to the Error messages +// ----------------------------------------- +// See their implementations in parser.y + +const char* errorMessage( ErrorNumber n) { + switch ( n) { + case NoError: + return "NO ERROR"; + case ParseError: + return "parse error"; + case VariableUsedError: + return "The creationvariable was used but not defined"; + case ClassnameUsedError: + return "The classname was used out of scope of any class"; + case TemplateParamExpectedError: + return "A template parameter is missing"; + case MalformedTemplateParamError: + return "The template parameter is malformed (<> nesting ..)"; + case MalformedFunctionDeclaration: + return "The function declaration is malformed"; + case SemicolonMissingError: + return "The declaration does not end in a semicolon"; + case IncludeNestingTooDeepError: + return "Includes nested too deeply"; + case IncludeOpenError: + return "Cannot open include file"; + case ChapterStructureError: + return "Malformed chapter structure: one chapter per file"; + } + return "UNKNOWN ERROR MESSAGE NUMBER"; +} + +void printErrorMessage( ErrorNumber n){ + cerr << "error " << n << " in line " << line_number << " in `" + << in_filename << "': " << errorMessage( n) << "." << endl; +} + + +// support functions +// ----------------- +Text* blockintroProcessing( const char* text, int len, Text* t) { + if ( len < 0) { /* Hack! Here we know that t has to get capitalized.*/ + len = 4; + InListFIter< TextToken> ix( *t); + ForAll( ix) { + if ( ! (*ix).isSpace) { + char *s = (*ix).string; + while ( *s) { + *s++ = toupper( *s); + } + } + } + } + if ( ! t->isEmpty()) { + t->head().prepend( TextToken( text, len)); + /* Hack! ptr arithmetic points to the closing tag text */ + t->append( * new TextToken( text + len + 1)); + } + return t; +}