-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,202 +1,254 @@ | |||
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"; |
92 | } | 82 | } |
93 | }else{ | 83 | }else{ |
94 | outs << i->type << " " << i->name << ";\n"; | 84 | outs << i->type << " " << i->name << ";\n"; |
95 | } | 85 | } |
96 | } | 86 | } |
97 | anchor_time = true; | 87 | anchor_time = true; |
98 | } | 88 | } |
99 | \<\%member_functions:decl\%\>{ | 89 | \<\%member_functions:decl\%\>{ |
100 | for(sitecing_parser::member_functions_t::const_iterator i=parser.member_functions.begin();i!=parser.member_functions.end();i++) { | 90 | for(sitecing_parser::member_functions_t::const_iterator i=parser.member_functions.begin();i!=parser.member_functions.end();i++) { |
101 | (i->name.empty()?outs:outs << "virtual ") | 91 | (i->name.empty()?outs:outs << "virtual ") |
102 | << i->type << " "; | 92 | << i->type << " "; |
103 | if(i->name.empty()) { | 93 | if(i->name.empty()) { |
104 | outs << parser.class_name << "()"; | 94 | outs << parser.class_name << "()"; |
105 | }else if(i->name == "~") | 95 | }else if(i->name == "~") |
106 | outs << "~" << parser.class_name << "()"; | 96 | outs << "~" << parser.class_name << "()"; |
107 | else | 97 | else |
108 | outs << i->name << i->args; | 98 | outs << i->name << i->args; |
109 | outs << ";\n"; | 99 | outs << ";\n"; |
110 | } | 100 | } |
111 | anchor_time = true; | 101 | anchor_time = true; |
112 | } | 102 | } |
113 | \<\%imports:list\%\> { | 103 | \<\%imports:list\%\> { |
114 | for(sitecing_parser::member_variables_t::const_iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { | 104 | for(sitecing_parser::member_variables_t::const_iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { |
115 | if(i->bComponent) | 105 | if(i->bComponent) |
116 | outs << i->initializer << endl; | 106 | outs << i->initializer << endl; |
117 | } | 107 | } |
118 | anchor_time = true; | 108 | anchor_time = true; |
119 | } | 109 | } |
120 | \<\%imports:includes\%\>{ | 110 | \<\%imports:includes\%\>{ |
121 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { | 111 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { |
122 | if(i->bComponent) | 112 | if(i->bComponent) |
123 | outs << "\n#include \"" << i->initializer << ".h\"\n"; | 113 | outs << "\n#include \"" << i->initializer << ".h\"\n"; |
124 | } | 114 | } |
125 | anchor_time = true; | 115 | anchor_time = true; |
126 | } | 116 | } |
127 | \<\%imports:import\%\>{ | 117 | \<\%imports:import\%\>{ |
128 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { | 118 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { |
129 | if(!i->bComponent) | 119 | if(!i->bComponent) |
130 | continue; | 120 | continue; |
131 | if(i->bTypeOnly) | 121 | if(i->bTypeOnly) |
132 | continue; | 122 | continue; |
133 | outs << "__soc_" << i->name << "=__SCIF->ss->fetch(\"" << i->initializer << "\",__SCIF); " << i->name << "=static_cast<__type_" << i->name << "*>(__soc_" << i->name << ".ac->__the_most_derived_this());\n"; | 123 | outs << "__soc_" << i->name << "=__SCIF->ss->fetch(\"" << i->initializer << "\",__SCIF); " << i->name << "=static_cast<__type_" << i->name << "*>(__soc_" << i->name << ".ac->__the_most_derived_this());\n"; |
134 | } | 124 | } |
135 | anchor_time = true; | 125 | anchor_time = true; |
136 | } | 126 | } |
137 | 127 | ||
138 | \<\%base_component\%\> { | 128 | \<\%base_component\%\> { |
139 | // TODO: | 129 | // TODO: |
140 | anchor_time = true; | 130 | anchor_time = true; |
141 | } | 131 | } |
142 | 132 | ||
143 | \<\%ancestors:includes\%\>{ | 133 | \<\%ancestors:includes\%\>{ |
144 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { | 134 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { |
145 | outs << "#include \"" << i->path << ".h\"\n"; | 135 | outs << "#include \"" << i->path << ".h\"\n"; |
146 | } | 136 | } |
147 | anchor_time = true; | 137 | anchor_time = true; |
148 | } | 138 | } |
149 | \<\%ancestors:component_list\%\>{ | 139 | \<\%ancestors:component_list\%\>{ |
150 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { | 140 | for(sitecing_parser::ancestor_classes_t::const_iterator i=parser.ancestor_classes.begin();i!=parser.ancestor_classes.end();++i) { |
151 | outs << i->path << "\n"; | 141 | outs << i->path << "\n"; |
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 | */ |