Changes in src/main.cc [af84a35:b4f8808]
- File:
-
- 1 edited
-
src/main.cc (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/main.cc
raf84a35 rb4f8808 7 7 // main.cc -- 8 8 // 9 // Author : Richard C. Bilson9 // Author : Peter Buhr and Rob Schluntz 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jun 6 15:51:47 201813 // Update Count : 49812 // Last Modified On : Fri Aug 23 06:50:08 2019 13 // Update Count : 607 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, SIGSEGV20 19 #include <cassert> // for assertf 21 20 #include <cstdio> // for fopen, FILE, fclose, stdin 22 21 #include <cstdlib> // for exit, free, abort, EXIT_F... 22 #include <csignal> // for signal, SIGABRT, SIGSEGV 23 23 #include <cstring> // for index 24 24 #include <fstream> // for ofstream 25 25 #include <iostream> // for operator<<, basic_ostream 26 #include <iomanip> 26 27 #include <iterator> // for back_inserter 27 28 #include <list> // for list 28 29 #include <string> // for char_traits, operator<< 29 30 31 #include "CompilationState.h" 30 32 #include "../config.h" // for CFA_LIBDIR 31 33 #include "CodeGen/FixMain.h" // for FixMain … … 33 35 #include "CodeGen/Generate.h" // for generate 34 36 #include "CodeTools/DeclStats.h" // for printDeclStats 37 #include "CodeTools/ResolvProtoDump.h" // for dumpAsResolvProto 35 38 #include "CodeTools/TrackLoc.h" // for fillLocations 36 39 #include "Common/CompilerError.h" // for CompilerError 37 #include "Common/ Heap.h"40 #include "Common/Stats.h" 38 41 #include "Common/PassVisitor.h" 39 42 #include "Common/SemanticError.h" // for SemanticError … … 61 64 #include "Virtual/ExpandCasts.h" // for expandCasts 62 65 66 63 67 using namespace std; 64 68 65 #define PASS(name, pass) \ 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 ) \ 66 87 if ( errorp ) { cerr << name << endl; } \ 67 HeapStats::newPass(name); \ 68 pass; 88 NewPass(name); \ 89 Stats::Time::StartBlock(name); \ 90 pass; \ 91 Stats::Time::StopBlock(); 69 92 70 93 LinkageSpec::Spec linkage = LinkageSpec::Cforall; … … 72 95 DeclarationNode * parseTree = nullptr; // program parse tree 73 96 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 ); 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[] ); 101 102 static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false ); 102 103 static void dump( list< Declaration * > & translationUnit, ostream & out = cout ); … … 152 153 } // backtrace 153 154 154 void sigSegvBusHandler( int sig_num ) {155 static void sigSegvBusHandler( int sig_num ) { 155 156 cerr << "*CFA runtime error* program cfa-cpp terminated with " 156 157 << (sig_num == SIGSEGV ? "segment fault" : "bus error") … … 158 159 backtrace( 2 ); // skip first 2 stack frames 159 160 //_exit( EXIT_FAILURE ); 160 abort(); 161 abort(); // cause core dump for debugging 161 162 } // sigSegvBusHandler 162 163 163 void sigAbortHandler( __attribute__((unused)) int sig_num ) {164 static void sigAbortHandler( __attribute__((unused)) int sig_num ) { 164 165 backtrace( 6 ); // skip first 6 stack frames 165 166 signal( SIGABRT, SIG_DFL); // reset default signal handler 166 raise( SIGABRT ); // reraise SIGABRT167 raise( SIGABRT ); // reraise SIGABRT 167 168 } // 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; 173 const char *filename = nullptr; 172 ostream * output = & cout; 174 173 list< Declaration * > translationUnit; 175 174 … … 183 182 // } // for 184 183 185 parse_cmdline( argc, argv , filename );// process command-line arguments184 parse_cmdline( argc, argv ); // process command-line arguments 186 185 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 } // if 187 193 188 194 try { … … 190 196 if ( optind < argc ) { // any commands after the flags ? => input file name 191 197 input = fopen( argv[ optind ], "r" ); 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"; 198 assertf( input, "cannot open %s because %s\n", argv[ optind ], strerror( errno ) ); 197 199 optind += 1; 198 200 } else { // no input file name 199 201 input = stdin; 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 202 } // if 203 204 Stats::Time::StartGlobal(); 205 NewPass("Parse"); 206 Stats::Time::StartBlock("Parse"); 204 207 205 208 // read in the builtins, extras, and the prelude … … 207 210 // -l is for initial build ONLY and builtins.cf is not in the lib directory so access it here. 208 211 212 assertf( !PreludeDirector.empty(), "Can't find prelude without option --prelude-dir must be used." ); 213 209 214 // Read to gcc builtins, if not generating the cfa library 210 FILE * gcc_builtins = fopen( libcfap | treep ? "../prelude/gcc-builtins.cf" : CFA_LIBDIR "/gcc-builtins.cf", "r" );215 FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" ); 211 216 assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" ); 212 217 parse( gcc_builtins, LinkageSpec::Compiler ); 213 218 214 219 // read the extra prelude in, if not generating the cfa library 215 FILE * extras = fopen( libcfap | treep ? "../prelude/extras.cf" : CFA_LIBDIR "/extras.cf", "r" );220 FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" ); 216 221 assertf( extras, "cannot open extras.cf\n" ); 217 222 parse( extras, LinkageSpec::BuiltinC ); … … 219 224 if ( ! libcfap ) { 220 225 // read the prelude in, if not generating the cfa library 221 FILE * prelude = fopen( treep ? "../prelude/prelude.cf" : CFA_LIBDIR "/prelude.cf", "r" );222 assertf( prelude, "cannot open prelude.cf \n" );226 FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" ); 227 assertf( prelude, "cannot open prelude.cfa\n" ); 223 228 parse( prelude, LinkageSpec::Intrinsic ); 224 229 225 230 // Read to cfa builtins, if not generating the cfa library 226 FILE * builtins = fopen( libcfap | treep ? "../prelude/builtins.cf" : CFA_LIBDIR "/builtins.cf", "r" );231 FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" ); 227 232 assertf( builtins, "cannot open builtins.cf\n" ); 228 233 parse( builtins, LinkageSpec::BuiltinCFA ); … … 235 240 parseTree->printList( cout ); 236 241 delete parseTree; 237 return 0;242 return EXIT_SUCCESS; 238 243 } // if 239 244 … … 244 249 if ( astp ) { 245 250 dump( translationUnit ); 246 return 0; 247 } // if 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(); 248 259 249 260 // add the assignment statement after the initialization of a type parameter 250 PASS( " validate", SymTab::validate( translationUnit, symtabp ) );261 PASS( "Validate", SymTab::validate( translationUnit, symtabp ) ); 251 262 if ( symtabp ) { 252 263 deleteAll( translationUnit ); 253 return 0;264 return EXIT_SUCCESS; 254 265 } // if 255 266 … … 257 268 PassVisitor<ResolvExpr::AlternativePrinter> printer( cout ); 258 269 acceptAll( translationUnit, printer ); 259 return 0;270 return EXIT_SUCCESS; 260 271 } // if 261 272 262 273 if ( validp ) { 263 274 dump( 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 ) );275 return EXIT_SUCCESS; 276 } // if 277 278 PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) ); 279 PASS( "Fix Names", CodeGen::fixNames( translationUnit ) ); 280 PASS( "Gen Init", InitTweak::genInit( translationUnit ) ); 281 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( translationUnit ) ); 271 282 if ( libcfap ) { 272 283 // generate the bodies of cfa library functions … … 277 288 CodeTools::printDeclStats( translationUnit ); 278 289 deleteAll( translationUnit ); 279 return 0;280 } 290 return EXIT_SUCCESS; 291 } // if 281 292 282 293 if ( bresolvep ) { 283 294 dump( translationUnit ); 284 return 0;295 return EXIT_SUCCESS; 285 296 } // if 286 297 287 298 CodeTools::fillLocations( translationUnit ); 288 299 289 PASS( "resolve", ResolvExpr::resolve( translationUnit ) ); 300 if ( resolvprotop ) { 301 CodeTools::dumpAsResolvProto( translationUnit ); 302 return EXIT_SUCCESS; 303 } // if 304 305 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) ); 290 306 if ( exprp ) { 291 307 dump( translationUnit ); 292 return 0;308 return EXIT_SUCCESS; 293 309 } // if 294 310 295 311 // fix ObjectDecl - replaces ConstructorInit nodes 296 PASS( " fixInit", InitTweak::fix( translationUnit, filename, libcfap || treep) );312 PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) ); 297 313 if ( ctorinitp ) { 298 314 dump ( translationUnit ); 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 reused303 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 expanded309 310 PASS( " expandTuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?315 return EXIT_SUCCESS; 316 } // if 317 318 PASS( "Expand Unique Expr", 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 319 320 PASS( "Translate EHM" , ControlStruct::translateEHM( translationUnit ) ); 321 322 PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) ); 323 324 PASS( "Convert Specializations", GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded 325 326 PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this? 311 327 312 328 if ( tuplep ) { 313 329 dump( translationUnit ); 314 return 0;315 } 316 317 PASS( " virtual expandCasts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM318 319 PASS( " instantiateGenerics", GenPoly::instantiateGeneric( translationUnit ) );330 return EXIT_SUCCESS; 331 } // if 332 333 PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM 334 335 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( translationUnit ) ); 320 336 if ( genericsp ) { 321 337 dump( translationUnit ); 322 return 0;323 } 324 PASS( "convertLvalue", GenPoly::convertLvalue( translationUnit ) ); 325 338 return EXIT_SUCCESS; 339 } // if 340 341 PASS( "Convert L-Value", GenPoly::convertLvalue( translationUnit ) ); 326 342 327 343 if ( bboxp ) { 328 344 dump( translationUnit ); 329 return 0;330 } // if 331 PASS( " box", GenPoly::box( translationUnit ) );345 return EXIT_SUCCESS; 346 } // if 347 PASS( "Box", GenPoly::box( translationUnit ) ); 332 348 333 349 if ( bcodegenp ) { 334 350 dump( translationUnit ); 335 return 0;336 } 351 return EXIT_SUCCESS; 352 } // if 337 353 338 354 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 341 357 342 358 CodeTools::fillLocations( translationUnit ); 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");359 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) ); 360 361 CodeGen::FixMain::fix( *output, (PreludeDirector + "/bootloader.c").c_str() ); 346 362 if ( output != &cout ) { 347 363 delete output; … … 357 373 delete output; 358 374 } // if 359 return 1;375 return EXIT_FAILURE; 360 376 } catch ( UnimplementedError &e ) { 361 377 cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl; … … 363 379 delete output; 364 380 } // if 365 return 1;381 return EXIT_FAILURE; 366 382 } catch ( CompilerError &e ) { 367 383 cerr << "Compiler Error: " << e.get_what() << endl; … … 370 386 delete output; 371 387 } // if 372 return 1;373 } catch (...) {388 return EXIT_FAILURE; 389 } catch ( ... ) { 374 390 std::exception_ptr eptr = std::current_exception(); 375 391 try { 376 392 if (eptr) { 377 393 std::rethrow_exception(eptr); 378 } 379 else { 380 std::cerr << "Exception Uncaught and Unkown" << std::endl; 381 } 394 } else { 395 std::cerr << "Exception Uncaught and Unknown" << std::endl; 396 } // if 382 397 } catch(const std::exception& e) { 383 std::cerr << "Un aught Exception \"" << e.what() << "\"\n";384 } 385 return 1;386 } // try398 std::cerr << "Uncaught Exception \"" << e.what() << "\"\n"; 399 } // try 400 return EXIT_FAILURE; 401 } // try 387 402 388 403 deleteAll( translationUnit ); 389 if(!libcfap && !treep) HeapStats::printStats();390 return 0;404 Stats::print(); 405 return EXIT_SUCCESS; 391 406 } // main 392 407 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 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[] ) { 420 508 opterr = 0; // (global) prevent getopt from printing error messages 421 509 422 510 bool Wsuppress = false, Werror = false; 423 511 int c; 424 while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrstTvwW:yzZD:F:", long_opts, &long_index)) != -1 ) {512 while ( (c = getopt_long( argc, argv, optstring, long_opts, nullptr )) != -1 ) { 425 513 switch ( c ) { 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: 514 case 'h': // help message 515 usage( argv ); // no return 516 break; 464 517 case 'l': // generate libcfa.c 465 518 libcfap = true; 466 519 break; 467 case Linemarks: 468 case 'L': // print lines marks 520 case 'L': // generate line marks 469 521 linemarks = true; 470 522 break; 471 case Nopreamble: 472 case 'n': // do not read preamble 523 case 'm': // do not replace main 524 nomainp = true; 525 break; 526 case 'N': // do not generate line marks 527 linemarks = false; 528 break; 529 case 'n': // do not read prelude 473 530 nopreludep = true; 474 531 break; 475 case Nolinemarks: 476 case 'N': // suppress line marks 477 linemarks = false; 478 break; 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 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 500 554 treep = true; 501 555 break; 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': 556 case 'g': // wait for gdb 557 waiting_for_gdb = true; 558 break; 559 case 'w': // suppress all warnings, hidden 510 560 Wsuppress = true; 511 561 break; 512 case 'W': 562 case 'W': // coordinate gcc -W with CFA, hidden 513 563 if ( strcmp( optarg, "all" ) == 0 ) { 514 564 SemanticWarning_EnableAll(); … … 527 577 } // if 528 578 break; 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 '?': 579 case 'D': // ignore -Dxxx, forwarded by cpp, hidden 580 break; 581 case '?': // unknown option 544 582 if ( optopt ) { // short option ? 545 assertf( false, "Unknown option: -%c\n", (char)optopt );583 cout << "Unknown option -" << (char)optopt << endl; 546 584 } else { 547 assertf( false, "Unknown option: %s\n", argv[optind - 1] ); 548 } // if 549 #if defined(__GNUC__) && __GNUC__ >= 7 550 __attribute__((fallthrough)); 551 #endif 585 cout << "Unknown option " << argv[optind - 1] << endl; 586 } // 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: 552 596 default: 553 abort();597 usage( argv ); // no return 554 598 } // switch 555 599 } // while … … 589 633 list< Declaration * > decls; 590 634 591 if ( noprotop) {635 if ( genproto ) { 592 636 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), notPrelude ); 593 637 } else { … … 597 641 // depending on commandline options, either generate code or dump the AST 598 642 if ( codegenp ) { 599 CodeGen::generate( decls, out, ! noprotop, prettycodegenp );643 CodeGen::generate( decls, out, ! genproto, prettycodegenp ); 600 644 } else { 601 645 printAll( decls, out ); 602 } 646 } // if 603 647 deleteAll( translationUnit ); 604 648 } // dump
Note:
See TracChangeset
for help on using the changeset viewer.