]> git.tdb.fi Git - libs/datafile.git/blob - tool/compiler.cpp
ed5710b97d3bd8d3ffac53d88f4c41855b2866fd
[libs/datafile.git] / tool / compiler.cpp
1 /* $Id$
2
3 This file is part of libmspdatafile
4 Copyright © 2008  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/datafile/parser.h>
9 #include <msp/fs/dir.h>
10 #include <msp/fs/utils.h>
11 #include <msp/strings/regex.h>
12 #include "compiler.h"
13
14 using namespace std;
15 using namespace Msp;
16
17 Compiler::Compiler(DataFile::Writer &w):
18         writer(w),
19         reset_src(false)
20 {
21         add("file",     &Compiler::file);
22         add("for_each", &Compiler::for_each);
23         add("write",    &Compiler::write);
24 }
25
26 void Compiler::file(const string &fn)
27 {
28         File fl(*this, FS::dirname(get_source())/fn);
29         load_sub_with(fl);
30 }
31
32 void Compiler::for_each(const vector<string> &patterns)
33 {
34         ForEach fe(*this, FS::dirname(get_source()), list<string>(patterns.begin(), patterns.end()));
35         load_sub_with(fe);
36 }
37
38 void Compiler::write(const DataFile::Statement &st)
39 {
40         if(reset_src)
41         {
42                 writer.write((DataFile::Statement("__src"), string()));
43                 reset_src=false;
44         }
45
46         for(list<DataFile::Statement>::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i)
47                 writer.write(*i);
48 }
49
50 bool Compiler::process_statement(const FS::Path &fn, DataFile::Statement &st)
51 {
52         if(st.keyword=="_content")
53                 return true;
54
55         for(vector<DataFile::Value>::iterator i=st.args.begin(); i!=st.args.end(); ++i)
56                 if(i->get_type()==DataFile::STRING)
57                 {
58                         if(i->get_raw()=="$filename")
59                                 *i=DataFile::Value(FS::basename(fn.str()));
60                         else if(i->get_raw()=="$content")
61                         {
62                                 IO::File in(fn.str());
63                                 string data;
64                                 while(!in.eof())
65                                 {
66                                         char buf[4096];
67                                         unsigned len=in.read(buf, sizeof(buf));
68                                         data.append(buf, len);
69                                 }
70                                 *i=DataFile::Value(data);
71                         }
72                 }
73
74         for(list<DataFile::Statement>::iterator i=st.sub.begin(); i!=st.sub.end();)
75         {
76                 if(process_statement(fn, *i))
77                 {
78                         IO::File in(fn.str());
79                         IO::Buffered buf(in);
80
81                         DataFile::Parser parser(in, fn.str());
82                         while(parser)
83                         {
84                                 DataFile::Statement ss=parser.parse();
85                                 if(ss.valid)
86                                         st.sub.insert(i, ss);
87                         }
88                         i=st.sub.erase(i);
89                 }
90                 else
91                         ++i;
92         }
93
94         return false;
95 }
96
97 void Compiler::process_file(const FS::Path &fn, const list<DataFile::Statement> &st)
98 {
99         writer.write((DataFile::Statement("__src"), FS::basename(fn.str())));
100         reset_src=true;
101
102         if(st.empty())
103                 process_file(fn);
104         else
105         {
106                 for(list<DataFile::Statement>::const_iterator i=st.begin(); i!=st.end(); ++i)
107                 {
108                         if(i->keyword=="_content")
109                                 process_file(fn);
110                         else
111                         {
112                                 DataFile::Statement s=*i;
113                                 process_statement(fn, s);
114                                 writer.write(s);
115                         }
116                 }
117         }
118 }
119
120 void Compiler::process_file(const FS::Path &fn)
121 {
122         IO::File in(fn.str());
123         IO::Buffered buf(in);
124
125         DataFile::Parser parser(in, fn.str());
126         while(parser)
127         {
128                 DataFile::Statement st=parser.parse();
129                 if(st.valid)
130                         writer.write(st);
131         }
132 }
133
134
135 File::File(Compiler &c, const FS::Path &fn):
136         compiler(c),
137         filename(fn)
138 {
139         add("write", &File::write);
140 }
141
142 void File::finish()
143 {
144         compiler.process_file(filename, write_st);
145 }
146
147 void File::write(const DataFile::Statement &st)
148 {
149         write_st.insert(write_st.end(), st.sub.begin(), st.sub.end());
150 }
151
152
153 ForEach::ForEach(Compiler &c, const FS::Path &b, const list<string> &p):
154         compiler(c),
155         base(b),
156         patterns(p)
157 {
158         add("exclude", &ForEach::exclude);
159         add("pattern", &ForEach::pattern);
160         add("write",   &ForEach::write);
161 }
162
163 void ForEach::finish()
164 {
165         list<string> files=FS::list_files(base);
166         for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
167         {
168                 bool match=false;
169                 for(list<string>::const_iterator j=patterns.begin(); (j!=patterns.end() && !match); ++j)
170                         match=Regex(*j).match(*i);
171                 for(list<string>::const_iterator j=excludes.begin(); (j!=excludes.end() && match); ++j)
172                         match=!Regex(*j).match(*i);
173                 if(match)
174                         compiler.process_file(base / *i, write_st);
175         }
176 }
177
178 void ForEach::exclude(const string &p)
179 {
180         excludes.push_back(p);
181 }
182
183 void ForEach::pattern(const string &p)
184 {
185         patterns.push_back(p);
186 }
187
188 void ForEach::write(const DataFile::Statement &st)
189 {
190         write_st.insert(write_st.end(), st.sub.begin(), st.sub.end());
191 }