--- /dev/null
+/* $Id$
+
+This file is part of libmspdatafile
+Copyright © 2008 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/datafile/parser.h>
+#include <msp/fs/dir.h>
+#include <msp/fs/utils.h>
+#include <msp/strings/regex.h>
+#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<string> &patterns)
+{
+ ForEach fe(*this, FS::dirname(get_source()), list<string>(patterns.begin(), patterns.end()));
+ load_sub_with(fe);
+}
+
+void Compiler::write(const DataFile::Statement &st)
+{
+ for(list<DataFile::Statement>::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<DataFile::Value>::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<DataFile::Statement>::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<DataFile::Statement> &st)
+{
+ for(list<DataFile::Statement>::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<string> &p):
+ compiler(c),
+ base(b),
+ patterns(p)
+{
+ add("exclude", &ForEach::exclude);
+ add("pattern", &ForEach::pattern);
+ add("write", &ForEach::write);
+}
+
+void ForEach::finish()
+{
+ list<string> files=FS::list_files(base);
+ for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
+ {
+ bool match=false;
+ for(list<string>::const_iterator j=patterns.begin(); (j!=patterns.end() && !match); ++j)
+ match=Regex(*j).match(*i);
+ for(list<string>::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());
+}
--- /dev/null
+/* $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 <msp/datafile/loader.h>
+#include <msp/datafile/statement.h>
+#include <msp/datafile/writer.h>
+#include <msp/fs/path.h>
+
+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<std::string> &);
+ 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<Msp::DataFile::Statement> &);
+ void process_file(const Msp::FS::Path &);
+};
+
+class File: public Msp::DataFile::Loader
+{
+private:
+ Compiler &compiler;
+ Msp::FS::Path filename;
+ std::list<Msp::DataFile::Statement> 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<std::string> patterns;
+ std::list<std::string> excludes;
+ std::list<Msp::DataFile::Statement> write_st;
+
+public:
+ ForEach(Compiler &, const Msp::FS::Path &, const std::list<std::string> &);
+private:
+ virtual void finish();
+
+ void exclude(const std::string &);
+ void pattern(const std::string &);
+ void write(const Msp::DataFile::Statement &);
+};
+
+#endif
#include <msp/datafile/parser.h>
#include <msp/datafile/statement.h>
#include <msp/datafile/writer.h>
+#include "compiler.h"
#include "tool.h"
using namespace std;
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<string> &args=getopt.get_args();
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();
+ }
}
}
}