From 52e6bd3e02522f68166c70f83d2ef3d7cf0c15ff Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 12 Sep 2008 18:58:06 +0000 Subject: [PATCH] Add a compile mode to mspdatatool --- Build | 1 + tool/compiler.cpp | 179 ++++++++++++++++++++++++++++++++++++++++++++++ tool/compiler.h | 70 ++++++++++++++++++ tool/tool.cpp | 26 +++++-- tool/tool.h | 7 ++ 5 files changed, 276 insertions(+), 7 deletions(-) create mode 100644 tool/compiler.cpp create mode 100644 tool/compiler.h diff --git a/Build b/Build index 53a4ebd..faf77b6 100644 --- a/Build +++ b/Build @@ -21,6 +21,7 @@ package "mspdatafile" program "mspdatatool" { + require "mspfs"; source "tool"; install true; build_info diff --git a/tool/compiler.cpp b/tool/compiler.cpp new file mode 100644 index 0000000..53c1b53 --- /dev/null +++ b/tool/compiler.cpp @@ -0,0 +1,179 @@ +/* $Id$ + +This file is part of libmspdatafile +Copyright © 2008 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include +#include +#include "compiler.h" + +using namespace std; +using namespace Msp; + +Compiler::Compiler(DataFile::Writer &w): + writer(w) +{ + add("file", &Compiler::file); + add("for_each", &Compiler::for_each); + add("write", &Compiler::write); +} + +void Compiler::file(const string &fn) +{ + File fl(*this, FS::dirname(get_source())/fn); + load_sub_with(fl); +} + +void Compiler::for_each(const vector &patterns) +{ + ForEach fe(*this, FS::dirname(get_source()), list(patterns.begin(), patterns.end())); + load_sub_with(fe); +} + +void Compiler::write(const DataFile::Statement &st) +{ + for(list::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i) + writer.write(*i); +} + +bool Compiler::process_statement(const FS::Path &fn, DataFile::Statement &st) +{ + if(st.keyword=="_content") + return true; + + for(vector::iterator i=st.args.begin(); i!=st.args.end(); ++i) + if(i->get_type()==DataFile::STRING) + { + if(i->get_raw()=="$filename") + *i=DataFile::Value(FS::basename(fn.str())); + else if(i->get_raw()=="$content") + { + IO::File in(fn.str()); + string data; + while(!in.eof()) + { + char buf[4096]; + unsigned len=in.read(buf, sizeof(buf)); + data.append(buf, len); + } + *i=DataFile::Value(data); + } + } + + for(list::iterator i=st.sub.begin(); i!=st.sub.end();) + { + if(process_statement(fn, *i)) + { + IO::File in(fn.str()); + IO::Buffered buf(in); + + DataFile::Parser parser(in, fn.str()); + while(parser) + { + DataFile::Statement ss=parser.parse(); + if(ss.valid) + st.sub.insert(i, ss); + } + i=st.sub.erase(i); + } + else + ++i; + } + + return false; +} + +void Compiler::process_file(const FS::Path &fn, const list &st) +{ + for(list::const_iterator i=st.begin(); i!=st.end(); ++i) + { + if(i->keyword=="_content") + process_file(fn); + else + { + DataFile::Statement s=*i; + process_statement(fn, s); + writer.write(s); + } + } +} + +void Compiler::process_file(const FS::Path &fn) +{ + IO::File in(fn.str()); + IO::Buffered buf(in); + + DataFile::Parser parser(in, fn.str()); + while(parser) + { + DataFile::Statement st=parser.parse(); + if(st.valid) + writer.write(st); + } +} + + +File::File(Compiler &c, const FS::Path &fn): + compiler(c), + filename(fn) +{ + add("write", &File::write); +} + +void File::finish() +{ + if(write_st.empty()) + compiler.process_file(filename); + else + compiler.process_file(filename, write_st); +} + +void File::write(const DataFile::Statement &st) +{ + write_st.insert(write_st.end(), st.sub.begin(), st.sub.end()); +} + + +ForEach::ForEach(Compiler &c, const FS::Path &b, const list &p): + compiler(c), + base(b), + patterns(p) +{ + add("exclude", &ForEach::exclude); + add("pattern", &ForEach::pattern); + add("write", &ForEach::write); +} + +void ForEach::finish() +{ + list files=FS::list_files(base); + for(list::iterator i=files.begin(); i!=files.end(); ++i) + { + bool match=false; + for(list::const_iterator j=patterns.begin(); (j!=patterns.end() && !match); ++j) + match=Regex(*j).match(*i); + for(list::const_iterator j=excludes.begin(); (j!=excludes.end() && match); ++j) + match=!Regex(*j).match(*i); + if(match) + compiler.process_file(base / *i, write_st); + } +} + +void ForEach::exclude(const string &p) +{ + excludes.push_back(p); +} + +void ForEach::pattern(const string &p) +{ + patterns.push_back(p); +} + +void ForEach::write(const DataFile::Statement &st) +{ + write_st.insert(write_st.end(), st.sub.begin(), st.sub.end()); +} diff --git a/tool/compiler.h b/tool/compiler.h new file mode 100644 index 0000000..f77f04b --- /dev/null +++ b/tool/compiler.h @@ -0,0 +1,70 @@ +/* $Id$ + +This file is part of libmspdatafile +Copyright © 2008 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#ifndef TOOL_COMPILER_H_ +#define TOOL_COMPILER_H_ + +#include +#include +#include +#include + +class Compiler: public Msp::DataFile::Loader +{ + friend class File; + friend class ForEach; + +private: + Msp::DataFile::Writer &writer; + +public: + Compiler(Msp::DataFile::Writer &); +private: + void file(const std::string &); + void for_each(const std::vector &); + void write(const Msp::DataFile::Statement &); + + bool process_statement(const Msp::FS::Path &, Msp::DataFile::Statement &); + void process_file(const Msp::FS::Path &, const std::list &); + void process_file(const Msp::FS::Path &); +}; + +class File: public Msp::DataFile::Loader +{ +private: + Compiler &compiler; + Msp::FS::Path filename; + std::list write_st; + +public: + File(Compiler &, const Msp::FS::Path &); +private: + virtual void finish(); + + void write(const Msp::DataFile::Statement &); +}; + +class ForEach: public Msp::DataFile::Loader +{ +private: + Compiler &compiler; + Msp::FS::Path base; + std::list patterns; + std::list excludes; + std::list write_st; + +public: + ForEach(Compiler &, const Msp::FS::Path &, const std::list &); +private: + virtual void finish(); + + void exclude(const std::string &); + void pattern(const std::string &); + void write(const Msp::DataFile::Statement &); +}; + +#endif diff --git a/tool/tool.cpp b/tool/tool.cpp index ca415d3..36ee5c4 100644 --- a/tool/tool.cpp +++ b/tool/tool.cpp @@ -12,6 +12,7 @@ Distributed under the LGPL #include #include #include +#include "compiler.h" #include "tool.h" using namespace std; @@ -19,11 +20,14 @@ using namespace Msp; DataTool::DataTool(int argc, char **argv): in_fn("-"), - out_fn("-") + out_fn("-"), + binary(false), + compile(false) { GetOpt getopt; - getopt.add_option('o', "output", out_fn, GetOpt::REQUIRED_ARG); getopt.add_option('b', "binary", binary, GetOpt::NO_ARG); + getopt.add_option('c', "compile", compile, GetOpt::NO_ARG); + getopt.add_option('o', "output", out_fn, GetOpt::REQUIRED_ARG); getopt(argc, argv); const vector &args=getopt.get_args(); @@ -53,13 +57,21 @@ int DataTool::main() if(binary) writer.set_binary(true); - while(parser) + if(compile) + { + Compiler compiler(writer); + compiler.load(parser); + } + else { - DataFile::Statement st=parser.parse(); - if(st.valid) + while(parser) { - writer.write(st); - out_buf.flush(); + DataFile::Statement st=parser.parse(); + if(st.valid) + { + writer.write(st); + out_buf.flush(); + } } } } diff --git a/tool/tool.h b/tool/tool.h index 99e8297..ab399ad 100644 --- a/tool/tool.h +++ b/tool/tool.h @@ -5,6 +5,9 @@ Copyright © 2008 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ +#ifndef TOOL_H_ +#define TOOL_H_ + #include #include @@ -14,9 +17,13 @@ private: std::string in_fn; std::string out_fn; bool binary; + bool compile; + public: DataTool(int argc, char **argv); int main(); static Application::RegApp reg; }; + +#endif -- 2.45.2