summaryrefslogtreecommitdiffabout
path: root/lib/sitecing_enflesher.ll
authorMichael Krelin <hacker@klever.net>2005-03-30 15:50:28 (UTC)
committer Michael Krelin <hacker@klever.net>2005-03-30 15:50:28 (UTC)
commit3ddbfeafde93d1aab16a710498d86eef4e787406 (patch) (unidiff)
treed53ef21cf3b2bddfeb957c98344d0be8759ed555 /lib/sitecing_enflesher.ll
parent642dc685bd0a3f1526e22827a4539aa0e06aeff7 (diff)
downloadsitecing-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
Diffstat (limited to 'lib/sitecing_enflesher.ll') (more/less context) (show whitespace changes)
-rw-r--r--lib/sitecing_enflesher.ll76
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>
6using namespace std; 6using namespace std;
7#include "sitecing/sitecing_exception.h" 7#include "sitecing/sitecing_exception.h"
8using namespace sitecing; 8using 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
182void sitecing_enflesher::LexerOutput(const char *buf,int size) { 172void sitecing_enflesher::LexerOutput(const char *buf,int size) {
183 outs.write(buf,size); 173 outs.write(buf,size);
184} 174}
185 175
186void sitecing_enflesher::enflesh() { 176void 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
194void sitecing_enflesher::anchor() { 184void 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
191void 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 */