Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/main.cc

    re6955b1 r35f9114  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug 20 12:52:22 2016
    13 // Update Count     : 403
     12// Last Modified On : Sat Aug  6 16:17:41 2016
     13// Update Count     : 210
    1414//
    1515
    1616#include <iostream>
    1717#include <fstream>
    18 #include <signal.h>                                                                             // signal
    19 #include <getopt.h>                                                                             // getopt
    20 #include <execinfo.h>                                                                   // backtrace, backtrace_symbols_fd
    21 #include <cxxabi.h>                                                                             // __cxa_demangle
    22 
    23 using namespace std;
    24 
    25 #include "Parser/lex.h"
    26 #include "Parser/parser.h"
    27 #include "Parser/TypedefTable.h"
     18#include <cstdlib>
     19#include <cstdio>
     20#include <getopt.h>
     21#include "Parser/Parser.h"
     22#include "Parser/ParseNode.h"
     23#include "Parser/LinkageSpec.h"
     24#include "SynTree/Declaration.h"
     25#include "SynTree/Visitor.h"
    2826#include "GenPoly/Lvalue.h"
    2927#include "GenPoly/Specialize.h"
     
    3432#include "CodeGen/FixNames.h"
    3533#include "ControlStruct/Mutate.h"
     34#include "Tuples/Mutate.h"
     35#include "Tuples/FunctionChecker.h"
     36#include "SymTab/Mangler.h"
     37#include "SymTab/Indexer.h"
    3638#include "SymTab/Validate.h"
    3739#include "ResolvExpr/AlternativePrinter.h"
    3840#include "ResolvExpr/Resolver.h"
    3941#include "MakeLibCfa.h"
     42#include "InitTweak/Mutate.h"
    4043#include "InitTweak/GenInit.h"
    4144#include "InitTweak/FixInit.h"
     45//#include "Explain/GenProlog.h"
     46//#include "Try/Visit.h"
     47
     48#include "Common/SemanticError.h"
    4249#include "Common/UnimplementedError.h"
     50
    4351#include "../config.h"
    4452
    4553using namespace std;
    4654
    47 #define OPTPRINT(x) if ( errorp ) cerr << x << endl;
    48 
    49 
    50 LinkageSpec::Spec linkage = LinkageSpec::Cforall;
    51 TypedefTable typedefTable;
    52 DeclarationNode * parseTree = nullptr;                                  // program parse tree
    53 
    54 extern int yydebug;                                                                             // set for -g flag (Grammar)
     55#define OPTPRINT(x) \
     56        if ( errorp ) std::cerr << x << std::endl;
     57
     58static void parse( FILE * input, LinkageSpec::Type t, bool shouldExit = false );
     59static void dump( std::list< Declaration * > & translationUnit, std::ostream & out = std::cout );
     60
    5561bool
    5662        astp = false,
     
    6066        exprp = false,
    6167        expraltp = false,
     68        grammarp = false,
    6269        libcfap = false,
    6370        nopreludep = false,
     
    7178        codegenp = false;
    7279
    73 static void parse_cmdline( int argc, char *argv[], const char *& filename );
    74 static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false );
    75 static void dump( list< Declaration * > & translationUnit, ostream & out = cout );
    76 
    77 void sigSegvBusHandler( int sig_num ) {
    78         enum { Frames = 50 };
    79         void * array[Frames];
    80         int size = backtrace( array, Frames );
    81 
    82         cerr << "*CFA runtime error* program cfa-cpp terminated with "
    83                  <<     (sig_num == SIGSEGV ? "segment fault" : "bus error")
    84                  << " backtrace:" << endl;
    85 
    86         char ** messages = backtrace_symbols( array, size );   
    87 
    88         // skip first stack frame (points here)
    89         for ( int i = 2; i < size - 2 && messages != nullptr; i += 1 ) {
    90                 char * mangled_name = nullptr, * offset_begin = nullptr, * offset_end = nullptr;
    91                 for ( char *p = messages[i]; *p; ++p ) {        // find parantheses and +offset
    92                         if (*p == '(') {
    93                                 mangled_name = p;
    94                         } else if (*p == '+') {
    95                                 offset_begin = p;
    96                         } else if (*p == ')') {
    97                                 offset_end = p;
    98                                 break;
    99                         } // if
    100                 } // for
    101 
    102                 // if line contains symbol, attempt to demangle
    103                 if ( mangled_name && offset_begin && offset_end && mangled_name < offset_begin ) {
    104                         *mangled_name++ = '\0';
    105                         *offset_begin++ = '\0';
    106                         *offset_end++ = '\0';
    107 
    108                         int status;
    109                         char * real_name = __cxxabiv1::__cxa_demangle( mangled_name, 0, 0, &status );
    110                         if ( status == 0 ) {                                            // demangling successful ?
    111                                 cerr << "(" << i - 2 << ") " << messages[i] << " : "
    112                                          << real_name << "+" << offset_begin << offset_end << endl;
    113 
    114                         } else {                                                                        // otherwise, output mangled name
    115                                 cerr << "(" << i - 2 << ") " << messages[i] << " : "
    116                                          << mangled_name << "+" << offset_begin << offset_end << endl;
    117                         } // if
    118                         free( real_name );
    119                 } else {                                                                                // otherwise, print the whole line
    120                         cerr << "(" << i - 2 << ") " << messages[i] << endl;
    121                 } // if
    122         } // for
    123         free( messages );
    124         exit( EXIT_FAILURE );
    125 } // sigSegvBusHandler
    126 
    127 int main( int argc, char * argv[] ) {
    128         FILE * input;                                                                           // use FILE rather than istream because yyin is FILE
    129         ostream *output = & cout;
    130         const char *filename = nullptr;
    131         list< Declaration * > translationUnit;
    132 
    133         signal( SIGSEGV, sigSegvBusHandler );
    134         signal( SIGBUS, sigSegvBusHandler );
    135 
    136         parse_cmdline( argc, argv, filename );                          // process command-line arguments
     80enum { Ast, Bbox, Bresolver, CtorInitFix, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, };
     81
     82static struct option long_opts[] = {
     83        { "ast", no_argument, 0, Ast },
     84        { "before-box", no_argument, 0, Bbox },
     85        { "before-resolver", no_argument, 0, Bresolver },
     86        { "ctorinitfix", no_argument, 0, CtorInitFix },
     87        { "expr", no_argument, 0, Expr },
     88        { "expralt", no_argument, 0, ExprAlt },
     89        { "grammar", no_argument, 0, Grammar },
     90        { "libcfa", no_argument, 0, LibCFA },
     91        { "no-preamble", no_argument, 0, Nopreamble },
     92        { "parse", no_argument, 0, Parse },
     93        { "no-prototypes", no_argument, 0, Prototypes },
     94        { "resolver", no_argument, 0, Resolver },
     95        { "symbol", no_argument, 0, Symbol },
     96        { "tree", no_argument, 0, Tree },
     97        { "validate", no_argument, 0, Validate },
     98        { 0, 0, 0, 0 }
     99};
     100
     101int main( int argc, char *argv[] ) {
     102        FILE *input;
     103        std::ostream *output = &std::cout;
     104        int long_index;
     105        std::list< Declaration * > translationUnit;
     106        const char *filename = NULL;
     107
     108        opterr = 0;                                                                                     // prevent getopt from printing error messages
     109
     110        int c;
     111        while ( (c = getopt_long( argc, argv, "abBcefglnpqrstvyzD:F:", long_opts, &long_index )) != -1 ) {
     112                switch ( c ) {
     113                  case Ast:
     114                  case 'a':                                                                             // dump AST
     115                        astp = true;
     116                        break;
     117                  case Bresolver:
     118                  case 'b':                                                                             // print before resolver steps
     119                        bresolvep = true;
     120                        break;
     121                  case 'B':                                                                             // print before resolver steps
     122                        bboxp = true;
     123                        break;
     124                  case CtorInitFix:
     125                  case 'c':
     126                        ctorinitp = true;
     127                        break;
     128                  case Expr:
     129                  case 'e':                                                                             // dump AST after expression analysis
     130                        exprp = true;
     131                        break;
     132                  case ExprAlt:
     133                  case 'f':                                                                             // print alternatives for expressions
     134                        expraltp = true;
     135                        break;
     136                  case Grammar:
     137                  case 'g':                                                                             // bison debugging info (grammar rules)
     138                        grammarp = true;
     139                        break;
     140                  case LibCFA:
     141                  case 'l':                                                                             // generate libcfa.c
     142                        libcfap = true;
     143                        break;
     144                  case Nopreamble:
     145                  case 'n':                                                                             // do not read preamble
     146                        nopreludep = true;
     147                        break;
     148                  case Prototypes:
     149                  case 'p':                                                                             // generate prototypes for preamble functions
     150                        noprotop = true;
     151                        break;
     152                  case Parse:
     153                  case 'q':                                                                             // dump parse tree
     154                        parsep = true;
     155                        break;
     156                  case Resolver:
     157                  case 'r':                                                                             // print resolver steps
     158                        resolvep = true;
     159                        break;
     160                  case Symbol:
     161                  case 's':                                                                             // print symbol table events
     162                        symtabp = true;
     163                        break;
     164                  case Tree:
     165                  case 't':                                                                             // build in tree
     166                        treep = true;
     167                        break;
     168                  case 'v':                                                                             // dump AST after decl validation pass
     169                        validp = true;
     170                        break;
     171                  case 'y':
     172                        errorp = true;
     173                        break;
     174                  case 'z':
     175                        codegenp = true;
     176                        break;
     177                  case 'D':                                                                             // ignore -Dxxx
     178                        break;
     179                  case 'F':                                                                             // source file-name without suffix
     180                        filename = optarg;
     181                        break;
     182                  case '?':
     183                        cout << "Unknown option: '" << (char)optopt << "'" << endl;
     184                        exit( EXIT_FAILURE );
     185                  default:
     186                        abort();
     187                } // switch
     188        } // while
    137189
    138190        try {
    139191                // choose to read the program from a file or stdin
    140                 if ( optind < argc ) {                                                  // any commands after the flags ? => input file name
     192                if ( optind < argc ) {
    141193                        input = fopen( argv[ optind ], "r" );
    142                         assertf( input, "cannot open %s\n", argv[ optind ] );
     194                        if ( ! input ) {
     195                                std::cout << "Error: cannot open " << argv[ optind ] << std::endl;
     196                                exit( EXIT_FAILURE );
     197                        } // if
    143198                        // if running cfa-cpp directly, might forget to pass -F option (and really shouldn't have to)
    144                         if ( filename == nullptr ) filename = argv[ optind ];
     199                        if ( filename == NULL ) filename = argv[ optind ];
    145200                        // prelude filename comes in differently
    146201                        if ( libcfap ) filename = "prelude.cf";
    147202                        optind += 1;
    148                 } else {                                                                                // no input file name
     203                } else {
    149204                        input = stdin;
    150205                        // if running cfa-cpp directly, might forget to pass -F option. Since this takes from stdin, pass
    151206                        // a fake name along
    152                         if ( filename == nullptr ) filename = "stdin";
    153                 } // if
    154 
    155                 if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
     207                        if ( filename == NULL ) filename = "stdin";
     208                } // if
     209
     210                if ( optind < argc ) {
    156211                        output = new ofstream( argv[ optind ] );
    157212                } // if
     213
     214                Parser::get_parser().set_debug( grammarp );
    158215
    159216                // read in the builtins, extras, and the prelude
     
    161218                        // -l is for initial build ONLY and builtins.cf is not in the lib directory so access it here.
    162219                        FILE * builtins = fopen( libcfap | treep ? "builtins.cf" : CFA_LIBDIR "/builtins.cf", "r" );
    163                         assertf( builtins, "cannot open builtins.cf\n" );
     220                        if ( builtins == NULL ) {
     221                                std::cerr << "Error: cannot open builtins.cf" << std::endl;
     222                                exit( EXIT_FAILURE );
     223                        } // if
    164224                        parse( builtins, LinkageSpec::Compiler );
    165225
    166226                        // read the extra prelude in, if not generating the cfa library
    167227                        FILE * extras = fopen( libcfap | treep ? "extras.cf" : CFA_LIBDIR "/extras.cf", "r" );
    168                         assertf( extras, "cannot open extras.cf\n" );
     228                        if ( extras == NULL ) {
     229                                std::cerr << "Error: cannot open extras.cf" << std::endl;
     230                                exit( EXIT_FAILURE );
     231                        } // if
    169232                        parse( extras, LinkageSpec::C );
    170233
     
    172235                                // read the prelude in, if not generating the cfa library
    173236                                FILE * prelude = fopen( treep ? "prelude.cf" : CFA_LIBDIR "/prelude.cf", "r" );
    174                                 assertf( prelude, "cannot open prelude.cf\n" );
     237                                if ( prelude == NULL ) {
     238                                        std::cerr << "Error: cannot open prelude.cf" << std::endl;
     239                                        exit( EXIT_FAILURE );
     240                                } // if
     241
    175242                                parse( prelude, LinkageSpec::Intrinsic );
    176243                        } // if
    177244                } // if
    178245
    179                 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, yydebug );
     246                parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, grammarp );
    180247
    181248                if ( parsep ) {
    182                         parseTree->printList( cout );
    183                         delete parseTree;
    184                         return 0;
    185                 } // if
    186 
    187                 buildList( parseTree, translationUnit );
    188                 delete parseTree;
    189                 parseTree = nullptr;
    190 
     249                        Parser::get_parser().get_parseTree()->printList( std::cout );
     250                        Parser::get_parser().freeTree();
     251                        return 0;
     252                } // if
     253
     254                buildList( Parser::get_parser().get_parseTree(), translationUnit );
     255
     256                Parser::get_parser().freeTree();
    191257                if ( astp ) {
    192258                        dump( translationUnit );
     
    202268
    203269                if ( expraltp ) {
    204                         ResolvExpr::AlternativePrinter printer( cout );
     270                        ResolvExpr::AlternativePrinter printer( std::cout );
    205271                        acceptAll( translationUnit, printer );
    206272                        return 0;
     
    234300                        dump( translationUnit );
    235301                        return 0;
    236                 } // if
     302                }
    237303
    238304                // fix ObjectDecl - replaces ConstructorInit nodes
     
    242308                        dump ( translationUnit );
    243309                        return 0;
    244                 } // if
     310                }
    245311
    246312                OPTPRINT("instantiateGenerics")
     
    256322                        dump( translationUnit );
    257323                        return 0;
    258                 } // if
     324                }
    259325                OPTPRINT( "box" )
    260326                GenPoly::box( translationUnit );
     
    268334                CodeGen::generate( translationUnit, *output, ! noprotop );
    269335
    270                 if ( output != &cout ) {
     336                if ( output != &std::cout ) {
    271337                        delete output;
    272338                } // if
    273339        } catch ( SemanticError &e ) {
    274340                if ( errorp ) {
    275                         cerr << "---AST at error:---" << endl;
    276                         dump( translationUnit, cerr );
    277                         cerr << endl << "---End of AST, begin error message:---\n" << endl;
    278                 } // if
    279                 e.print( cerr );
    280                 if ( output != &cout ) {
     341                        std::cerr << "---AST at error:---" << std::endl;
     342                        dump( translationUnit, std::cerr );
     343                        std::cerr << std::endl << "---End of AST, begin error message:---\n" << std::endl;
     344                }
     345                e.print( std::cerr );
     346                if ( output != &std::cout ) {
    281347                        delete output;
    282348                } // if
    283349                return 1;
    284350        } catch ( UnimplementedError &e ) {
    285                 cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
    286                 if ( output != &cout ) {
     351                std::cout << "Sorry, " << e.get_what() << " is not currently implemented" << std::endl;
     352                if ( output != &std::cout ) {
    287353                        delete output;
    288354                } // if
    289355                return 1;
    290356        } catch ( CompilerError &e ) {
    291                 cerr << "Compiler Error: " << e.get_what() << endl;
    292                 cerr << "(please report bugs to " << endl;
    293                 if ( output != &cout ) {
     357                std::cerr << "Compiler Error: " << e.get_what() << std::endl;
     358                std::cerr << "(please report bugs to " << std::endl;
     359                if ( output != &std::cout ) {
    294360                        delete output;
    295361                } // if
     
    301367} // main
    302368
    303 void parse_cmdline( int argc, char * argv[], const char *& filename ) {
    304         enum { Ast, Bbox, Bresolver, CtorInitFix, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, };
    305 
    306         static struct option long_opts[] = {
    307                 { "ast", no_argument, 0, Ast },
    308                 { "before-box", no_argument, 0, Bbox },
    309                 { "before-resolver", no_argument, 0, Bresolver },
    310                 { "ctorinitfix", no_argument, 0, CtorInitFix },
    311                 { "expr", no_argument, 0, Expr },
    312                 { "expralt", no_argument, 0, ExprAlt },
    313                 { "grammar", no_argument, 0, Grammar },
    314                 { "libcfa", no_argument, 0, LibCFA },
    315                 { "no-preamble", no_argument, 0, Nopreamble },
    316                 { "parse", no_argument, 0, Parse },
    317                 { "no-prototypes", no_argument, 0, Prototypes },
    318                 { "resolver", no_argument, 0, Resolver },
    319                 { "symbol", no_argument, 0, Symbol },
    320                 { "tree", no_argument, 0, Tree },
    321                 { "validate", no_argument, 0, Validate },
    322                 { 0, 0, 0, 0 }
    323         }; // long_opts
    324         int long_index;
    325 
    326         opterr = 0;                                                                                     // (global) prevent getopt from printing error messages
    327 
    328         int c;
    329         while ( (c = getopt_long( argc, argv, "abBcefglnpqrstvyzD:F:", long_opts, &long_index )) != -1 ) {
    330                 switch ( c ) {
    331                   case Ast:
    332                   case 'a':                                                                             // dump AST
    333                         astp = true;
    334                         break;
    335                   case Bresolver:
    336                   case 'b':                                                                             // print before resolver steps
    337                         bresolvep = true;
    338                         break;
    339                   case 'B':                                                                             // print before resolver steps
    340                         bboxp = true;
    341                         break;
    342                   case CtorInitFix:
    343                   case 'c':
    344                         ctorinitp = true;
    345                         break;
    346                   case Expr:
    347                   case 'e':                                                                             // dump AST after expression analysis
    348                         exprp = true;
    349                         break;
    350                   case ExprAlt:
    351                   case 'f':                                                                             // print alternatives for expressions
    352                         expraltp = true;
    353                         break;
    354                   case Grammar:
    355                   case 'g':                                                                             // bison debugging info (grammar rules)
    356                         yydebug = true;
    357                         break;
    358                   case LibCFA:
    359                   case 'l':                                                                             // generate libcfa.c
    360                         libcfap = true;
    361                         break;
    362                   case Nopreamble:
    363                   case 'n':                                                                             // do not read preamble
    364                         nopreludep = true;
    365                         break;
    366                   case Prototypes:
    367                   case 'p':                                                                             // generate prototypes for preamble functions
    368                         noprotop = true;
    369                         break;
    370                   case Parse:
    371                   case 'q':                                                                             // dump parse tree
    372                         parsep = true;
    373                         break;
    374                   case Resolver:
    375                   case 'r':                                                                             // print resolver steps
    376                         resolvep = true;
    377                         break;
    378                   case Symbol:
    379                   case 's':                                                                             // print symbol table events
    380                         symtabp = true;
    381                         break;
    382                   case Tree:
    383                   case 't':                                                                             // build in tree
    384                         treep = true;
    385                         break;
    386                   case 'v':                                                                             // dump AST after decl validation pass
    387                         validp = true;
    388                         break;
    389                   case 'y':
    390                         errorp = true;
    391                         break;
    392                   case 'z':
    393                         codegenp = true;
    394                         break;
    395                   case 'D':                                                                             // ignore -Dxxx
    396                         break;
    397                   case 'F':                                                                             // source file-name without suffix
    398                         filename = optarg;
    399                         break;
    400                   case '?':
    401                         assertf( false, "Unknown option: '%c'\n", (char)optopt );
    402                   default:
    403                         abort();
    404                 } // switch
    405         } // while
    406 } // parse_cmdline
    407 
    408 static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit ) {
    409         extern int yyparse( void );
    410         extern FILE * yyin;
    411         extern int yylineno;
    412 
    413         ::linkage = linkage;                                                            // set globals
    414         yyin = input;
    415         yylineno = 1;
    416         typedefTable.enterScope();
    417         int parseStatus = yyparse();
     369static void parse( FILE * input, LinkageSpec::Type linkage, bool shouldExit ) {
     370        Parser::get_parser().set_linkage( linkage );
     371        Parser::get_parser().parse( input );
    418372
    419373        fclose( input );
    420         if ( shouldExit || parseStatus != 0 ) {
    421                 exit( parseStatus );
     374        if ( shouldExit || Parser::get_parser().get_parseStatus() != 0 ) {
     375                exit( Parser::get_parser().get_parseStatus() );
    422376        } // if
    423 } // parse
     377}
    424378
    425379static bool notPrelude( Declaration * decl ) {
    426380        return ! LinkageSpec::isBuiltin( decl->get_linkage() );
    427 } // notPrelude
    428 
    429 static void dump( list< Declaration * > & translationUnit, ostream & out ) {
    430         list< Declaration * > decls;
    431 
     381}
     382
     383static void dump( std::list< Declaration * > & translationUnit, std::ostream & out ) {
     384        std::list< Declaration * > decls;
    432385        if ( noprotop ) {
    433                 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), notPrelude );
     386                filter( translationUnit.begin(), translationUnit.end(),
     387                                std::back_inserter( decls ), notPrelude );
    434388        } else {
    435389                decls = translationUnit;
    436         } // if
     390        }
    437391
    438392        printAll( decls, out );
    439393        deleteAll( translationUnit );
    440 } // dump
     394}
     395
    441396
    442397// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.