]> granicus.if.org Git - re2c/commitdiff
Allow to override output and header filenames with configurations.
authorUlya Trofimovich <skvadrik@gmail.com>
Wed, 11 May 2016 10:17:49 +0000 (11:17 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Wed, 11 May 2016 10:17:49 +0000 (11:17 +0100)
19 files changed:
re2c/bootstrap/src/conf/parse_opts.cc
re2c/bootstrap/src/parse/lex_conf.cc
re2c/src/codegen/emit_dfa.cc
re2c/src/codegen/output.cc
re2c/src/codegen/output.h
re2c/src/conf/opt.cc
re2c/src/conf/opt.h
re2c/src/conf/parse_opts.re
re2c/src/ir/skeleton/generate_code.cc
re2c/src/ir/skeleton/generate_data.cc
re2c/src/ir/skeleton/skeleton.h
re2c/src/main.cc
re2c/src/parse/lex_conf.re
re2c/test/config/flags.c
re2c/test/config/flags.re
re2c/test/config/flags_output.c [new file with mode: 0644]
re2c/test/config/flags_output.re [new file with mode: 0644]
re2c/test/config/flags_type-header.c [new file with mode: 0644]
re2c/test/config/flags_type-header.re [new file with mode: 0644]

index 8134fe5b7dcb40bcebf74a6fb0bfac8118b09501..d891b503aad36ed6d857135ff7929043e66976e0 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.16 on Tue May 10 13:30:37 2016 */
+/* Generated by re2c 0.16 on Wed May 11 11:08:20 2016 */
 #line 1 "../src/conf/parse_opts.re"
 #include "src/codegen/input_api.h"
 #include "src/conf/msg.h"
@@ -2458,7 +2458,7 @@ yy604:
 yy605:
        ++YYCURSOR;
 #line 173 "../src/conf/parse_opts.re"
-       { if (!opts.output (*argv)) return EXIT_FAIL; goto opt; }
+       { opts.set_output_file(*argv); goto opt; }
 #line 2463 "src/conf/parse_opts.cc"
 yy607:
        ++YYCURSOR;
index 1656edd3bbd3e719124a02c1bbf4b9564612b61b..5908b28e13e0d7a81679ce3fec2f527a2ce047bd 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.16 on Tue May 10 16:46:34 2016 */
+/* Generated by re2c 0.16 on Wed May 11 11:08:20 2016 */
 #line 1 "../src/parse/lex_conf.re"
 #include "src/util/c99_stdint.h"
 #include <string>
@@ -651,7 +651,7 @@ yy114:
        if (yych == 'u') goto yy159;
 yy115:
 #line 68 "../src/parse/lex_conf.re"
-       { if (!opts.output(lex_conf_string())) exit(1); return; }
+       { opts.set_output_file(lex_conf_string()); return; }
 #line 656 "src/parse/lex_conf.cc"
 yy116:
        yyaccept = 8;
index 8d50dd47e86e99d3090043fe0fc77f014bde38df..84ef2af2a6af91c040b996b50be51dc7496afbdc 100644 (file)
@@ -180,7 +180,7 @@ void DFA::emit(Output & output, uint32_t& ind, bool isLastCond, bool& bPrologBra
        if (opts->target == opt_t::SKELETON) {
                if (output.skeletons.insert (name).second)
                {
-                       emit_data(*skeleton, o.file_name);
+                       emit_data(*skeleton);
                        emit_start(*skeleton, o, max_fill, need_backup, need_backupctx,
                                need_accept, basetag, tagnames);
                        uint32_t i = 2;
index b1cfbd7f890f23fb7675d6c253f6f8d97c44715f..b48e1d03d2c4dbafdfad0adaa1d5457ec62b3957 100644 (file)
@@ -5,6 +5,7 @@
 #include "src/codegen/indent.h"
 #include "src/codegen/output.h"
 #include "src/codegen/print.h"
+#include "src/conf/msg.h"
 #include "src/conf/opt.h"
 #include "src/conf/warn.h"
 #include "src/util/strrreplace.h"
@@ -61,10 +62,8 @@ OutputBlock::~OutputBlock ()
        }
 }
 
-OutputFile::OutputFile(const std::string &fn)
-       : file_name (fn)
-       , file (NULL)
-       , blocks ()
+OutputFile::OutputFile()
+       : blocks ()
        , label_counter ()
        , warn_condition_order (!opts->tFlag) // see note [condition order]
        , default_tags (true)
@@ -72,28 +71,9 @@ OutputFile::OutputFile(const std::string &fn)
        new_block ();
 }
 
-bool OutputFile::open ()
-{
-       if (file_name.empty())
-       {
-               file_name = "<stdout>";
-               file = stdout;
-       }
-       else
-       {
-               file = fopen (file_name.c_str(), "wb");
-       }
-       return file != NULL;
-}
-
 OutputFile::~OutputFile ()
 {
-       if (file != NULL && file != stdout)
-       {
-               fclose (file);
-       }
-       for (unsigned int i = 0; i < blocks.size (); ++i)
-       {
+       for (unsigned int i = 0; i < blocks.size(); ++i) {
                delete blocks[i];
        }
 }
@@ -289,116 +269,118 @@ void OutputFile::global_lists(
        }
 }
 
-void OutputFile::emit(
-       const uniq_vector_t<std::string> &global_types,
+bool OutputFile::emit(const uniq_vector_t<std::string> &global_types,
        const std::set<std::string> &global_tags,
        size_t max_fill)
 {
-       if (file != NULL)
-       {
-               unsigned int line_count = 1;
-               for (unsigned int j = 0; j < blocks.size (); ++j)
-               {
-                       OutputBlock & b = * blocks[j];
-                       for (unsigned int i = 0; i < b.fragments.size (); ++i)
-                       {
-                               OutputFragment & f = * b.fragments[i];
-                               switch (f.type)
-                               {
-                                       case OutputFragment::CODE:
-                                               break;
-                                       case OutputFragment::LINE_INFO:
-                                               output_line_info (f.stream, line_count + 1, file_name);
-                                               break;
-                                       case OutputFragment::STATE_GOTO:
-                                               output_state_goto (f.stream, f.indent, 0);
-                                               break;
-                                       case OutputFragment::TAGS:
-                                               if (f.tags) {
-                                                       output_tags(f.stream, *f.tags, global_tags);
-                                               } else if (default_tags) {
-                                                       output_tags_default(f.stream, f.indent, b.tags);
-                                               }
-                                               break;
-                                       case OutputFragment::TYPES:
-                                               output_types (f.stream, f.indent, global_types);
-                                               break;
-                                       case OutputFragment::WARN_CONDITION_ORDER:
-                                               if (warn_condition_order) // see note [condition order]
-                                               {
-                                                       warn.condition_order (b.line);
-                                               }
-                                               break;
-                                       case OutputFragment::YYACCEPT_INIT:
-                                               output_yyaccept_init (f.stream, f.indent, b.used_yyaccept);
-                                               break;
-                                       case OutputFragment::YYMAXFILL:
-                                               output_yymaxfill (f.stream, max_fill);
-                                               break;
-                               }
-                               std::string content = f.stream.str ();
-                               fwrite (content.c_str (), 1, content.size (), file);
-                               line_count += f.count_lines ();
+       FILE *file = NULL;
+       std::string filename = opts->output_file;
+       if (filename.empty()) {
+               filename = "<stdout>";
+               file = stdout;
+       } else {
+               file = fopen(filename.c_str(), "wb");
+               if (!file) {
+                       error("cannot open output file: %s", filename.c_str());
+                       return false;
+               }
+       }
+
+       unsigned int line_count = 1;
+       for (unsigned int j = 0; j < blocks.size(); ++j) {
+               OutputBlock & b = * blocks[j];
+               for (unsigned int i = 0; i < b.fragments.size(); ++i) {
+                       OutputFragment & f = * b.fragments[i];
+                       switch (f.type) {
+                               case OutputFragment::CODE: break;
+                               case OutputFragment::LINE_INFO:
+                                       output_line_info(f.stream, line_count + 1, filename);
+                                       break;
+                               case OutputFragment::STATE_GOTO:
+                                       output_state_goto(f.stream, f.indent, 0);
+                                       break;
+                               case OutputFragment::TAGS:
+                                       if (f.tags) {
+                                               output_tags(f.stream, *f.tags, global_tags);
+                                       } else if (default_tags) {
+                                               output_tags_default(f.stream, f.indent, b.tags);
+                                       }
+                                       break;
+                               case OutputFragment::TYPES:
+                                       output_types(f.stream, f.indent, global_types);
+                                       break;
+                               case OutputFragment::WARN_CONDITION_ORDER:
+                                       if (warn_condition_order) {// see note [condition order]
+                                               warn.condition_order (b.line);
+                                       }
+                                       break;
+                               case OutputFragment::YYACCEPT_INIT:
+                                       output_yyaccept_init(f.stream, f.indent, b.used_yyaccept);
+                                       break;
+                               case OutputFragment::YYMAXFILL:
+                                       output_yymaxfill(f.stream, max_fill);
+                                       break;
                        }
+                       std::string content = f.stream.str();
+                       fwrite(content.c_str(), 1, content.size(), file);
+                       line_count += f.count_lines();
                }
        }
+
+       fclose(file);
+       return true;
 }
 
-HeaderFile::HeaderFile(const std::string &fn)
-       : stream ()
-       // header is always generated, but not always dumped to file
-       // NULL filename crashes 'operator <<' on some platforms
-       // TODO: generate header only if necessary
-       , file_name (fn)
-       , file (NULL)
+bool HeaderFile::emit(const uniq_vector_t<std::string> &types)
 {
-       if (file_name.empty()) {
-               file_name = "<stdout>.h";
+       if (!opts->tFlag) {
+               return true;
        }
-}
 
-bool HeaderFile::open ()
-{
-       file = fopen (file_name.c_str(), "wb");
-       return file != NULL;
-}
+       FILE *file = NULL;
+       std::string filename = opts->header_file;
+       if (filename.empty()) {
+               filename = "<stdout>.h";
+               file = stdout;
+       } else {
+               file = fopen(filename.c_str(), "wb");
+               if (!file) {
+                       error("cannot open header file: %s", filename.c_str());
+                       return false;
+               }
+       }
 
-void HeaderFile::emit(const uniq_vector_t<std::string> &types)
-{
-       output_version_time (stream);
-       output_line_info (stream, 3, file_name);
+       output_version_time(stream);
+       output_line_info(stream, 3, filename);
        stream << "\n";
        output_types(stream, 0, types);
-}
 
-HeaderFile::~HeaderFile ()
-{
-       if (file != NULL)
-       {
-               std::string content = stream.str ();
-               fwrite (content.c_str (), 1, content.size (), file);
-               fclose (file);
-       }
+       std::string content = stream.str();
+       fwrite(content.c_str(), 1, content.size(), file);
+
+       fclose(file);
+       return true;
 }
 
-Output::Output(const std::string &source_name, const std::string &header_name)
-       : source(source_name)
-       , header(header_name)
+Output::Output()
+       : source()
+       , header()
        , skeletons()
        , max_fill(1)
 {}
 
-Output::~Output ()
+bool Output::emit()
 {
-       if (!warn.error ())
-       {
-               uniq_vector_t<std::string> types;
-               std::set<std::string> tags;
-               source.global_lists(types, tags);
-
-               source.emit(types, tags, max_fill);
-               header.emit(types);
+       if (warn.error()) {
+               return false;
        }
+
+       uniq_vector_t<std::string> types;
+       std::set<std::string> tags;
+       source.global_lists(types, tags);
+
+       return source.emit(types, tags, max_fill)
+               && header.emit(types);
 }
 
 void output_tags(std::ostream &o, const ConfTags &conf,
index 1a2fba0a910d6a674c69301da97a0a5c9dd8bb52..497f6313308da3c104bbd2e801664656ab33e6eb 100644 (file)
@@ -66,13 +66,8 @@ struct OutputBlock
        ~OutputBlock ();
 };
 
-struct OutputFile
+class OutputFile
 {
-public:
-       std::string file_name;
-
-private:
-       FILE * file;
        std::vector<OutputBlock *> blocks;
 
 public:
@@ -80,8 +75,8 @@ public:
        bool warn_condition_order;
        bool default_tags;
 
-       OutputFile(const std::string &fn);
-       ~OutputFile ();
+       OutputFile();
+       ~OutputFile();
 
        std::ostream & stream ();
        OutputBlock &block();
@@ -118,24 +113,19 @@ public:
        void global_lists(uniq_vector_t<std::string> &types,
                std::set<std::string> &tags) const;
 
-       void emit(const uniq_vector_t<std::string> &global_types,
+       bool emit(const uniq_vector_t<std::string> &global_types,
                const std::set<std::string> &global_tags, size_t max_fill);
 
        FORBID_COPY (OutputFile);
 };
 
-struct HeaderFile
+class HeaderFile
 {
-       HeaderFile(const std::string &fn);
-       ~HeaderFile ();
-       bool open ();
-       void emit(const uniq_vector_t<std::string> &types);
-
-private:
        std::ostringstream stream;
-       std::string file_name;
-       FILE * file;
 
+public:
+       HeaderFile(): stream() {}
+       bool emit(const uniq_vector_t<std::string> &types);
        FORBID_COPY (HeaderFile);
 };
 
@@ -146,8 +136,8 @@ struct Output
        std::set<std::string> skeletons;
        size_t max_fill;
 
-       Output(const std::string &source_name, const std::string &header_name);
-       ~Output ();
+       Output();
+       bool emit();
 };
 
 void output_tags(std::ostream &o, const ConfTags &conf,
index 946d3497f2445e2e758b96e09fe4fd88d646177f..ed8e6246ad1c99b6d1dc5674ab7f73d45d89c2fd 100644 (file)
@@ -292,20 +292,6 @@ bool Opt::source (const char *s)
        }
 }
 
-bool Opt::output (const std::string &s)
-{
-       if (!output_file.empty())
-       {
-               error ("multiple output files: %s, %s", output_file.c_str(), s.c_str());
-               return false;
-       }
-       else
-       {
-               output_file = s;
-               return true;
-       }
-}
-
 void Opt::reset_encoding (const Enc & enc)
 {
        useropt->encoding = enc;
index 667808352e4279ccae46d482f403078696649fdd..b4518b0190dd7eec279a6acaeb17ce3920388442 100644 (file)
@@ -17,6 +17,8 @@ namespace re2c
 #define RE2C_OPTS \
        /* target */ \
        OPT1 (opt_t::target_t, target, CODE) \
+       /* output file */ \
+       OPT (std::string, output_file, "") \
        /* fingerprint */ \
        OPT (bool, bNoGenerationDate, false) \
        OPT (bool, version, true) \
@@ -28,7 +30,7 @@ namespace re2c
        /* conditions */ \
        OPT (bool, cFlag, false) \
        OPT (bool, tFlag, false) \
-       OPT (std::string,  header_file, "") \
+       OPT (std::string, header_file, "") \
        OPT (std::string, yycondtype, "YYCONDTYPE") \
        OPT (std::string, cond_get, "YYGETCONDITION") \
        OPT (bool, cond_get_naked, false) \
@@ -157,7 +159,6 @@ struct Opt
        static const opt_t baseopt;
 
        const char *source_file;
-       std::string output_file;
 
 private:
        useropt_t useropt;
@@ -166,7 +167,6 @@ private:
 public:
        Opt ()
                : source_file (NULL)
-               , output_file ()
                , useropt ()
                , realopt (useropt)
        {}
@@ -178,7 +178,6 @@ public:
        }
 
        bool source (const char *s);
-       bool output (const std::string &s);
 
        // Inplace configurations are applied immediately when parsed.
        // This is very bad: first, re2c behaviour is changed in the middle
index ebc6f21499ce0b87d1dbfe3196f6b7448a3ba124..a8b2536e5dc65a832344a339a9e76d83f230876b 100644 (file)
@@ -170,7 +170,7 @@ opt_output:
                error ("bad argument to option -o, --output: %s", *argv);
                return EXIT_FAIL;
        }
-       filename end { if (!opts.output (*argv)) return EXIT_FAIL; goto opt; }
+       filename end { opts.set_output_file(*argv); goto opt; }
 */
 
 opt_header:
index b956b61bb8ba2dc4968b4800244ffcb0bbab95b5..3e4d87d6b03ac79e79cca06e216049b33823d3fe 100644 (file)
@@ -101,6 +101,10 @@ void emit_start(const Skeleton &skel, OutputFile &o, size_t maxfill,
                sizeof_key = skel.sizeof_key;
        const size_t norule = skel.rule2key(Rule::NONE);
        const std::string &name = skel.name;
+       std::string filename = opts->output_file;
+       if (filename.empty()) {
+               filename = "<stdout>";
+       }
 
        o.ws("\n#define YYCTYPE ");
        exact_uint (o, sizeof_cunit);
@@ -181,7 +185,7 @@ void emit_start(const Skeleton &skel, OutputFile &o, size_t maxfill,
        o.ws("\n").wind(1).ws("unsigned int i = 0;");
        o.ws("\n");
        o.ws("\n").wind(1).ws("input = (YYCTYPE *) read_file");
-       o.ws("\n").wind(2).ws("(\"").wstring(o.file_name).ws(".").wstring(name).ws(".input\"");
+       o.ws("\n").wind(2).ws("(\"").wstring(filename).ws(".").wstring(name).ws(".input\"");
        o.ws("\n").wind(2).ws(", sizeof (YYCTYPE)");
        o.ws("\n").wind(2).ws(", padding");
        o.ws("\n").wind(2).ws(", &input_len");
@@ -198,7 +202,7 @@ void emit_start(const Skeleton &skel, OutputFile &o, size_t maxfill,
                o.ws("\n");
        }
        o.ws("\n").wind(1).ws("keys = (YYKEYTYPE *) read_file");
-       o.ws("\n").wind(2).ws("(\"").wstring(o.file_name).ws(".").wstring(name).ws(".keys\"");
+       o.ws("\n").wind(2).ws("(\"").wstring(filename).ws(".").wstring(name).ws(".keys\"");
        o.ws("\n").wind(2).ws(", 3 * sizeof (YYKEYTYPE)");
        o.ws("\n").wind(2).ws(", 0");
        o.ws("\n").wind(2).ws(", &keys_count");
index b73f34d87e5f0745239817c367115350aec2f8e0..b417b0e6c530b5f713c0bb0c55c1b30a18ac49fc 100644 (file)
@@ -228,8 +228,13 @@ static void generate_paths(const Skeleton &skel, cover_t &cover)
        }
 }
 
-void emit_data(const Skeleton &skel, const std::string &fname)
+void emit_data(const Skeleton &skel)
 {
+       std::string fname = opts->output_file;
+       if (fname.empty()) {
+               fname = "<stdout>";
+       }
+
        const std::string input_name = fname + "." + skel.name + ".input";
        FILE *input = fopen(input_name.c_str(), "wb");
        if (!input) {
index ab51c28235eea60348e45d7af0743fd01ca4b284..1161011f6d88898a6b5355982585e7c524033652 100644 (file)
@@ -87,7 +87,7 @@ uint32_t maxpath(const Skeleton &skel);
 void warn_undefined_control_flow(const Skeleton &skel);
 void fprint_default_path(FILE *f, const Skeleton &skel, const path_t &p);
 void warn_unreachable_nullable_rules(const Skeleton &skel);
-void emit_data(const Skeleton &skel, const std::string &fname);
+void emit_data(const Skeleton &skel);
 void emit_prolog(OutputFile & o);
 void emit_start(const Skeleton &skel, OutputFile &o, size_t maxfill,
        bool backup, bool backupctx, bool accept, bool basetag,
index 6d1288b4f5e85abbd227dbfc654515e55e22c2ba..d69e708a01a16963f5c09f3de37cd6aab7eec435 100644 (file)
@@ -41,20 +41,13 @@ int main(int, char *argv[])
        }
 
        // set up the output streams
-       re2c::Output output (opts.output_file, opts->header_file);
-       if (!output.source.open ())
-       {
-               error ("cannot open output file: %s", opts.output_file.c_str());
-               return 1;
-       }
-       if (opts->tFlag && !output.header.open ())
-       {
-               error ("cannot open header file: %s", opts->header_file.c_str());
-               return 1;
-       }
+       re2c::Output output;
 
        Scanner scanner (input, output.source);
        parse (scanner, output);
+       if (!output.emit()) {
+               return 1;
+       }
 
        return warn.error () ? 1 : 0;
 }
index 093e3e3af20e9ceffa308df99f6bc6797c92c053..cffd556c52b1604a00e3c14f8a8f3aaaa0214f45 100644 (file)
@@ -65,7 +65,7 @@ void Scanner::lex_conf ()
        "flags:" ("x" | "utf-16")     { lex_conf_enc(Enc::UTF16);  return; }
        "flags:" ("8" | "utf-8")      { lex_conf_enc(Enc::UTF8);   return; }
 
-       "flags:" ("o" | "output")      { if (!opts.output(lex_conf_string())) exit(1); return; }
+       "flags:" ("o" | "output")      { opts.set_output_file(lex_conf_string()); return; }
        "flags:" ("t" | "type-header") { opts.set_header_file(lex_conf_string()); return; }
 
        "flags:encoding-policy"  { lex_conf_encoding_policy();  return; }
index b0d0e9d554bc548978638930fdea2caafd1903ba..c7248d924bd34b4ae7a3e178679bdb26f9d518a3 100644 (file)
@@ -1,5 +1,5 @@
 /* Generated by re2c */
-#line 1 "flags.re"
+#line 1 "config/flags.re"
 
 int main()
 {
index 67aec08a9c4d2c027a932e2333bbc0ff02517eb5..b8fdc5d098b32255e78c5cd27b41478849aa16eb 100644 (file)
     re2c:flags:8 = 1;
     re2c:flags:utf-8 = 0;
 
+    re2c:flags:o = "flags_x.c";
+    re2c:flags:output = "flags.c";
+    re2c:flags:t = "flags_x.h";
+    re2c:flags:type-header = "flags.h";
+
     re2c:flags:encoding-policy = ignore;
     re2c:flags:encoding-policy = substitute;
     re2c:flags:encoding-policy = fail;
diff --git a/re2c/test/config/flags_output.c b/re2c/test/config/flags_output.c
new file mode 100644 (file)
index 0000000..14a7c3c
--- /dev/null
@@ -0,0 +1,4 @@
+/* Generated by re2c */
+#line 1 "config/flags_output.re"
+#line 5 "config/flags_output.re"
+
diff --git a/re2c/test/config/flags_output.re b/re2c/test/config/flags_output.re
new file mode 100644 (file)
index 0000000..1e8f2c7
--- /dev/null
@@ -0,0 +1,5 @@
+/*!re2c
+    // 2nd configuration overrides 1st
+    re2c:flags:o = "flags_output_x.c";
+    re2c:flags:output = "flags_output.c";
+*/
diff --git a/re2c/test/config/flags_type-header.c b/re2c/test/config/flags_type-header.c
new file mode 100644 (file)
index 0000000..6e4b9b2
--- /dev/null
@@ -0,0 +1,9 @@
+/* Generated by re2c */
+#line 1 "config/flags_type-header.re"
+#line 6 "config/flags_type-header.re"
+
+/* Generated by re2c */
+#line 3 "flags_type-header.h"
+
+enum YYCONDTYPE {
+};
diff --git a/re2c/test/config/flags_type-header.re b/re2c/test/config/flags_type-header.re
new file mode 100644 (file)
index 0000000..a0956e8
--- /dev/null
@@ -0,0 +1,6 @@
+/*!re2c
+    // 2nd configuration overrides 1st
+    re2c:flags:t = "flags_type-header_x.h";
+    re2c:flags:type-header = "flags_type-header.h";
+    re2c:flags:c = 1;
+*/