tizen 2.3.1 release
[external/ragel.git] / ragel / main.cpp
index 2e7d989..2b54b51 100644 (file)
@@ -54,7 +54,6 @@
 #include "vector.h"
 #include "version.h"
 #include "common.h"
-#include "xmlparse.h"
 #include "inputdata.h"
 
 using std::istream;
@@ -78,7 +77,7 @@ bool machineSpecFound = false;
 bool wantDupsRemoved = true;
 
 bool printStatistics = false;
-bool frontendOnly = false;
+bool generateXML = false;
 bool generateDot = false;
 
 /* Target language and output style. */
@@ -88,18 +87,10 @@ int numSplitPartitions = 0;
 bool noLineDirectives = false;
 
 bool displayPrintables = false;
-bool graphvizDone = false;
 
 /* Target ruby impl */
 RubyImplEnum rubyImpl = MRI;
 
-ArgsVector includePaths;
-
-istream *inStream = 0;
-ostream *outStream = 0;
-output_filter *outFilter = 0;
-const char *outputFileName = 0;
-
 /* Print a summary of the options. */
 void usage()
 {
@@ -156,7 +147,7 @@ void usage()
 void version()
 {
        cout << "Ragel State Machine Compiler version " VERSION << " " PUBDATE << endl <<
-                       "Copyright (c) 2001-2008 by Adrian Thurston" << endl;
+                       "Copyright (c) 2001-2009 by Adrian Thurston" << endl;
        exit(0);
 }
 
@@ -224,7 +215,7 @@ void escapeLineDirectivePath( std::ostream &out, char *path )
        }
 }
 
-void processArgs( int argc, const char **argv, const char *&inputFileName )
+void processArgs( int argc, const char **argv, InputData &id )
 {
        ParamCheck pc("xo:dnmleabjkS:M:I:CDJRAvHh?-:sT:F:G:P:LpV", argc, argv);
 
@@ -239,18 +230,18 @@ void processArgs( int argc, const char **argv, const char *&inputFileName )
                                break;
 
                        case 'x':
-                               frontendOnly = true;
+                               generateXML = true;
                                break;
 
                        /* Output. */
                        case 'o':
                                if ( *pc.paramArg == 0 )
                                        error() << "a zero length output file name was given" << endl;
-                               else if ( outputFileName != 0 )
+                               else if ( id.outputFileName != 0 )
                                        error() << "more than one output file name was given" << endl;
                                else {
                                        /* Ok, remember the output file name. */
-                                       outputFileName = pc.paramArg;
+                                       id.outputFileName = pc.paramArg;
                                }
                                break;
 
@@ -313,7 +304,7 @@ void processArgs( int argc, const char **argv, const char *&inputFileName )
                                if ( *pc.paramArg == 0 )
                                        error() << "please specify an argument to -I" << endl;
                                else {
-                                       includePaths.append( pc.paramArg );
+                                       id.includePaths.append( pc.paramArg );
                                }
                                break;
 
@@ -345,16 +336,17 @@ void processArgs( int argc, const char **argv, const char *&inputFileName )
                                printStatistics = true;
                                break;
                        case '-': {
-                               char *eq = strchr( pc.paramArg, '=' );
+                               char *arg = strdup( pc.paramArg );
+                               char *eq = strchr( arg, '=' );
 
                                if ( eq != 0 )
                                        *eq++ = 0;
 
-                               if ( strcmp( pc.paramArg, "help" ) == 0 )
+                               if ( strcmp( arg, "help" ) == 0 )
                                        usage();
-                               else if ( strcmp( pc.paramArg, "version" ) == 0 )
+                               else if ( strcmp( arg, "version" ) == 0 )
                                        version();
-                               else if ( strcmp( pc.paramArg, "error-format" ) == 0 ) {
+                               else if ( strcmp( arg, "error-format" ) == 0 ) {
                                        if ( eq == 0 )
                                                error() << "expecting '=value' for error-format" << endl;
                                        else if ( strcmp( eq, "gnu" ) == 0 )
@@ -364,12 +356,13 @@ void processArgs( int argc, const char **argv, const char *&inputFileName )
                                        else
                                                error() << "invalid value for error-format" << endl;
                                }
-                               else if ( strcmp( pc.paramArg, "rbx" ) == 0 )
+                               else if ( strcmp( arg, "rbx" ) == 0 )
                                        rubyImpl = Rubinius;
                                else {
                                        error() << "--" << pc.paramArg << 
                                                        " is an invalid argument" << endl;
                                }
+                               free( arg );
                                break;
                        }
 
@@ -432,27 +425,24 @@ void processArgs( int argc, const char **argv, const char *&inputFileName )
                        /* It is interpreted as an input file. */
                        if ( *pc.curArg == 0 )
                                error() << "a zero length input file name was given" << endl;
-                       else if ( inputFileName != 0 )
+                       else if ( id.inputFileName != 0 )
                                error() << "more than one input file name was given" << endl;
                        else {
                                /* OK, Remember the filename. */
-                               inputFileName = pc.curArg;
+                               id.inputFileName = pc.curArg;
                        }
                        break;
                }
        }
 }
 
-void process( const char *inputFileName )
+void process( InputData &id )
 {
-       bool wantComplete = true;
-       bool outputActive = true;
-
        /* Open the input file for reading. */
-       assert( inputFileName != 0 );
-       ifstream *inFile = new ifstream( inputFileName );
+       assert( id.inputFileName != 0 );
+       ifstream *inFile = new ifstream( id.inputFileName );
        if ( ! inFile->is_open() )
-               error() << "could not open " << inputFileName << " for reading" << endp;
+               error() << "could not open " << id.inputFileName << " for reading" << endp;
 
        /* Used for just a few things. */
        std::ostringstream hostData;
@@ -460,26 +450,20 @@ void process( const char *inputFileName )
        /* Make the first input item. */
        InputItem *firstInputItem = new InputItem;
        firstInputItem->type = InputItem::HostData;
+       firstInputItem->loc.fileName = id.inputFileName;
        firstInputItem->loc.line = 1;
        firstInputItem->loc.col = 1;
-       inputItems.append( firstInputItem );
+       id.inputItems.append( firstInputItem );
 
-       Scanner scanner( inputFileName, *inFile, 0, 0, 0, false );
+       Scanner scanner( id, id.inputFileName, *inFile, 0, 0, 0, false );
        scanner.do_scan();
 
        /* Finished, final check for errors.. */
        if ( gblErrorCount > 0 )
                exit(1);
 
-       if ( generateDot ) {
-               wantComplete = false;
-               outputActive = false;
-       }
-
-       InputData inputData( inputFileName, outputActive, wantComplete );
-
        /* Now send EOF to all parsers. */
-       inputData.terminateAllParsers();
+       id.terminateAllParsers();
 
        /* Bail on above error. */
        if ( gblErrorCount > 0 )
@@ -487,50 +471,50 @@ void process( const char *inputFileName )
 
        /* Locate the backend program */
        /* Compiles machines. */
-       inputData.prepareMachineGen();
+       id.prepareMachineGen();
 
        if ( gblErrorCount > 0 )
                exit(1);
 
-       inputData.makeOutputStream();
+       id.makeOutputStream();
 
        /* Generates the reduced machine, which we use to write output. */
-       inputData.generateReduced();
+       if ( !generateXML ) {
+               id.generateReduced();
+
+               if ( gblErrorCount > 0 )
+                       exit(1);
+       }
 
+       id.verifyWritesHaveData();
        if ( gblErrorCount > 0 )
                exit(1);
 
-       inputData.openOutput();
-       inputData.writeOutput();
+       /*
+        * From this point on we should not be reporting any errors.
+        */
+
+       id.openOutput();
+       id.writeOutput();
 
        /* Close the input and the intermediate file. */
        delete inFile;
 
-       /* Bail on above error. */
-       if ( gblErrorCount > 0 )
-               exit(1);
-
        /* If writing to a file, delete the ostream, causing it to flush.
         * Standard out is flushed automatically. */
-       if ( outputFileName != 0 ) {
-               delete outStream;
-               delete outFilter;
+       if ( id.outputFileName != 0 ) {
+               delete id.outStream;
+               delete id.outFilter;
        }
 
-       /* Finished, final check for errors.. */
-       if ( gblErrorCount > 0 ) {
-               /* If we opened an output file, remove it. */
-               if ( outputFileName != 0 )
-                       unlink( outputFileName );
-               exit(1);
-       }
+       assert( gblErrorCount == 0 );
 }
 
 char *makeIntermedTemplate( const char *baseFileName )
 {
        char *result = 0;
        const char *templ = "ragel-XXXXXX.xml";
-       char *lastSlash = strrchr( baseFileName, '/' );
+       const char *lastSlash = strrchr( baseFileName, '/' );
        if ( lastSlash == 0 ) {
                result = new char[strlen(templ)+1];
                strcpy( result, templ );
@@ -544,67 +528,16 @@ char *makeIntermedTemplate( const char *baseFileName )
        return result;
 };
 
-const char *openIntermed( const char *inputFileName, const char *outputFileName )
-{
-       srand(time(0));
-       const char *result = 0;
-
-       /* Which filename do we use as the base? */
-       const char *baseFileName = outputFileName != 0 ? outputFileName : inputFileName;
-
-       /* The template for the intermediate file name. */
-       const char *intermedFileName = makeIntermedTemplate( baseFileName );
-
-       /* Randomize the name and try to open. */
-       char fnChars[] = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-       char *firstX = strrchr( intermedFileName, 'X' ) - 5;
-       for ( int tries = 0; tries < 20; tries++ ) {
-               /* Choose a random name. */
-               for ( int x = 0; x < 6; x++ )
-                       firstX[x] = fnChars[rand() % 52];
-
-               /* Try to open the file. */
-               int fd = ::open( intermedFileName, O_WRONLY|O_EXCL|O_CREAT, S_IRUSR|S_IWUSR );
-
-               if ( fd > 0 ) {
-                       /* Success. Close the file immediately and return the name for use
-                        * by the child processes. */
-                       ::close( fd );
-                       result = intermedFileName;
-                       break;
-               }
-
-               if ( errno == EACCES ) {
-                       error() << "failed to open temp file " << intermedFileName << 
-                                       ", access denied" << endp;
-               }
-       }
-
-       if ( result == 0 )
-               error() << "abnormal error: cannot find unique name for temp file" << endp;
-
-       return result;
-}
-
-
-
 /* Main, process args and call yyparse to start scanning input. */
 int main( int argc, const char **argv )
 {
-       const char *inputFileName = 0;
-       processArgs( argc, argv, inputFileName );
-       
-
-       /* If -M or -S are given and we're not generating a dot file then invoke
-        * the frontend. These options are not useful with code generators. */
-       if ( machineName != 0 || machineSpec != 0 ) {
-               if ( !generateDot )
-                       frontendOnly = true;
-       }
+       InputData id;
+
+       processArgs( argc, argv, id );
 
        /* Require an input file. If we use standard in then we won't have a file
         * name on which to base the output. */
-       if ( inputFileName == 0 )
+       if ( id.inputFileName == 0 )
                error() << "no input file given" << endl;
 
        /* Bail on argument processing errors. */
@@ -612,17 +545,14 @@ int main( int argc, const char **argv )
                exit(1);
 
        /* Make sure we are not writing to the same file as the input file. */
-       if ( inputFileName != 0 && outputFileName != 0 && 
-                       strcmp( inputFileName, outputFileName  ) == 0 )
+       if ( id.inputFileName != 0 && id.outputFileName != 0 && 
+                       strcmp( id.inputFileName, id.outputFileName  ) == 0 )
        {
-               error() << "output file \"" << outputFileName  << 
+               error() << "output file \"" << id.outputFileName  << 
                                "\" is the same as the input file" << endp;
        }
 
-       process( inputFileName );
-
-       /* Clean up the intermediate. */
-       exit( 0 );
+       process( id );
 
        return 0;
 }