Split dotfile generation out into its own executable.
authorthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Mon, 12 Feb 2007 05:18:28 +0000 (05:18 +0000)
committerthurston <thurston@052ea7fc-9027-0410-9066-f65837a77df0>
Mon, 12 Feb 2007 05:18:28 +0000 (05:18 +0000)
git-svn-id: http://svn.complang.org/ragel/trunk@103 052ea7fc-9027-0410-9066-f65837a77df0

configure
configure.in
rlcodegen/Makefile.in
rlcodegen/fsmcodegen.cpp
rlcodegen/main.cpp
rlcodegen/rlcodegen.h
rlgen-dot/Makefile.in [new file with mode: 0644]
rlgen-dot/gvdotgen.cpp [moved from rlcodegen/gvdotgen.cpp with 97% similarity]
rlgen-dot/gvdotgen.h [moved from rlcodegen/gvdotgen.h with 100% similarity]
rlgen-dot/main.cpp [new file with mode: 0644]
rlgen-dot/rlgen-dot.h [new file with mode: 0644]

index 1c2ddb8..fbb8641 100755 (executable)
--- a/configure
+++ b/configure
@@ -2898,7 +2898,7 @@ _ACEOF
 
 fi
 
-                                                                                          ac_config_files="$ac_config_files Makefile common/Makefile ragel/Makefile redfsm/Makefile rlcodegen/Makefile rlgen-java/Makefile rlgen-ruby/Makefile doc/Makefile test/Makefile"
+                                                                                                    ac_config_files="$ac_config_files Makefile common/Makefile ragel/Makefile redfsm/Makefile rlcodegen/Makefile rlgen-java/Makefile rlgen-ruby/Makefile rlgen-dot/Makefile doc/Makefile test/Makefile"
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
@@ -3430,6 +3430,7 @@ do
   "rlcodegen/Makefile" ) CONFIG_FILES="$CONFIG_FILES rlcodegen/Makefile" ;;
   "rlgen-java/Makefile" ) CONFIG_FILES="$CONFIG_FILES rlgen-java/Makefile" ;;
   "rlgen-ruby/Makefile" ) CONFIG_FILES="$CONFIG_FILES rlgen-ruby/Makefile" ;;
+  "rlgen-dot/Makefile" ) CONFIG_FILES="$CONFIG_FILES rlgen-dot/Makefile" ;;
   "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
   "test/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
   "common/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS common/config.h" ;;
index 4bdb18b..a5a6177 100644 (file)
@@ -111,6 +111,6 @@ if test -n "$RUBY"; then
 fi
 
 dnl write output files
-AC_OUTPUT(Makefile common/Makefile ragel/Makefile redfsm/Makefile rlcodegen/Makefile rlgen-java/Makefile rlgen-ruby/Makefile doc/Makefile test/Makefile)
+AC_OUTPUT(Makefile common/Makefile ragel/Makefile redfsm/Makefile rlcodegen/Makefile rlgen-java/Makefile rlgen-ruby/Makefile rlgen-dot/Makefile doc/Makefile test/Makefile)
 
 echo "configuration of ragel complete"
index bb47c18..2dc2ccd 100644 (file)
@@ -24,7 +24,7 @@ DEFS +=
 CFLAGS += -g -Wall
 LDFLAGS +=
 
-CC_SRCS = main.cpp gvdotgen.cpp fsmcodegen.cpp \
+CC_SRCS = main.cpp fsmcodegen.cpp \
        tabcodegen.cpp ftabcodegen.cpp flatcodegen.cpp \
        fflatcodegen.cpp gotocodegen.cpp fgotocodegen.cpp \
        ipgotocodegen.cpp splitcodegen.cpp 
index 7ac1a5a..c8d35c4 100644 (file)
@@ -25,7 +25,6 @@
 #include "fsmcodegen.h"
 #include "redfsm.h"
 #include "gendata.h"
-#include "gvdotgen.h"
 #include <sstream>
 #include <string>
 #include <assert.h>
@@ -52,11 +51,9 @@ void lineDirective( ostream &out, char *fileName, int line )
 
 void genLineDirective( ostream &out )
 {
-       if ( outputFormat == OutCode ) {
-               std::streambuf *sbuf = out.rdbuf();
-               output_filter *filter = static_cast<output_filter*>(sbuf);
-               lineDirective( out, filter->fileName, filter->line + 1 );
-       }
+       std::streambuf *sbuf = out.rdbuf();
+       output_filter *filter = static_cast<output_filter*>(sbuf);
+       lineDirective( out, filter->fileName, filter->line + 1 );
 }
 
 
index 02918df..98488d8 100644 (file)
@@ -43,9 +43,6 @@
 #include "ipgotocodegen.h"
 #include "splitcodegen.h"
 
-#include "gvdotgen.h"
-
-
 using std::istream;
 using std::ifstream;
 using std::ostream;
@@ -56,7 +53,6 @@ using std::cerr;
 using std::endl;
 
 /* Target language and output style. */
-OutputFormat outputFormat = OutCode;
 CodeStyleEnum codeStyle = GenTables;
 
 /* Io globals. */
@@ -80,9 +76,6 @@ void usage()
 "   -h, -H, -?, --help    Print this usage and exit\n"
 "   -v, --version         Print version information and exit\n"
 "   -o <file>             Write output to <file>\n"
-"output:\n"
-"   -V                    Generate a Graphviz dotfile instead of code\n"
-"   -p                    Print printable characters in Graphviz output\n"
 "generated code style:\n"
 "   -T0                   Table driven FSM (default)\n"
 "   -T1                   Faster table driven FSM\n"
@@ -98,7 +91,7 @@ void usage()
 /* Print version information. */
 void version()
 {
-       cout << "Ragel Code Generator for C, C++, Objective-C, D and Graphviz" << endl <<
+       cout << "Ragel Code Generator for C, C++, Objective-C, D" << endl <<
                        "Version " VERSION << ", " PUBDATE << endl <<
                        "Copyright (c) 2001-2007 by Adrian Thurston" << endl;
 }
@@ -125,7 +118,7 @@ ostream *openOutput( char *inputFile )
 
        /* If the output format is code and no output file name is given, then
         * make a default. */
-       if ( outputFormat == OutCode && outputFileName == 0 ) {
+       if ( outputFileName == 0 ) {
                char *ext = findFileExtension( inputFile );
                if ( ext != 0 && strcmp( ext, ".rh" ) == 0 )
                        outputFileName = fileNameFromStem( inputFile, ".h" );
@@ -170,71 +163,66 @@ CodeGenData *makeCodeGen( char *sourceFileName, char *fsmName,
                ostream &out, bool wantComplete )
 {
        CodeGenData *codeGen = 0;
-       if ( outputFormat == OutGraphvizDot ) {
-               codeGen = new GraphvizDotGen(out);
-       }
-       else {
-               switch ( hostLangType ) {
-               case CCode:
-                       switch ( codeStyle ) {
-                       case GenTables:
-                               codeGen = new CTabCodeGen(out);
-                               break;
-                       case GenFTables:
-                               codeGen = new CFTabCodeGen(out);
-                               break;
-                       case GenFlat:
-                               codeGen = new CFlatCodeGen(out);
-                               break;
-                       case GenFFlat:
-                               codeGen = new CFFlatCodeGen(out);
-                               break;
-                       case GenGoto:
-                               codeGen = new CGotoCodeGen(out);
-                               break;
-                       case GenFGoto:
-                               codeGen = new CFGotoCodeGen(out);
-                               break;
-                       case GenIpGoto:
-                               codeGen = new CIpGotoCodeGen(out);
-                               break;
-                       case GenSplit:
-                               codeGen = new CSplitCodeGen(out);
-                               break;
-                       }
+       switch ( hostLangType ) {
+       case CCode:
+               switch ( codeStyle ) {
+               case GenTables:
+                       codeGen = new CTabCodeGen(out);
                        break;
-
-               case DCode:
-                       switch ( codeStyle ) {
-                       case GenTables:
-                               codeGen = new DTabCodeGen(out);
-                               break;
-                       case GenFTables:
-                               codeGen = new DFTabCodeGen(out);
-                               break;
-                       case GenFlat:
-                               codeGen = new DFlatCodeGen(out);
-                               break;
-                       case GenFFlat:
-                               codeGen = new DFFlatCodeGen(out);
-                               break;
-                       case GenGoto:
-                               codeGen = new DGotoCodeGen(out);
-                               break;
-                       case GenFGoto:
-                               codeGen = new DFGotoCodeGen(out);
-                               break;
-                       case GenIpGoto:
-                               codeGen = new DIpGotoCodeGen(out);
-                               break;
-                       case GenSplit:
-                               codeGen = new DSplitCodeGen(out);
-                               break;
-                       }
+               case GenFTables:
+                       codeGen = new CFTabCodeGen(out);
+                       break;
+               case GenFlat:
+                       codeGen = new CFlatCodeGen(out);
+                       break;
+               case GenFFlat:
+                       codeGen = new CFFlatCodeGen(out);
+                       break;
+               case GenGoto:
+                       codeGen = new CGotoCodeGen(out);
+                       break;
+               case GenFGoto:
+                       codeGen = new CFGotoCodeGen(out);
+                       break;
+               case GenIpGoto:
+                       codeGen = new CIpGotoCodeGen(out);
                        break;
+               case GenSplit:
+                       codeGen = new CSplitCodeGen(out);
+                       break;
+               }
+               break;
 
-               default: break;
+       case DCode:
+               switch ( codeStyle ) {
+               case GenTables:
+                       codeGen = new DTabCodeGen(out);
+                       break;
+               case GenFTables:
+                       codeGen = new DFTabCodeGen(out);
+                       break;
+               case GenFlat:
+                       codeGen = new DFlatCodeGen(out);
+                       break;
+               case GenFFlat:
+                       codeGen = new DFFlatCodeGen(out);
+                       break;
+               case GenGoto:
+                       codeGen = new DGotoCodeGen(out);
+                       break;
+               case GenFGoto:
+                       codeGen = new DFGotoCodeGen(out);
+                       break;
+               case GenIpGoto:
+                       codeGen = new DIpGotoCodeGen(out);
+                       break;
+               case GenSplit:
+                       codeGen = new DSplitCodeGen(out);
+                       break;
                }
+               break;
+
+       default: break;
        }
 
        codeGen->sourceFileName = sourceFileName;
@@ -268,15 +256,6 @@ int main(int argc, char **argv)
                                }
                                break;
 
-                       /* Output formats. */
-                       case 'V':
-                               outputFormat = OutGraphvizDot;
-                               break;
-
-                       case 'p':
-                               printPrintables = true;
-                               break;
-
                        /* Code style. */
                        case 'T':
                                if ( pc.parameterArg[0] == '0' )
@@ -380,8 +359,8 @@ int main(int argc, char **argv)
        if ( gblErrorCount > 0 )
                exit(1);
 
-       bool wantComplete = outputFormat != OutGraphvizDot;
-       bool outputActive = outputFormat == OutCode;
+       bool wantComplete = true;
+       bool outputActive = true;
 
        /* Parse the input! */
        xml_parse( *inStream, xmlInputFileName, outputActive, wantComplete );
index 959b58a..1b7b85e 100644 (file)
 
 #define PROGNAME "rlcodegen"
 
-/* Target language. */
-enum OutputFormat
-{
-       OutCode,
-       OutGraphvizDot
-};
-
 /* Target output style. */
 enum CodeStyleEnum
 {
@@ -50,7 +43,6 @@ enum CodeStyleEnum
        GenSplit
 };
 
-extern OutputFormat outputFormat;
 extern CodeStyleEnum codeStyle;
 
 /* IO filenames and stream. */
diff --git a/rlgen-dot/Makefile.in b/rlgen-dot/Makefile.in
new file mode 100644 (file)
index 0000000..b79a2a5
--- /dev/null
@@ -0,0 +1,65 @@
+#
+#   Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
+#
+
+#   This file is part of Ragel.
+#
+#   Ragel is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   Ragel is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with Ragel; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+
+INCS += -I../common -I../redfsm -I../aapl
+DEFS +=
+
+CFLAGS += -g -Wall
+LDFLAGS +=
+
+CC_SRCS = main.cpp gvdotgen.cpp 
+
+LIBS = ../common/common.a ../redfsm/redfsm.a
+
+PREFIX += @prefix@
+
+#*************************************
+
+# Programs
+CXX = @CXX@
+
+# Get objects and dependencies from sources.
+OBJS = $(CC_SRCS:%.cpp=%.o)
+DEPS = $(CC_SRCS:%.cpp=.%.d)
+
+# Get the version info.
+include ../version.mk
+
+# Rules.
+all: rlgen-dot
+
+rlgen-dot: $(LIBS) $(OBJS)
+       $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+%.o: %.cpp
+       @$(CXX) -M $(DEFS) $(INCS) $< > .$*.d
+       $(CXX) -c $(CFLAGS) $(DEFS) $(INCS) -o $@ $<
+
+distclean: clean
+       rm -f Makefile
+
+clean:
+       rm -f tags .*.d *.o rlgen-dot $(EXTRA_CLEAN)
+
+install: all
+       install -d $(PREFIX)/bin
+       install -s rlgen-dot $(PREFIX)/bin/rlgen-dot
+
+-include $(DEPS)
similarity index 97%
rename from rlcodegen/gvdotgen.cpp
rename to rlgen-dot/gvdotgen.cpp
index 3be8626..85b0259 100644 (file)
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  */
 
-
-#include "rlcodegen.h"
+#include "rlgen-dot.h"
 #include "gvdotgen.h"
 #include "gendata.h"
 
 using namespace std;
 
+void lineDirective( ostream &out, char *fileName, int line )
+{
+}
+
+void genLineDirective( ostream &out )
+{
+}
+
 std::ostream &GraphvizDotGen::KEY( Key key )
 {
-       if ( printPrintables && key.isPrintable() ) {
+       if ( displayPrintables && key.isPrintable() ) {
                // Output values as characters, ensuring we escape the quote (") character
                char cVal = (char) key.getVal();
                switch ( cVal ) {
@@ -294,7 +301,6 @@ void GraphvizDotGen::writeDotFile( )
 
 void GraphvizDotGen::finishRagelDef()
 {
-       assert( outputFormat == OutGraphvizDot );
        if ( !graphvizDone ) {
                graphvizDone = true;
 
similarity index 100%
rename from rlcodegen/gvdotgen.h
rename to rlgen-dot/gvdotgen.h
diff --git a/rlgen-dot/main.cpp b/rlgen-dot/main.cpp
new file mode 100644 (file)
index 0000000..5f816ae
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ *  Copyright 2001-2005 Adrian Thurston <thurston@cs.queensu.ca>
+ */
+
+/*  This file is part of Ragel.
+ *
+ *  Ragel is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ * 
+ *  Ragel is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with Ragel; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+
+#include "common.h"
+#include "rlgen-dot.h"
+#include "xmlparse.h"
+#include "pcheck.h"
+#include "vector.h"
+#include "version.h"
+#include "gvdotgen.h"
+
+using std::istream;
+using std::ifstream;
+using std::ostream;
+using std::ios;
+using std::cin;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* Io globals. */
+istream *inStream = 0;
+ostream *outStream = 0;
+output_filter *outFilter = 0;
+char *outputFileName = 0;
+
+/* Graphviz dot file generation. */
+bool graphvizDone = false;
+
+int numSplitPartitions = 0;
+bool displayPrintables = false;
+
+/* Print a summary of the options. */
+void usage()
+{
+       cout <<
+"usage: " PROGNAME " [options] file\n"
+"general:\n"
+"   -h, -H, -?, --help    Print this usage and exit\n"
+"   -v, --version         Print version information and exit\n"
+"   -o <file>             Write output to <file>\n"
+"output:\n"
+"   -p                    Display printable characters on labels\n"
+       ;       
+}
+
+/* Print version information. */
+void version()
+{
+       cout << "Ragel interface to Graphviz Dotfiles" << endl <<
+                       "Version " VERSION << ", " PUBDATE << endl <<
+                       "Copyright (c) 2001-2007 by Adrian Thurston" << endl;
+}
+
+/* Total error count. */
+int gblErrorCount = 0;
+
+ostream &error()
+{
+       gblErrorCount += 1;
+       cerr << PROGNAME ": ";
+       return cerr;
+}
+
+/*
+ * Callbacks invoked by the XML data parser.
+ */
+
+/* Invoked by the parser when the root element is opened. */
+ostream *openOutput( char *inputFile )
+{
+       /* Make sure we are not writing to the same file as the input file. */
+       if ( outputFileName != 0 && strcmp( inputFile, outputFileName  ) == 0 ) {
+               error() << "output file \"" << outputFileName  << 
+                               "\" is the same as the input file" << endl;
+       }
+
+       if ( outputFileName != 0 ) {
+               /* Create the filter on the output and open it. */
+               outFilter = new output_filter( outputFileName );
+               outFilter->open( outputFileName, ios::out|ios::trunc );
+               if ( !outFilter->is_open() ) {
+                       error() << "error opening " << outputFileName << " for writing" << endl;
+                       exit(1);
+               }
+
+               /* Open the output stream, attaching it to the filter. */
+               outStream = new ostream( outFilter );
+       }
+       else {
+               /* Writing out ot std out. */
+               outStream = &cout;
+       }
+       return outStream;
+}
+
+/* Invoked by the parser when a ragel definition is opened. */
+CodeGenData *makeCodeGen( char *sourceFileName, char *fsmName, 
+               ostream &out, bool wantComplete )
+{
+       CodeGenData *codeGen = new GraphvizDotGen(out);
+
+       codeGen->sourceFileName = sourceFileName;
+       codeGen->fsmName = fsmName;
+       codeGen->wantComplete = wantComplete;
+
+       return codeGen;
+}
+
+
+/* Main, process args and call yyparse to start scanning input. */
+int main(int argc, char **argv)
+{
+       ParamCheck pc("o:pvHh?-:", argc, argv);
+       char *xmlInputFileName = 0;
+
+       while ( pc.check() ) {
+               switch ( pc.state ) {
+               case ParamCheck::match:
+                       switch ( pc.parameter ) {
+                       /* Output. */
+                       case 'o':
+                               if ( *pc.parameterArg == 0 )
+                                       error() << "a zero length output file name was given" << endl;
+                               else if ( outputFileName != 0 )
+                                       error() << "more than one output file name was given" << endl;
+                               else {
+                                       /* Ok, remember the output file name. */
+                                       outputFileName = pc.parameterArg;
+                               }
+                               break;
+
+                       case 'p':
+                               displayPrintables = true;
+                               break;
+
+                       /* Version and help. */
+                       case 'v':
+                               version();
+                               exit(0);
+                       case 'H': case 'h': case '?':
+                               usage();
+                               exit(0);
+                       case '-':
+                               if ( strcasecmp(pc.parameterArg, "help") == 0 ) {
+                                       usage();
+                                       exit(0);
+                               }
+                               else if ( strcasecmp(pc.parameterArg, "version") == 0 ) {
+                                       version();
+                                       exit(0);
+                               }
+                               else {
+                                       error() << "--" << pc.parameterArg << 
+                                                       " is an invalid argument" << endl;
+                                       break;
+                               }
+                       }
+                       break;
+
+               case ParamCheck::invalid:
+                       error() << "-" << pc.parameter << " is an invalid argument" << endl;
+                       break;
+
+               case ParamCheck::noparam:
+                       if ( *pc.curArg == 0 )
+                               error() << "a zero length input file name was given" << endl;
+                       else if ( xmlInputFileName != 0 )
+                               error() << "more than one input file name was given" << endl;
+                       else {
+                               /* OK, Remember the filename. */
+                               xmlInputFileName = pc.curArg;
+                       }
+                       break;
+               }
+       }
+
+       /* Bail on above errors. */
+       if ( gblErrorCount > 0 )
+               exit(1);
+
+       /* Open the input file for reading. */
+       if ( xmlInputFileName != 0 ) {
+               /* Open the input file for reading. */
+               ifstream *inFile = new ifstream( xmlInputFileName );
+               inStream = inFile;
+               if ( ! inFile->is_open() )
+                       error() << "could not open " << xmlInputFileName << " for reading" << endl;
+       }
+       else {
+               xmlInputFileName = "<stdin>";
+               inStream = &cin;
+       }
+
+       /* Bail on above errors. */
+       if ( gblErrorCount > 0 )
+               exit(1);
+
+       bool wantComplete = false;
+       bool outputActive = false;
+
+       /* Parse the input! */
+       xml_parse( *inStream, xmlInputFileName, outputActive, wantComplete );
+
+       /* If writing to a file, delete the ostream, causing it to flush.
+        * Standard out is flushed automatically. */
+       if ( outputFileName != 0 ) {
+               delete outStream;
+               delete outFilter;
+       }
+
+       /* Finished, final check for errors.. */
+       if ( gblErrorCount > 0 ) {
+               /* If we opened an output file, remove it. */
+               if ( outputFileName != 0 )
+                       unlink( outputFileName );
+               exit(1);
+       }
+       return 0;
+}
diff --git a/rlgen-dot/rlgen-dot.h b/rlgen-dot/rlgen-dot.h
new file mode 100644 (file)
index 0000000..83152a5
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca>
+ */
+
+/*  This file is part of Ragel.
+ *
+ *  Ragel is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ * 
+ *  Ragel is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with Ragel; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+#ifndef _RLGENDOT
+#define _RLGENDOT
+
+#include <stdio.h>
+#include <iostream>
+#include "avltree.h"
+#include "vector.h"
+#include "config.h"
+
+#define PROGNAME "rlgen-dot"
+
+/* IO filenames and stream. */
+extern bool displayPrintables;
+extern bool graphvizDone;
+extern int gblErrorCount;
+
+std::ostream &error();
+
+#endif /* _RLGENDOT */