Changes in src/main.cc [b4f8808:af84a35]
- File:
-
- 1 edited
-
src/main.cc (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/main.cc
rb4f8808 raf84a35 7 7 // main.cc -- 8 8 // 9 // Author : Peter Buhr and Rob Schluntz9 // Author : Richard C. Bilson 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Aug 23 06:50:08 201913 // Update Count : 60712 // Last Modified On : Wed Jun 6 15:51:47 2018 13 // Update Count : 498 14 14 // 15 15 … … 17 17 #include <execinfo.h> // for backtrace, backtrace_symbols 18 18 #include <getopt.h> // for no_argument, optind, geto... 19 #include <signal.h> // for signal, SIGABRT, SIGSEGV 19 20 #include <cassert> // for assertf 20 21 #include <cstdio> // for fopen, FILE, fclose, stdin 21 22 #include <cstdlib> // for exit, free, abort, EXIT_F... 22 #include <csignal> // for signal, SIGABRT, SIGSEGV23 23 #include <cstring> // for index 24 24 #include <fstream> // for ofstream 25 25 #include <iostream> // for operator<<, basic_ostream 26 #include <iomanip>27 26 #include <iterator> // for back_inserter 28 27 #include <list> // for list 29 28 #include <string> // for char_traits, operator<< 30 29 31 #include "CompilationState.h"32 30 #include "../config.h" // for CFA_LIBDIR 33 31 #include "CodeGen/FixMain.h" // for FixMain … … 35 33 #include "CodeGen/Generate.h" // for generate 36 34 #include "CodeTools/DeclStats.h" // for printDeclStats 37 #include "CodeTools/ResolvProtoDump.h" // for dumpAsResolvProto38 35 #include "CodeTools/TrackLoc.h" // for fillLocations 39 36 #include "Common/CompilerError.h" // for CompilerError 40 #include "Common/ Stats.h"37 #include "Common/Heap.h" 41 38 #include "Common/PassVisitor.h" 42 39 #include "Common/SemanticError.h" // for SemanticError … … 64 61 #include "Virtual/ExpandCasts.h" // for expandCasts 65 62 66 67 63 using namespace std; 68 64 69 static void NewPass( const char * const name ) { 70 Stats::Heap::newPass( name ); 71 using namespace Stats::Counters; 72 { 73 static auto group = build<CounterGroup>( "Pass Visitor" ); 74 auto pass = build<CounterGroup>( name, group ); 75 pass_visitor_stats.depth = 0; 76 pass_visitor_stats.avg = build<AverageCounter<double>>( "Average Depth", pass ); 77 pass_visitor_stats.max = build<MaxCounter<double>>( "Max Depth", pass ); 78 } 79 { 80 static auto group = build<CounterGroup>( "Syntax Node" ); 81 auto pass = build<CounterGroup>( name, group ); 82 BaseSyntaxNode::new_nodes = build<SimpleCounter>( "Allocs", pass ); 83 } 84 } 85 86 #define PASS( name, pass ) \ 65 #define PASS(name, pass) \ 87 66 if ( errorp ) { cerr << name << endl; } \ 88 NewPass(name); \ 89 Stats::Time::StartBlock(name); \ 90 pass; \ 91 Stats::Time::StopBlock(); 67 HeapStats::newPass(name); \ 68 pass; 92 69 93 70 LinkageSpec::Spec linkage = LinkageSpec::Cforall; … … 95 72 DeclarationNode * parseTree = nullptr; // program parse tree 96 73 97 static bool waiting_for_gdb = false; // flag to set cfa-cpp to wait for gdb on start 98 99 static std::string PreludeDirector = ""; 100 101 static void parse_cmdline( int argc, char *argv[] ); 74 extern int yydebug; // set for -g flag (Grammar) 75 bool 76 astp = false, 77 bresolvep = false, 78 bboxp = false, 79 bcodegenp = false, 80 ctorinitp = false, 81 declstatsp = false, 82 exprp = false, 83 expraltp = false, 84 genericsp = false, 85 libcfap = false, 86 nopreludep = false, 87 noprotop = false, 88 nomainp = false, 89 parsep = false, 90 resolvep = false, // used in AlternativeFinder 91 symtabp = false, 92 treep = false, 93 tuplep = false, 94 validp = false, 95 errorp = false, 96 codegenp = false, 97 prettycodegenp = false, 98 linemarks = false; 99 100 static void parse_cmdline( int argc, char *argv[], const char *& filename ); 102 101 static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false ); 103 102 static void dump( list< Declaration * > & translationUnit, ostream & out = cout ); … … 153 152 } // backtrace 154 153 155 staticvoid sigSegvBusHandler( int sig_num ) {154 void sigSegvBusHandler( int sig_num ) { 156 155 cerr << "*CFA runtime error* program cfa-cpp terminated with " 157 156 << (sig_num == SIGSEGV ? "segment fault" : "bus error") … … 159 158 backtrace( 2 ); // skip first 2 stack frames 160 159 //_exit( EXIT_FAILURE ); 161 abort(); // cause core dump for debugging160 abort(); 162 161 } // sigSegvBusHandler 163 162 164 staticvoid sigAbortHandler( __attribute__((unused)) int sig_num ) {163 void sigAbortHandler( __attribute__((unused)) int sig_num ) { 165 164 backtrace( 6 ); // skip first 6 stack frames 166 165 signal( SIGABRT, SIG_DFL); // reset default signal handler 167 raise( SIGABRT ); // reraise SIGABRT166 raise( SIGABRT ); // reraise SIGABRT 168 167 } // sigAbortHandler 168 169 169 170 170 int main( int argc, char * argv[] ) { 171 171 FILE * input; // use FILE rather than istream because yyin is FILE 172 ostream * output = & cout; 172 ostream *output = & cout; 173 const char *filename = nullptr; 173 174 list< Declaration * > translationUnit; 174 175 … … 182 183 // } // for 183 184 184 parse_cmdline( argc, argv );// process command-line arguments185 parse_cmdline( argc, argv, filename ); // process command-line arguments 185 186 CodeGen::FixMain::setReplaceMain( !nomainp ); 186 187 if ( waiting_for_gdb ) {188 std::cerr << "Waiting for gdb" << std::endl;189 std::cerr << "run :" << std::endl;190 std::cerr << " gdb attach " << getpid() << std::endl;191 raise(SIGSTOP);192 } // if193 187 194 188 try { … … 196 190 if ( optind < argc ) { // any commands after the flags ? => input file name 197 191 input = fopen( argv[ optind ], "r" ); 198 assertf( input, "cannot open %s because %s\n", argv[ optind ], strerror( errno ) ); 192 assertf( input, "cannot open %s\n", argv[ optind ] ); 193 // if running cfa-cpp directly, might forget to pass -F option (and really shouldn't have to) 194 if ( filename == nullptr ) filename = argv[ optind ]; 195 // prelude filename comes in differently 196 if ( libcfap ) filename = "prelude.cf"; 199 197 optind += 1; 200 198 } else { // no input file name 201 199 input = stdin; 202 } // if 203 204 Stats::Time::StartGlobal(); 205 NewPass("Parse"); 206 Stats::Time::StartBlock("Parse"); 200 // if running cfa-cpp directly, might forget to pass -F option. Since this takes from stdin, pass 201 // a fake name along 202 if ( filename == nullptr ) filename = "stdin"; 203 } // if 207 204 208 205 // read in the builtins, extras, and the prelude … … 210 207 // -l is for initial build ONLY and builtins.cf is not in the lib directory so access it here. 211 208 212 assertf( !PreludeDirector.empty(), "Can't find prelude without option --prelude-dir must be used." );213 214 209 // Read to gcc builtins, if not generating the cfa library 215 FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" );210 FILE * gcc_builtins = fopen( libcfap | treep ? "../prelude/gcc-builtins.cf" : CFA_LIBDIR "/gcc-builtins.cf", "r" ); 216 211 assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" ); 217 212 parse( gcc_builtins, LinkageSpec::Compiler ); 218 213 219 214 // read the extra prelude in, if not generating the cfa library 220 FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" );215 FILE * extras = fopen( libcfap | treep ? "../prelude/extras.cf" : CFA_LIBDIR "/extras.cf", "r" ); 221 216 assertf( extras, "cannot open extras.cf\n" ); 222 217 parse( extras, LinkageSpec::BuiltinC ); … … 224 219 if ( ! libcfap ) { 225 220 // read the prelude in, if not generating the cfa library 226 FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );227 assertf( prelude, "cannot open prelude.cf a\n" );221 FILE * prelude = fopen( treep ? "../prelude/prelude.cf" : CFA_LIBDIR "/prelude.cf", "r" ); 222 assertf( prelude, "cannot open prelude.cf\n" ); 228 223 parse( prelude, LinkageSpec::Intrinsic ); 229 224 230 225 // Read to cfa builtins, if not generating the cfa library 231 FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" );226 FILE * builtins = fopen( libcfap | treep ? "../prelude/builtins.cf" : CFA_LIBDIR "/builtins.cf", "r" ); 232 227 assertf( builtins, "cannot open builtins.cf\n" ); 233 228 parse( builtins, LinkageSpec::BuiltinCFA ); … … 240 235 parseTree->printList( cout ); 241 236 delete parseTree; 242 return EXIT_SUCCESS;237 return 0; 243 238 } // if 244 239 … … 249 244 if ( astp ) { 250 245 dump( translationUnit ); 251 return EXIT_SUCCESS; 252 } // if 253 254 // Temporary: fill locations after parsing so that every node has a location, for early error messages. 255 // Eventually we should pass the locations from the parser to every node, but this quick and dirty solution 256 // works okay for now. 257 CodeTools::fillLocations( translationUnit ); 258 Stats::Time::StopBlock(); 246 return 0; 247 } // if 259 248 260 249 // add the assignment statement after the initialization of a type parameter 261 PASS( " Validate", SymTab::validate( translationUnit, symtabp ) );250 PASS( "validate", SymTab::validate( translationUnit, symtabp ) ); 262 251 if ( symtabp ) { 263 252 deleteAll( translationUnit ); 264 return EXIT_SUCCESS;253 return 0; 265 254 } // if 266 255 … … 268 257 PassVisitor<ResolvExpr::AlternativePrinter> printer( cout ); 269 258 acceptAll( translationUnit, printer ); 270 return EXIT_SUCCESS;259 return 0; 271 260 } // if 272 261 273 262 if ( validp ) { 274 263 dump( translationUnit ); 275 return EXIT_SUCCESS;276 } // if 277 278 PASS( " FixLabels", ControlStruct::fixLabels( translationUnit ) );279 PASS( " FixNames", CodeGen::fixNames( translationUnit ) );280 PASS( " GenInit", InitTweak::genInit( translationUnit ) );281 PASS( " Expand MemberTuples" , Tuples::expandMemberTuples( translationUnit ) );264 return 0; 265 } // if 266 267 PASS( "fixLabels", ControlStruct::fixLabels( translationUnit ) ); 268 PASS( "fixNames", CodeGen::fixNames( translationUnit ) ); 269 PASS( "genInit", InitTweak::genInit( translationUnit ) ); 270 PASS( "expandMemberTuples" , Tuples::expandMemberTuples( translationUnit ) ); 282 271 if ( libcfap ) { 283 272 // generate the bodies of cfa library functions … … 288 277 CodeTools::printDeclStats( translationUnit ); 289 278 deleteAll( translationUnit ); 290 return EXIT_SUCCESS;291 } // if279 return 0; 280 } 292 281 293 282 if ( bresolvep ) { 294 283 dump( translationUnit ); 295 return EXIT_SUCCESS;284 return 0; 296 285 } // if 297 286 298 287 CodeTools::fillLocations( translationUnit ); 299 288 300 if ( resolvprotop ) { 301 CodeTools::dumpAsResolvProto( translationUnit ); 302 return EXIT_SUCCESS; 303 } // if 304 305 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) ); 289 PASS( "resolve", ResolvExpr::resolve( translationUnit ) ); 306 290 if ( exprp ) { 307 291 dump( translationUnit ); 308 return EXIT_SUCCESS;292 return 0; 309 293 } // if 310 294 311 295 // fix ObjectDecl - replaces ConstructorInit nodes 312 PASS( " Fix Init", InitTweak::fix( translationUnit, buildingLibrary()) );296 PASS( "fixInit", InitTweak::fix( translationUnit, filename, libcfap || treep ) ); 313 297 if ( ctorinitp ) { 314 298 dump ( translationUnit ); 315 return EXIT_SUCCESS;316 } // if 317 318 PASS( " Expand UniqueExpr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused319 320 PASS( " TranslateEHM" , ControlStruct::translateEHM( translationUnit ) );321 322 PASS( " GenWaitfor" , Concurrency::generateWaitFor( translationUnit ) );323 324 PASS( " ConvertSpecializations", GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded325 326 PASS( " ExpandTuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?299 return 0; 300 } // if 301 302 PASS( "expandUniqueExpr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused 303 304 PASS( "translateEHM" , ControlStruct::translateEHM( translationUnit ) ); 305 306 PASS( "generateWaitfor" , Concurrency::generateWaitFor( translationUnit ) ); 307 308 PASS( "convertSpecializations", GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded 309 310 PASS( "expandTuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this? 327 311 328 312 if ( tuplep ) { 329 313 dump( translationUnit ); 330 return EXIT_SUCCESS;331 } // if332 333 PASS( " Virtual ExpandCasts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM334 335 PASS( " InstantiateGenerics", GenPoly::instantiateGeneric( translationUnit ) );314 return 0; 315 } 316 317 PASS( "virtual expandCasts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM 318 319 PASS( "instantiateGenerics", GenPoly::instantiateGeneric( translationUnit ) ); 336 320 if ( genericsp ) { 337 321 dump( translationUnit ); 338 return EXIT_SUCCESS;339 } // if340 341 PASS( "Convert L-Value", GenPoly::convertLvalue( translationUnit ) ); 322 return 0; 323 } 324 PASS( "convertLvalue", GenPoly::convertLvalue( translationUnit ) ); 325 342 326 343 327 if ( bboxp ) { 344 328 dump( translationUnit ); 345 return EXIT_SUCCESS;346 } // if 347 PASS( " Box", GenPoly::box( translationUnit ) );329 return 0; 330 } // if 331 PASS( "box", GenPoly::box( translationUnit ) ); 348 332 349 333 if ( bcodegenp ) { 350 334 dump( translationUnit ); 351 return EXIT_SUCCESS;352 } // if335 return 0; 336 } 353 337 354 338 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 357 341 358 342 CodeTools::fillLocations( translationUnit ); 359 PASS( " Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) );360 361 CodeGen::FixMain::fix( *output, (PreludeDirector + "/bootloader.c").c_str());343 PASS( "codegen", CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp, true, linemarks ) ); 344 345 CodeGen::FixMain::fix( *output, treep ? "../prelude/bootloader.c" : CFA_LIBDIR "/bootloader.c" ); 362 346 if ( output != &cout ) { 363 347 delete output; … … 373 357 delete output; 374 358 } // if 375 return EXIT_FAILURE;359 return 1; 376 360 } catch ( UnimplementedError &e ) { 377 361 cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl; … … 379 363 delete output; 380 364 } // if 381 return EXIT_FAILURE;365 return 1; 382 366 } catch ( CompilerError &e ) { 383 367 cerr << "Compiler Error: " << e.get_what() << endl; … … 386 370 delete output; 387 371 } // if 388 return EXIT_FAILURE;389 } catch ( ...) {372 return 1; 373 } catch(...) { 390 374 std::exception_ptr eptr = std::current_exception(); 391 375 try { 392 376 if (eptr) { 393 377 std::rethrow_exception(eptr); 394 } else { 395 std::cerr << "Exception Uncaught and Unknown" << std::endl; 396 } // if 378 } 379 else { 380 std::cerr << "Exception Uncaught and Unkown" << std::endl; 381 } 397 382 } catch(const std::exception& e) { 398 std::cerr << "Un caught Exception \"" << e.what() << "\"\n";399 } // try400 return EXIT_FAILURE;401 } // try383 std::cerr << "Unaught Exception \"" << e.what() << "\"\n"; 384 } 385 return 1; 386 }// try 402 387 403 388 deleteAll( translationUnit ); 404 Stats::print();405 return EXIT_SUCCESS;389 if(!libcfap && !treep) HeapStats::printStats(); 390 return 0; 406 391 } // main 407 392 408 409 static const char optstring[] = ":hlLmNnpP:S:twW:D:"; 410 411 enum { PreludeDir = 128 }; 412 static struct option long_opts[] = { 413 { "help", no_argument, nullptr, 'h' }, 414 { "libcfa", no_argument, nullptr, 'l' }, 415 { "linemarks", no_argument, nullptr, 'L' }, 416 { "no-main", no_argument, 0, 'm' }, 417 { "no-linemarks", no_argument, nullptr, 'N' }, 418 { "no-prelude", no_argument, nullptr, 'n' }, 419 { "prototypes", no_argument, nullptr, 'p' }, 420 { "print", required_argument, nullptr, 'P' }, 421 { "prelude-dir", required_argument, nullptr, PreludeDir }, 422 { "statistics", required_argument, nullptr, 'S' }, 423 { "tree", no_argument, nullptr, 't' }, 424 { "gdb", no_argument, nullptr, 'g' }, 425 { "", no_argument, nullptr, 0 }, // -w 426 { "", no_argument, nullptr, 0 }, // -W 427 { "", no_argument, nullptr, 0 }, // -D 428 { nullptr, 0, nullptr, 0 } 429 }; // long_opts 430 431 static const char * description[] = { 432 "print help message", // -h 433 "generate libcfa.c", // -l 434 "generate line marks", // -L 435 "do not replace main", // -m 436 "do not generate line marks", // -N 437 "do not read prelude", // -n 438 "generate prototypes for prelude functions", // -p 439 "print", // -P 440 "<directory> prelude directory for debug/nodebug", // no flag 441 "<option-list> enable profiling information:\n counters,heap,time,all,none", // -S 442 "building cfa standard lib", // -t 443 "wait for gdb to attach", // -g 444 "", // -w 445 "", // -W 446 "", // -D 447 }; // description 448 449 static_assert( sizeof( long_opts ) / sizeof( long_opts[0] ) - 1 == sizeof( description ) / sizeof( description[0] ), "Long opts and description must match" ); 450 451 static struct Printopts { 452 const char * name; 453 int & flag; 454 int val; 455 const char * descript; 456 } printopts[] = { 457 { "ascodegen", codegenp, true, "print AST as codegen rather than AST" }, 458 { "asterr", errorp, true, "print AST on error" }, 459 { "declstats", declstatsp, true, "code property statistics" }, 460 { "parse", yydebug, true, "yacc (parsing) debug information" }, 461 { "pretty", prettycodegenp, true, "prettyprint for ascodegen flag" }, 462 { "rproto", resolvprotop, true, "resolver-proto instance" }, 463 { "rsteps", resolvep, true, "print resolver steps" }, 464 { "tree", parsep, true, "print parse tree" }, 465 // code dumps 466 { "ast", astp, true, "print AST after parsing" }, 467 { "symevt", symtabp, true, "print AST after symbol table events" }, 468 { "altexpr", expraltp, true, "print alternatives for expressions" }, 469 { "astdecl", validp, true, "print AST after declaration validation pass" }, 470 { "resolver", bresolvep, true, "print AST before resolver step" }, 471 { "astexpr", exprp, true, "print AST after expression analysis" }, 472 { "ctordtor", ctorinitp, true, "print AST after ctor/dtor are replaced" }, 473 { "tuple", tuplep, true, "print AST after tuple expansion" }, 474 { "astgen", genericsp, true, "print AST after instantiate generics" }, 475 { "box", bboxp, true, "print AST before box step" }, 476 { "codegen", bcodegenp, true, "print AST before code generation" }, 477 }; 478 enum { printoptsSize = sizeof( printopts ) / sizeof( printopts[0] ) }; 479 480 static void usage( char *argv[] ) { 481 cout << "Usage: " << argv[0] << " [options] [input-file (default stdin)] [output-file (default stdout)], where options are:" << endl; 482 int i = 0, j = 1; // j skips starting colon 483 for ( ; long_opts[i].name != 0 && optstring[j] != '\0'; i += 1, j += 1 ) { 484 if ( long_opts[i].name[0] != '\0' ) { // hidden option, internal usage only 485 if ( strcmp( long_opts[i].name, "prelude-dir" ) != 0 ) { // flag 486 cout << " -" << optstring[j] << ","; 487 } else { // no flag 488 j -= 1; // compensate 489 cout << " "; 490 } // if 491 cout << " --" << left << setw(12) << long_opts[i].name << " "; 492 if ( strcmp( long_opts[i].name, "print" ) == 0 ) { 493 cout << "one of: " << endl; 494 for ( int i = 0; i < printoptsSize; i += 1 ) { 495 cout << setw(10) << " " << left << setw(10) << printopts[i].name << " " << printopts[i].descript << endl; 496 } // for 497 } else { 498 cout << description[i] << endl; 499 } // if 500 } // if 501 if ( optstring[j + 1] == ':' ) j += 1; 502 } // for 503 if ( long_opts[i].name != 0 || optstring[j] != '\0' ) assertf( false, "internal error, mismatch of option flags and names\n" ); 504 exit( EXIT_FAILURE ); 505 } // usage 506 507 static void parse_cmdline( int argc, char * argv[] ) { 393 void parse_cmdline( int argc, char * argv[], const char *& filename ) { 394 enum { Ast, Bbox, Bresolver, CtorInitFix, DeclStats, Expr, ExprAlt, Grammar, LibCFA, Linemarks, Nolinemarks, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, TupleExpansion, Validate, }; 395 396 static struct option long_opts[] = { 397 { "ast", no_argument, 0, Ast }, 398 { "before-box", no_argument, 0, Bbox }, 399 { "before-resolver", no_argument, 0, Bresolver }, 400 { "ctorinitfix", no_argument, 0, CtorInitFix }, 401 { "decl-stats", no_argument, 0, DeclStats }, 402 { "expr", no_argument, 0, Expr }, 403 { "expralt", no_argument, 0, ExprAlt }, 404 { "grammar", no_argument, 0, Grammar }, 405 { "libcfa", no_argument, 0, LibCFA }, 406 { "line-marks", no_argument, 0, Linemarks }, 407 { "no-line-marks", no_argument, 0, Nolinemarks }, 408 { "no-preamble", no_argument, 0, Nopreamble }, 409 { "parse", no_argument, 0, Parse }, 410 { "no-prototypes", no_argument, 0, Prototypes }, 411 { "resolver", no_argument, 0, Resolver }, 412 { "symbol", no_argument, 0, Symbol }, 413 { "tree", no_argument, 0, Tree }, 414 { "tuple-expansion", no_argument, 0, TupleExpansion }, 415 { "validate", no_argument, 0, Validate }, 416 { 0, 0, 0, 0 } 417 }; // long_opts 418 int long_index; 419 508 420 opterr = 0; // (global) prevent getopt from printing error messages 509 421 510 422 bool Wsuppress = false, Werror = false; 511 423 int c; 512 while ( (c = getopt_long( argc, argv, optstring, long_opts, nullptr)) != -1 ) {424 while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) { 513 425 switch ( c ) { 514 case 'h': // help message 515 usage( argv ); // no return 516 break; 426 case Ast: 427 case 'a': // dump AST 428 astp = true; 429 break; 430 case Bresolver: 431 case 'b': // print before resolver steps 432 bresolvep = true; 433 break; 434 case 'B': // print before box steps 435 bboxp = true; 436 break; 437 case CtorInitFix: 438 case 'c': // print after constructors and destructors are replaced 439 ctorinitp = true; 440 break; 441 case 'C': // print before code generation 442 bcodegenp = true; 443 break; 444 case DeclStats: 445 case 'd': 446 declstatsp = true; 447 break; 448 case Expr: 449 case 'e': // dump AST after expression analysis 450 exprp = true; 451 break; 452 case ExprAlt: 453 case 'f': // print alternatives for expressions 454 expraltp = true; 455 break; 456 case Grammar: 457 case 'g': // bison debugging info (grammar rules) 458 yydebug = true; 459 break; 460 case 'G': // dump AST after instantiate generics 461 genericsp = true; 462 break; 463 case LibCFA: 517 464 case 'l': // generate libcfa.c 518 465 libcfap = true; 519 466 break; 520 case 'L': // generate line marks 467 case Linemarks: 468 case 'L': // print lines marks 521 469 linemarks = true; 522 470 break; 523 case 'm': // do not replace main 524 nomainp = true; 525 break; 526 case 'N': // do not generate line marks 471 case Nopreamble: 472 case 'n': // do not read preamble 473 nopreludep = true; 474 break; 475 case Nolinemarks: 476 case 'N': // suppress line marks 527 477 linemarks = false; 528 478 break; 529 case 'n': // do not read prelude 530 nopreludep = true; 531 break; 532 case 'p': // generate prototypes for prelude functions 533 genproto = true; 534 break; 535 case 'P': // print options 536 for ( int i = 0;; i += 1 ) { 537 if ( i == printoptsSize ) { 538 cout << "Unknown --print option " << optarg << endl; 539 goto Default; 540 } // if 541 if ( strcmp( optarg, printopts[i].name ) == 0 ) { 542 printopts[i].flag = printopts[i].val; 543 break; 544 } // if 545 } // for 546 break; 547 case PreludeDir: // prelude directory for debug/nodebug, hidden 548 PreludeDirector = optarg; 549 break; 550 case 'S': // enable profiling information, argument comma separated list of names 551 Stats::parse_params( optarg ); 552 break; 553 case 't': // building cfa stdlib 479 case Prototypes: 480 case 'p': // generate prototypes for preamble functions 481 noprotop = true; 482 break; 483 case 'm': // don't replace the main 484 nomainp = true; 485 break; 486 case Parse: 487 case 'q': // dump parse tree 488 parsep = true; 489 break; 490 case Resolver: 491 case 'r': // print resolver steps 492 resolvep = true; 493 break; 494 case Symbol: 495 case 's': // print symbol table events 496 symtabp = true; 497 break; 498 case Tree: 499 case 't': // build in tree 554 500 treep = true; 555 501 break; 556 case 'g': // wait for gdb 557 waiting_for_gdb = true; 558 break; 559 case 'w': // suppress all warnings, hidden 502 case TupleExpansion: 503 case 'T': // print after tuple expansion 504 tuplep = true; 505 break; 506 case 'v': // dump AST after decl validation pass 507 validp = true; 508 break; 509 case 'w': 560 510 Wsuppress = true; 561 511 break; 562 case 'W': // coordinate gcc -W with CFA, hidden512 case 'W': 563 513 if ( strcmp( optarg, "all" ) == 0 ) { 564 514 SemanticWarning_EnableAll(); … … 577 527 } // if 578 528 break; 579 case 'D': // ignore -Dxxx, forwarded by cpp, hidden 580 break; 581 case '?': // unknown option 529 case 'y': // dump AST on error 530 errorp = true; 531 break; 532 case 'z': // dump as codegen rather than AST 533 codegenp = true; 534 break; 535 case 'Z': // prettyprint during codegen (i.e. print unmangled names, etc.) 536 prettycodegenp = true; 537 break; 538 case 'D': // ignore -Dxxx 539 break; 540 case 'F': // source file-name without suffix 541 filename = optarg; 542 break; 543 case '?': 582 544 if ( optopt ) { // short option ? 583 cout << "Unknown option -" << (char)optopt << endl;545 assertf( false, "Unknown option: -%c\n", (char)optopt ); 584 546 } else { 585 cout << "Unknown option " << argv[optind - 1] << endl;547 assertf( false, "Unknown option: %s\n", argv[optind - 1] ); 586 548 } // if 587 goto Default; 588 case ':': // missing option 589 if ( optopt ) { // short option ? 590 cout << "Missing option for -" << (char)optopt << endl; 591 } else { 592 cout << "Missing option for " << argv[optind - 1] << endl; 593 } // if 594 goto Default; 595 Default: 549 #if defined(__GNUC__) && __GNUC__ >= 7 550 __attribute__((fallthrough)); 551 #endif 596 552 default: 597 usage( argv ); // no return553 abort(); 598 554 } // switch 599 555 } // while … … 633 589 list< Declaration * > decls; 634 590 635 if ( genproto) {591 if ( noprotop ) { 636 592 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), notPrelude ); 637 593 } else { … … 641 597 // depending on commandline options, either generate code or dump the AST 642 598 if ( codegenp ) { 643 CodeGen::generate( decls, out, ! genproto, prettycodegenp );599 CodeGen::generate( decls, out, ! noprotop, prettycodegenp ); 644 600 } else { 645 601 printAll( decls, out ); 646 } // if602 } 647 603 deleteAll( translationUnit ); 648 604 } // dump
Note:
See TracChangeset
for help on using the changeset viewer.