Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/main.cc

    r35f9114 re6955b1  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug  6 16:17:41 2016
    13 // Update Count     : 210
     12// Last Modified On : Sat Aug 20 12:52:22 2016
     13// Update Count     : 403
    1414//
    1515
    1616#include <iostream>
    1717#include <fstream>
    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"
     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
     23using namespace std;
     24
     25#include "Parser/lex.h"
     26#include "Parser/parser.h"
     27#include "Parser/TypedefTable.h"
    2628#include "GenPoly/Lvalue.h"
    2729#include "GenPoly/Specialize.h"
     
    3234#include "CodeGen/FixNames.h"
    3335#include "ControlStruct/Mutate.h"
    34 #include "Tuples/Mutate.h"
    35 #include "Tuples/FunctionChecker.h"
    36 #include "SymTab/Mangler.h"
    37 #include "SymTab/Indexer.h"
    3836#include "SymTab/Validate.h"
    3937#include "ResolvExpr/AlternativePrinter.h"
    4038#include "ResolvExpr/Resolver.h"
    4139#include "MakeLibCfa.h"
    42 #include "InitTweak/Mutate.h"
    4340#include "InitTweak/GenInit.h"
    4441#include "InitTweak/FixInit.h"
    45 //#include "Explain/GenProlog.h"
    46 //#include "Try/Visit.h"
    47 
    48 #include "Common/SemanticError.h"
    4942#include "Common/UnimplementedError.h"
    50 
    5143#include "../config.h"
    5244
    5345using namespace std;
    5446
    55 #define OPTPRINT(x) \
    56         if ( errorp ) std::cerr << x << std::endl;
    57 
    58 static void parse( FILE * input, LinkageSpec::Type t, bool shouldExit = false );
    59 static void dump( std::list< Declaration * > & translationUnit, std::ostream & out = std::cout );
    60 
     47#define OPTPRINT(x) if ( errorp ) cerr << x << endl;
     48
     49
     50LinkageSpec::Spec linkage = LinkageSpec::Cforall;
     51TypedefTable typedefTable;
     52DeclarationNode * parseTree = nullptr;                                  // program parse tree
     53
     54extern int yydebug;                                                                             // set for -g flag (Grammar)
    6155bool
    6256        astp = false,
     
    6660        exprp = false,
    6761        expraltp = false,
    68         grammarp = false,
    6962        libcfap = false,
    7063        nopreludep = false,
     
    7871        codegenp = false;
    7972
    80 enum { Ast, Bbox, Bresolver, CtorInitFix, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, };
    81 
    82 static 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 
    101 int 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
     73static void parse_cmdline( int argc, char *argv[], const char *& filename );
     74static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false );
     75static void dump( list< Declaration * > & translationUnit, ostream & out = cout );
     76
     77void 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
     127int 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
    189137
    190138        try {
    191139                // choose to read the program from a file or stdin
    192                 if ( optind < argc ) {
     140                if ( optind < argc ) {                                                  // any commands after the flags ? => input file name
    193141                        input = fopen( argv[ optind ], "r" );
    194                         if ( ! input ) {
    195                                 std::cout << "Error: cannot open " << argv[ optind ] << std::endl;
    196                                 exit( EXIT_FAILURE );
    197                         } // if
     142                        assertf( input, "cannot open %s\n", argv[ optind ] );
    198143                        // if running cfa-cpp directly, might forget to pass -F option (and really shouldn't have to)
    199                         if ( filename == NULL ) filename = argv[ optind ];
     144                        if ( filename == nullptr ) filename = argv[ optind ];
    200145                        // prelude filename comes in differently
    201146                        if ( libcfap ) filename = "prelude.cf";
    202147                        optind += 1;
    203                 } else {
     148                } else {                                                                                // no input file name
    204149                        input = stdin;
    205150                        // if running cfa-cpp directly, might forget to pass -F option. Since this takes from stdin, pass
    206151                        // a fake name along
    207                         if ( filename == NULL ) filename = "stdin";
    208                 } // if
    209 
    210                 if ( optind < argc ) {
     152                        if ( filename == nullptr ) filename = "stdin";
     153                } // if
     154
     155                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
    211156                        output = new ofstream( argv[ optind ] );
    212157                } // if
    213 
    214                 Parser::get_parser().set_debug( grammarp );
    215158
    216159                // read in the builtins, extras, and the prelude
     
    218161                        // -l is for initial build ONLY and builtins.cf is not in the lib directory so access it here.
    219162                        FILE * builtins = fopen( libcfap | treep ? "builtins.cf" : CFA_LIBDIR "/builtins.cf", "r" );
    220                         if ( builtins == NULL ) {
    221                                 std::cerr << "Error: cannot open builtins.cf" << std::endl;
    222                                 exit( EXIT_FAILURE );
    223                         } // if
     163                        assertf( builtins, "cannot open builtins.cf\n" );
    224164                        parse( builtins, LinkageSpec::Compiler );
    225165
    226166                        // read the extra prelude in, if not generating the cfa library
    227167                        FILE * extras = fopen( libcfap | treep ? "extras.cf" : CFA_LIBDIR "/extras.cf", "r" );
    228                         if ( extras == NULL ) {
    229                                 std::cerr << "Error: cannot open extras.cf" << std::endl;
    230                                 exit( EXIT_FAILURE );
    231                         } // if
     168                        assertf( extras, "cannot open extras.cf\n" );
    232169                        parse( extras, LinkageSpec::C );
    233170
     
    235172                                // read the prelude in, if not generating the cfa library
    236173                                FILE * prelude = fopen( treep ? "prelude.cf" : CFA_LIBDIR "/prelude.cf", "r" );
    237                                 if ( prelude == NULL ) {
    238                                         std::cerr << "Error: cannot open prelude.cf" << std::endl;
    239                                         exit( EXIT_FAILURE );
    240                                 } // if
    241 
     174                                assertf( prelude, "cannot open prelude.cf\n" );
    242175                                parse( prelude, LinkageSpec::Intrinsic );
    243176                        } // if
    244177                } // if
    245178
    246                 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, grammarp );
     179                parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, yydebug );
    247180
    248181                if ( parsep ) {
    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();
     182                        parseTree->printList( cout );
     183                        delete parseTree;
     184                        return 0;
     185                } // if
     186
     187                buildList( parseTree, translationUnit );
     188                delete parseTree;
     189                parseTree = nullptr;
     190
    257191                if ( astp ) {
    258192                        dump( translationUnit );
     
    268202
    269203                if ( expraltp ) {
    270                         ResolvExpr::AlternativePrinter printer( std::cout );
     204                        ResolvExpr::AlternativePrinter printer( cout );
    271205                        acceptAll( translationUnit, printer );
    272206                        return 0;
     
    300234                        dump( translationUnit );
    301235                        return 0;
    302                 }
     236                } // if
    303237
    304238                // fix ObjectDecl - replaces ConstructorInit nodes
     
    308242                        dump ( translationUnit );
    309243                        return 0;
    310                 }
     244                } // if
    311245
    312246                OPTPRINT("instantiateGenerics")
     
    322256                        dump( translationUnit );
    323257                        return 0;
    324                 }
     258                } // if
    325259                OPTPRINT( "box" )
    326260                GenPoly::box( translationUnit );
     
    334268                CodeGen::generate( translationUnit, *output, ! noprotop );
    335269
    336                 if ( output != &std::cout ) {
     270                if ( output != &cout ) {
    337271                        delete output;
    338272                } // if
    339273        } catch ( SemanticError &e ) {
    340274                if ( errorp ) {
    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 ) {
     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 ) {
    347281                        delete output;
    348282                } // if
    349283                return 1;
    350284        } catch ( UnimplementedError &e ) {
    351                 std::cout << "Sorry, " << e.get_what() << " is not currently implemented" << std::endl;
    352                 if ( output != &std::cout ) {
     285                cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
     286                if ( output != &cout ) {
    353287                        delete output;
    354288                } // if
    355289                return 1;
    356290        } catch ( CompilerError &e ) {
    357                 std::cerr << "Compiler Error: " << e.get_what() << std::endl;
    358                 std::cerr << "(please report bugs to " << std::endl;
    359                 if ( output != &std::cout ) {
     291                cerr << "Compiler Error: " << e.get_what() << endl;
     292                cerr << "(please report bugs to " << endl;
     293                if ( output != &cout ) {
    360294                        delete output;
    361295                } // if
     
    367301} // main
    368302
    369 static void parse( FILE * input, LinkageSpec::Type linkage, bool shouldExit ) {
    370         Parser::get_parser().set_linkage( linkage );
    371         Parser::get_parser().parse( input );
     303void 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
     408static 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();
    372418
    373419        fclose( input );
    374         if ( shouldExit || Parser::get_parser().get_parseStatus() != 0 ) {
    375                 exit( Parser::get_parser().get_parseStatus() );
     420        if ( shouldExit || parseStatus != 0 ) {
     421                exit( parseStatus );
    376422        } // if
    377 }
     423} // parse
    378424
    379425static bool notPrelude( Declaration * decl ) {
    380426        return ! LinkageSpec::isBuiltin( decl->get_linkage() );
    381 }
    382 
    383 static void dump( std::list< Declaration * > & translationUnit, std::ostream & out ) {
    384         std::list< Declaration * > decls;
     427} // notPrelude
     428
     429static void dump( list< Declaration * > & translationUnit, ostream & out ) {
     430        list< Declaration * > decls;
     431
    385432        if ( noprotop ) {
    386                 filter( translationUnit.begin(), translationUnit.end(),
    387                                 std::back_inserter( decls ), notPrelude );
     433                filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), notPrelude );
    388434        } else {
    389435                decls = translationUnit;
    390         }
     436        } // if
    391437
    392438        printAll( decls, out );
    393439        deleteAll( translationUnit );
    394 }
    395 
     440} // dump
    396441
    397442// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.