author | Michael Krelin <hacker@klever.net> | 2005-03-30 15:50:28 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2005-03-30 15:50:28 (UTC) |
commit | 3ddbfeafde93d1aab16a710498d86eef4e787406 (patch) (unidiff) | |
tree | d53ef21cf3b2bddfeb957c98344d0be8759ed555 /lib/sitecing_enflesher.ll | |
parent | 642dc685bd0a3f1526e22827a4539aa0e06aeff7 (diff) | |
download | sitecing-3ddbfeafde93d1aab16a710498d86eef4e787406.zip sitecing-3ddbfeafde93d1aab16a710498d86eef4e787406.tar.gz sitecing-3ddbfeafde93d1aab16a710498d86eef4e787406.tar.bz2 |
1. preprocessor doesn't touch unchanged files anymore
2. doublechedk on whether file is up to date when making
3. changed the way preprocessor targets depend on the timestamp file
4. a bugfix in strip_suffix/strip_prefix
-rw-r--r-- | lib/sitecing_enflesher.ll | 76 |
1 files changed, 64 insertions, 12 deletions
diff --git a/lib/sitecing_enflesher.ll b/lib/sitecing_enflesher.ll index 5f631d7..46489c7 100644 --- a/lib/sitecing_enflesher.ll +++ b/lib/sitecing_enflesher.ll | |||
@@ -1,91 +1,81 @@ | |||
1 | %{ | 1 | %{ |
2 | #include <iostream> | 2 | #include <iostream> |
3 | #include <fstream> | 3 | #include <fstream> |
4 | #include <cassert> | 4 | #include <cassert> |
5 | #include <stdexcept> | 5 | #include <stdexcept> |
6 | using namespace std; | 6 | using namespace std; |
7 | #include "sitecing/sitecing_exception.h" | 7 | #include "sitecing/sitecing_exception.h" |
8 | using namespace sitecing; | 8 | using namespace sitecing; |
9 | #define sitecing_enflesher_flexlexer_once | 9 | #define sitecing_enflesher_flexlexer_once |
10 | #include "sitecing/sitecing_enflesher.h" | 10 | #include "sitecing/sitecing_enflesher.h" |
11 | #include "sitecing/sitecing_parser.h" | 11 | #include "sitecing/sitecing_parser.h" |
12 | #undef yyFlexLexer | 12 | #undef yyFlexLexer |
13 | #define yyFlexLexer sitecing_enflesherFlexLexer | 13 | #define yyFlexLexer sitecing_enflesherFlexLexer |
14 | %} | 14 | %} |
15 | %option 8bit c++ verbose noyywrap yyclass="sitecing_enflesher" yylineno prefix="sitecing_enflesher" stack debug | 15 | %option 8bit c++ verbose noyywrap yyclass="sitecing_enflesher" yylineno prefix="sitecing_enflesher" stack debug |
16 | 16 | ||
17 | ID[A-Za-z_][A-Za-z0-9_]* | 17 | ID[A-Za-z_][A-Za-z0-9_]* |
18 | 18 | ||
19 | %% | 19 | %% |
20 | 20 | ||
21 | ^\%\%\#[^\n]+\n{ | 21 | ^\%\%\#[^\n]+\n{ |
22 | string line = yytext; | 22 | string line = yytext; |
23 | line.erase(0,3); | 23 | line.erase(0,3); |
24 | line.erase(line.length()-1); | 24 | line.erase(line.length()-1); |
25 | outs.flush(); | 25 | outs_open(parser.output_basename+line); |
26 | outs.close(); | ||
27 | outs.clear(); | ||
28 | outs.open((parser.output_basename+line).c_str(),ios::trunc); | ||
29 | if(!outs.good()) | ||
30 | throw preprocessor_error(CODEPOINT,"failed to write preprocessor output"); | ||
31 | anchor(); | 26 | anchor(); |
32 | anchoraged = true; | 27 | anchoraged = true; |
33 | } | 28 | } |
34 | ^\%\%[^\n]+\n{ | 29 | ^\%\%[^\n]+\n{ |
35 | string line = yytext; | 30 | string line = yytext; |
36 | line.erase(0,2); | 31 | line.erase(0,2); |
37 | line.erase(line.length()-1); | 32 | line.erase(line.length()-1); |
38 | outs.flush(); | 33 | outs_open(parser.output_basename+line); |
39 | outs.close(); | ||
40 | outs.clear(); | ||
41 | outs.open((parser.output_basename+line).c_str(),ios::trunc); | ||
42 | if(!outs.good()) | ||
43 | throw preprocessor_error(CODEPOINT,"failed to write preprocessor output"); | ||
44 | anchoraged = false; | 34 | anchoraged = false; |
45 | } | 35 | } |
46 | 36 | ||
47 | \<\%component_basename\%\>outs << parser.component_basename; anchor_time = true; | 37 | \<\%component_basename\%\>outs << parser.component_basename; anchor_time = true; |
48 | \<\%impl\%\> outs << parser.impl; anchor_time = true; | 38 | \<\%impl\%\> outs << parser.impl; anchor_time = true; |
49 | \<\%member_functions:impl\%\>{ | 39 | \<\%member_functions:impl\%\>{ |
50 | for(sitecing_parser::member_functions_t::const_iterator i=parser.member_functions.begin();i!=parser.member_functions.end();i++) { | 40 | for(sitecing_parser::member_functions_t::const_iterator i=parser.member_functions.begin();i!=parser.member_functions.end();i++) { |
51 | outs << i->type << " " << parser.class_name << "::"; | 41 | outs << i->type << " " << parser.class_name << "::"; |
52 | if(i->name.empty()) { | 42 | if(i->name.empty()) { |
53 | outs << parser.class_name << "()"; | 43 | outs << parser.class_name << "()"; |
54 | bool first = true; | 44 | bool first = true; |
55 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { | 45 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { |
56 | if(i->initializer.empty()) | 46 | if(i->initializer.empty()) |
57 | continue; | 47 | continue; |
58 | if(first) { | 48 | if(first) { |
59 | outs << ":"; | 49 | outs << ":"; |
60 | first=false; | 50 | first=false; |
61 | }else{ | 51 | }else{ |
62 | outs << ","; | 52 | outs << ","; |
63 | } | 53 | } |
64 | if(i->bComponent) { | 54 | if(i->bComponent) { |
65 | outs << i->name << "(NULL)"; | 55 | outs << i->name << "(NULL)"; |
66 | }else { | 56 | }else { |
67 | outs << i->name << "(" << i->initializer << ")"; | 57 | outs << i->name << "(" << i->initializer << ")"; |
68 | } | 58 | } |
69 | } | 59 | } |
70 | }else if(i->name == "~") | 60 | }else if(i->name == "~") |
71 | outs << "~" << parser.class_name << "()"; | 61 | outs << "~" << parser.class_name << "()"; |
72 | else | 62 | else |
73 | outs << i->name << i->args; | 63 | outs << i->name << i->args; |
74 | outs << "{\n" << i->body << "\n}\n"; | 64 | outs << "{\n" << i->body << "\n}\n"; |
75 | } | 65 | } |
76 | anchor_time = true; | 66 | anchor_time = true; |
77 | } | 67 | } |
78 | \<\%class_name\%\> outs << parser.class_name; anchor_time = true; | 68 | \<\%class_name\%\> outs << parser.class_name; anchor_time = true; |
79 | \<\%baseclass_header\%\>outs << parser.base_header; anchor_time = true; | 69 | \<\%baseclass_header\%\>outs << parser.base_header; anchor_time = true; |
80 | \<\%decl\%\> outs << parser.decl; anchor_time = true; | 70 | \<\%decl\%\> outs << parser.decl; anchor_time = true; |
81 | \<\%baseclass_name\%\> outs << parser.base_class; anchor_time = true; | 71 | \<\%baseclass_name\%\> outs << parser.base_class; anchor_time = true; |
82 | \<\%member_variables:decl\%\>{ | 72 | \<\%member_variables:decl\%\>{ |
83 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { | 73 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { |
84 | if(i->bComponent) { | 74 | if(i->bComponent) { |
85 | if(i->type.empty()) { | 75 | if(i->type.empty()) { |
86 | i->type = parser.factory.get_classname(i->initializer); | 76 | i->type = parser.factory.get_classname(i->initializer); |
87 | } | 77 | } |
88 | if(i->bTypeOnly) { | 78 | if(i->bTypeOnly) { |
89 | outs << "typedef " << i->type << " " << i->name << ";\n"; | 79 | outs << "typedef " << i->type << " " << i->name << ";\n"; |
90 | }else{ | 80 | }else{ |
91 | outs << "typedef " << i->type << " __type_" << i->name << ";\nsitecing::so_component __soc_" << i->name << ";\n__type_" << i->name << " *" << i->name << ";\n"; | 81 | outs << "typedef " << i->type << " __type_" << i->name << ";\nsitecing::so_component __soc_" << i->name << ";\n__type_" << i->name << " *" << i->name << ";\n"; |
@@ -152,51 +142,113 @@ ID [A-Za-z_][A-Za-z0-9_]* | |||
152 | } | 142 | } |
153 | anchor_time = true; | 143 | anchor_time = true; |
154 | } | 144 | } |
155 | \<\%ancestors:base_clause_part\%\>{ | 145 | \<\%ancestors:base_clause_part\%\>{ |
156 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { | 146 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { |
157 | outs << ", virtual public " << parser.factory.get_classname(i->path); | 147 | outs << ", virtual public " << parser.factory.get_classname(i->path); |
158 | } | 148 | } |
159 | } | 149 | } |
160 | \<\%ancestors:typedefs\%\> { | 150 | \<\%ancestors:typedefs\%\> { |
161 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { | 151 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { |
162 | outs << "typedef class " << parser.factory.get_classname(i->path) << " " << i->name << ";\n"; | 152 | outs << "typedef class " << parser.factory.get_classname(i->path) << " " << i->name << ";\n"; |
163 | } | 153 | } |
164 | anchor_time = true; | 154 | anchor_time = true; |
165 | } | 155 | } |
166 | \<\%ancestors:import\%\> { | 156 | \<\%ancestors:import\%\> { |
167 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { | 157 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { |
168 | outs << i->name << "::__do_imports();\n"; | 158 | outs << i->name << "::__do_imports();\n"; |
169 | } | 159 | } |
170 | anchor_time = true; | 160 | anchor_time = true; |
171 | } | 161 | } |
172 | 162 | ||
173 | \n { | 163 | \n { |
174 | if(anchor_time) | 164 | if(anchor_time) |
175 | anchor(); | 165 | anchor(); |
176 | ECHO; | 166 | ECHO; |
177 | } | 167 | } |
178 | . ECHO; | 168 | . ECHO; |
179 | 169 | ||
180 | %% | 170 | %% |
181 | 171 | ||
182 | void sitecing_enflesher::LexerOutput(const char *buf,int size) { | 172 | void sitecing_enflesher::LexerOutput(const char *buf,int size) { |
183 | outs.write(buf,size); | 173 | outs.write(buf,size); |
184 | } | 174 | } |
185 | 175 | ||
186 | void sitecing_enflesher::enflesh() { | 176 | void sitecing_enflesher::enflesh() { |
187 | ifstream ifs(parser.skeleton.c_str()); | 177 | ifstream ifs(parser.skeleton.c_str()); |
188 | if(!ifs.good()) | 178 | if(!ifs.good()) |
189 | throw preprocessor_error(CODEPOINT,"failed to open skeleton file"); | 179 | throw preprocessor_error(CODEPOINT,"failed to open skeleton file"); |
190 | switch_streams(&ifs,NULL); | 180 | switch_streams(&ifs,NULL); |
191 | yylex(); | 181 | yylex(); |
192 | } | 182 | } |
193 | 183 | ||
194 | void sitecing_enflesher::anchor() { | 184 | void sitecing_enflesher::anchor() { |
195 | if(!anchoraged) | 185 | if(!anchoraged) |
196 | return; | 186 | return; |
197 | outs << "\n#line " << lineno() << " \"" << parser.skeleton << "\"\n"; | 187 | outs << "\n#line " << lineno() << " \"" << parser.skeleton << "\"\n"; |
198 | anchor_time = false; | 188 | anchor_time = false; |
199 | } | 189 | } |
190 | |||
191 | void sitecing_enflesher::outs_open(const string& nfile) { | ||
192 | if(!outs_filename.empty()) { | ||
193 | outs.flush(); | ||
194 | outs.close(); | ||
195 | outs.clear(); | ||
196 | /* | ||
197 | * compare source and destination files. | ||
198 | * | ||
199 | * one can also keep a hash for the old one and compute one for the | ||
200 | * output while writing, but I'm not sure if it's any better. Surely a | ||
201 | * bit less accurate, unless we're going to compare it in case of | ||
202 | * difference, anyway. | ||
203 | */ | ||
204 | bool overwrite = false; | ||
205 | struct stat st_s, st_d; | ||
206 | string fn_s = outs_filename+".new"; | ||
207 | string fn_d = outs_filename; | ||
208 | if(stat(fn_d.c_str(),&st_d)) { | ||
209 | overwrite = true; | ||
210 | }else{ | ||
211 | if(stat(fn_s.c_str(),&st_s)) | ||
212 | throw preprocessor_error(CODEPOINT,"failed to stat() supposedly created file"); | ||
213 | if(st_s.st_size!=st_d.st_size) { | ||
214 | overwrite = true; | ||
215 | }else{ | ||
216 | ifstream i_s(fn_s.c_str(),ios::in); | ||
217 | if(!i_s) | ||
218 | throw preprocessor_error(CODEPOINT,"failed to open supposedly created file"); | ||
219 | ifstream i_d(fn_d.c_str(),ios::in); | ||
220 | if(!i_d) | ||
221 | throw preprocessor_error(CODEPOINT,"failed to open the old preprocessed source"); | ||
222 | off_t remaining = st_s.st_size; | ||
223 | char t1[2048]; | ||
224 | char t2[sizeof(t1)]; | ||
225 | while(remaining) { | ||
226 | int rb = remaining; | ||
227 | if(rb>sizeof(t1)) | ||
228 | rb = sizeof(t1); | ||
229 | if(i_s.read(t1,rb).gcount()!=rb) | ||
230 | throw preprocessor_error(CODEPOINT,"error reading just created file"); | ||
231 | if(i_d.read(t2,rb).gcount()!=rb) | ||
232 | throw preprocessor_error(CODEPOINT,"error reading the old preprocessed source"); | ||
233 | if(memcmp(t1,t2,rb)) { | ||
234 | overwrite = true; | ||
235 | break; | ||
236 | } | ||
237 | remaining -= rb; | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | if(overwrite) { | ||
242 | cerr << "renaming '" << fn_s << "'" << endl; | ||
243 | if(rename(fn_s.c_str(),fn_d.c_str())) | ||
244 | throw preprocessor_error(CODEPOINT,"failed to rename() generated output"); | ||
245 | } | ||
246 | } | ||
247 | outs_filename = nfile; | ||
248 | outs.open((nfile+".new").c_str(),ios::trunc); | ||
249 | if(!outs.good()) | ||
250 | throw preprocessor_error(CODEPOINT,"failed to write preprocessor output"); | ||
251 | } | ||
200 | /* | 252 | /* |
201 | * vim:set ft=lex: | 253 | * vim:set ft=lex: |
202 | */ | 254 | */ |