#ifdef WIN32 #pragma warning(disable: 4786) // Stop warnings about truncated identifiers in debug info #endif #include #include #include #include #include #include #include #include "parser.h" #include "cmm.h" #include "../utils/exceptionstream.h" #include "../utils/debug.h" #include "../utils/profil.h" using namespace parser; namespace { // Windows-specific error handling void System( const char* command) { if ( command[0]==0) return; if ( int e = system( command)) { std::stringstream msg; if ( e<0) msg << "system( `" << command << "') failed to run the command: errno=" << errno << ", `" << strerror( errno) << "'"; else msg << "system( `" << command << "') failed: command returned error number " << e; // This follows the Win32 documents for system(); may not be portable. throw std::runtime_error( msg.str()); } } void OutputHelp( std::ostream& out) { out << "\n" "cmm 0.28, 28 September 2003.\n" "\n" "Main parameters:\n" "\n" " -s \n" "\n" " Input cmm file should be preprocessed. Requires\n" " that the dispatch.cpp file (included in the cmm\n" " distribution) is linked into the final\n" " executable.\n" "\n" "\n" "Other parameters:\n" "\n" " -! Run using system().\n" " -autoblocks Insert `{' and `}' to match\n" " indentation.\n" " -block Inserts at start of all\n" " blocks\n" " -caller-dispatch enable caller dispatch\n" " -checkindent Checks indentation of lines\n" " containing '{' and '}'.\n" " -detailedparse Parse class/function bodies.\n" " -embeddedfns Support embedded functions, and\n" " convert to legal C++.\n" " -errorlevel xyz Sets how verbose error messages\n" " are after a parse failure\n" " x, y and z are each `0' or `1':\n" " x: showstartpos\n" " y: show all positions\n" " z: show failed terminals\n" " Default is 001\n" " -exceptions-exit Converts try..catch to exit(1).\n" " -exceptions-fudge Converts try..throw.. catch,\n" " to use Throw(), catch_t() and\n" " Catch2() functions\n" " -h|-help|--h|--help Show this help.\n" " -k Wait for keypress before exiting.\n" " -lexer-verbose Verbose lexer output\n" " -newdeclsyntax Support new declaration syntax,\n" " such as:\n" " foo: ( argv: []->char) int;\n" " -no-exceptions Generated code never throws\n" " exceptions. Calls exit(1) instead.\n" " -no-hash-line Ommit #line directives in\n" " generated source.\n" " -parse Parses , outputs parse-\n" " -tree if verbose.\n" " -parsefile Parses , outputs parse-\n" " -tree if verbose.\n" " -pre Inserts at start of output\n" " -profile
Generates profiling code.\n" " (Not for general useage)\n" " -profil Generates profiling stats using\n" " profil(1)\n" " -shownumnodes Prints out nuber of parser nodes\n" " created so far - e.g. you will\n" " probably want to put this flag\n" " after -s .\n" " -small-ints Add virtual function to every\n" " polymorphic class, which returns\n" " a unique int for that class\n" " -v|verbose Verbose.\n" " -no-c++ lexer_t ignores C++ keywords\n" "\n" " -serialise Generate serialisation code\n" " (experimental)\n" "\n" "Special names\n" " Declaring the following names in cmm code gives\n" " control of cmm parser's as it parses the code:\n" "\n" " cmm_pragma_autoblocks_on\n" " cmm_pragma_autoblocks_off\n" " cmm_pragma_detailedparse_on\n" " cmm_pragma_detailedparse_off\n" " cmm_pragma_newdeclsyntax_on\n" " cmm_pragma_newdeclsyntax_off\n" " cmm_pragma_embeddedfns_on\n" " cmm_pragma_embeddedfns_off\n" " cmm_pragma_lexer_verbose_on\n" " cmm_pragma_lexer_verbose_off\n" "\n" " E.g. int cmm_pragma_embeddedfns_on()\n" "\n" "\n" "Old usage:\n" "\n" " -c \n" "\n" " Reads in cmm source, and translates into c++\n" " source.\n" " Also generates a cmminfo file for use by `cmm -l'.\n" " This contain information about all multimethod\n" " implementations that were found in ,\n" " and also the filename .\n" " if_t is empty (i.e. \"\"), no\n" " cmminfo file is generated.\n" "\n" "\n" " -l {}\n" "\n" " Reads in cmminfo file(s) created previously by\n" " `cmm -c ...' command(s). Appends C++ source code\n" " to some of the c++ files generated by these\n" " command(s).\n" "\n" " Dispatch code customisation:\n" "\n" " In the following,
means a complete\n" " #include line. For example, to make the dispatch code\n" " use a custom replacement for std::map, called MyMap,\n" " defined in the header file \"MyMap.h\", do:\n" " cmm -map \"#include \\\"MyMap.h\\\"\" MyMap -l ...\n" "\n" " -array
Override use of \n" " and std::vector in code\n" " generated by cmm -l.\n" " Replacement should match\n" " template< class T, int N>,\n" " where N is fixed size.\n" " -map
Override use of and\n" " std::map in code generated\n" " by cmm -l.\n" "\n" "For more information, see: http://www.op59.net/cmm/\n" "\n" "\n" ; // 60 characters width: // 012345678901234567890123456789012345678901234567890123456789 } void IncrementParam( int argc, int& i, int increment) { i+=increment; if ( i>argc) throw std::runtime_error( "Not enough parameters. Run with `-h' to show help"); } bool GetBoolFromChar( char c) { if ( c=='1') return true; if ( c=='0') return false; throw exception_stream() << "Expecting `0' or `1', not `" << c << "'"; } } int main( int argc, char** argv0) { debug_TRACE_PRETTY; bool wait_for_keypress_before_exit = false; int retvalue = 1; std::string verboseprefix = std::string( argv0[0]) + ": "; bool checkindent = false; bool detailedparse = false; cmm::ThirdPassInfo::Extra thirdpassextra; bool lexerverbose = false; bool autoblocks = false; bool err_showfailed = true; bool err_showallpos = false; bool err_showstartpos= false; bool support_embedded_functions_in_expressions = false; bool support_new_declsyntax = false; parser::exceptions_translation exceptiontranslation = exceptionstranslation_PRESERVE; bool no_cplusplus = false; bool small_ints = false; bool caller_dispatch = false; std::string block_text; std::string pre_text; try { #if 0 { // test stlport'd iterator checking. std::vector< int> v; v.push_back( 1); v.push_back( 2); std::vector::iterator it=v.end(); int x = *it; } #endif std::auto_ptr< op59_net::scoped_profil> prof; std::string prof_outfile; bool verbose = false; bool no_hash_line = false; const char** argv = (const char**) argv0; if ( argc==1) { // invent default parameter list. static const char* argv1[] = { "", "-h", NULL}; argv = argv1; argc = sizeof( argv1)/sizeof( char*) - 1; } for ( int i=1; ifilename; std::string filename1 = filename0->output_compact_tostring(); // filename1 is in quotes, so we need to extract the text: std::string filename2 = filename1.substr( 1, filename1.length()-2); const char* filename = filename2.c_str(); if ( verbose) { std::cerr << verboseprefix << *dispatcher->items.back()->declarator->is_name()->name << " >> " << filename << "\n"; } std::ofstream out( filename, std::ios::app); if ( !out) { exception_stream e; e << "Couldn't open `" << filename << "' for appending"; throw e; } out << "\n"; cmm::OutputPreDispatchCode( out, *third.virtfns[i], third); outstream_t outstream( out); outstream.remove_virtual_from_functionparams = true; //debug << "3. lookupfn is " << *lookup << "\n"; lookup->output( outstream); dispatcher->output( outstream); //debug << "4. end of lookup fn\n"; } } else throw exception_stream() << "Unrecognised param `" << argv[i] << "'."; if ( i<=i0) throw std::logic_error( "internal_t error - parameter count not incremented in main()"); if ( i> argc) throw std::logic_error( "internal_t error - parameter count incremented beyond end of params"); } if ( prof.get()) { prof->output( argv[0], prof_outfile); } retvalue = 0; } catch( std::exception& e) { std::cerr << verboseprefix << e.what() << "\n"; } catch(...) { std::cerr << verboseprefix << "Unrecognised exception\n"; } if ( wait_for_keypress_before_exit) { std::cerr << verboseprefix << "Press to finish...\n"; std::cin.get(); } return retvalue; } #ifdef __GNUC__ std::stringstream* MakeStringStream() { return new std::stringstream; } #endif