-rw-r--r-- | include/sitecing/sitecing_enflesher.h | 13 | ||||
-rw-r--r-- | lib/component_factory.cc | 19 | ||||
-rw-r--r-- | lib/file_factory.cc | 1 | ||||
-rw-r--r-- | lib/sitecing_enflesher.ll | 76 | ||||
-rw-r--r-- | lib/sitecing_util.cc | 4 |
5 files changed, 93 insertions, 20 deletions
diff --git a/include/sitecing/sitecing_enflesher.h b/include/sitecing/sitecing_enflesher.h index 512a358..8bc43a0 100644 --- a/include/sitecing/sitecing_enflesher.h +++ b/include/sitecing/sitecing_enflesher.h | |||
@@ -42,6 +42,11 @@ class sitecing_enflesher : public sitecing_enflesherFlexLexer { | |||
42 | * The output stream. | 42 | * The output stream. |
43 | */ | 43 | */ |
44 | ofstream outs; | 44 | ofstream outs; |
45 | /** | ||
46 | * the outs stream destination file. | ||
47 | * @see outs | ||
48 | */ | ||
49 | string outs_filename; | ||
45 | 50 | ||
46 | /** | 51 | /** |
47 | * @param p The parser object containing preparsed data. | 52 | * @param p The parser object containing preparsed data. |
@@ -61,6 +66,14 @@ class sitecing_enflesher : public sitecing_enflesherFlexLexer { | |||
61 | * Put a #line anchor into output. | 66 | * Put a #line anchor into output. |
62 | */ | 67 | */ |
63 | void anchor(); | 68 | void anchor(); |
69 | |||
70 | /** | ||
71 | * Close previously opened output stream, rename to the 'correct' | ||
72 | * destination filename, if needed, and open new file. | ||
73 | * @see outs | ||
74 | * @see outs_filename | ||
75 | */ | ||
76 | void outs_open(const string& nfile); | ||
64 | }; | 77 | }; |
65 | 78 | ||
66 | #endif /* __SITECING_SITECING_ENFLESHER_H */ | 79 | #endif /* __SITECING_SITECING_ENFLESHER_H */ |
diff --git a/lib/component_factory.cc b/lib/component_factory.cc index f8666dc..b8f5a16 100644 --- a/lib/component_factory.cc +++ b/lib/component_factory.cc | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | namespace sitecing { | 20 | namespace sitecing { |
21 | 21 | ||
22 | static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors" }; | 22 | static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; |
23 | static const char *cc_targets[] = { ".o", ".d" }; | 23 | static const char *cc_targets[] = { ".o", ".d" }; |
24 | 24 | ||
25 | component_factory::component_factory(configuration& c) | 25 | component_factory::component_factory(configuration& c) |
@@ -116,15 +116,20 @@ namespace sitecing { | |||
116 | string dp = normalize_path(dst,strip_trailing_slash); | 116 | string dp = normalize_path(dst,strip_trailing_slash); |
117 | // XXX: or just compare it off, instead of throwing things around. | 117 | // XXX: or just compare it off, instead of throwing things around. |
118 | try { | 118 | try { |
119 | strip_prefix(dp,root_intermediate); | 119 | string noro = strip_prefix(dp,root_intermediate); |
120 | return file_factory::is_uptodate(dst,deps); | 120 | for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { |
121 | }catch(utility_no_prefix& unp) { | 121 | try { |
122 | string nos = strip_suffix(noro,pp_targets[ppt]); | ||
123 | return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); | ||
124 | }catch(utility_no_suffix& uns) { } | ||
122 | } | 125 | } |
126 | bool rv = file_factory::is_uptodate(dst,deps); | ||
127 | return rv; | ||
128 | }catch(utility_no_prefix& unp) { } | ||
123 | try { | 129 | try { |
124 | strip_prefix(dp,root_so); | 130 | strip_prefix(dp,root_so); |
125 | return file_factory::is_uptodate(dst,deps); | 131 | return file_factory::is_uptodate(dst,deps); |
126 | }catch(utility_no_prefix& unp) { | 132 | }catch(utility_no_prefix& unp) { } |
127 | } | ||
128 | return true; | 133 | return true; |
129 | } | 134 | } |
130 | 135 | ||
@@ -249,6 +254,8 @@ namespace sitecing { | |||
249 | parser.component_basename = noro; | 254 | parser.component_basename = noro; |
250 | try { | 255 | try { |
251 | parser.preprocess(src); | 256 | parser.preprocess(src); |
257 | string sf = root_intermediate+noro+".pp_stamp"; | ||
258 | ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp | ||
252 | }catch(preprocessor_error& pe) { | 259 | }catch(preprocessor_error& pe) { |
253 | pe.component_name = noro; | 260 | pe.component_name = noro; |
254 | pe.see(CODEPOINT); | 261 | pe.see(CODEPOINT); |
diff --git a/lib/file_factory.cc b/lib/file_factory.cc index c6b5748..7ca7b86 100644 --- a/lib/file_factory.cc +++ b/lib/file_factory.cc | |||
@@ -39,6 +39,7 @@ namespace sitecing { | |||
39 | if(!is_uptodate(dst,&deps)) { | 39 | if(!is_uptodate(dst,&deps)) { |
40 | for(file_list_t::const_iterator i=deps.begin();i!=deps.end();i++) | 40 | for(file_list_t::const_iterator i=deps.begin();i!=deps.end();i++) |
41 | make(*i); | 41 | make(*i); |
42 | if(!is_uptodate(dst,&deps)) | ||
42 | build(dst); | 43 | build(dst); |
43 | } | 44 | } |
44 | depth--; | 45 | depth--; |
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 | |||
@@ -22,12 +22,7 @@ ID [A-Za-z_][A-Za-z0-9_]* | |||
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 | } |
@@ -35,12 +30,7 @@ ID [A-Za-z_][A-Za-z0-9_]* | |||
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 | ||
@@ -197,6 +187,68 @@ void sitecing_enflesher::anchor() { | |||
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 | */ |
diff --git a/lib/sitecing_util.cc b/lib/sitecing_util.cc index 5466b28..f892a60 100644 --- a/lib/sitecing_util.cc +++ b/lib/sitecing_util.cc | |||
@@ -56,13 +56,13 @@ namespace sitecing { | |||
56 | } | 56 | } |
57 | 57 | ||
58 | string strip_prefix(const string& str,const string& prefix) { | 58 | string strip_prefix(const string& str,const string& prefix) { |
59 | if(str.compare(0,prefix.length(),prefix)) | 59 | if( (str.length()<prefix.length()) || str.compare(0,prefix.length(),prefix)) |
60 | throw utility_no_prefix(CODEPOINT,"no such prefix"); | 60 | throw utility_no_prefix(CODEPOINT,"no such prefix"); |
61 | return str.substr(prefix.length()); | 61 | return str.substr(prefix.length()); |
62 | } | 62 | } |
63 | 63 | ||
64 | string strip_suffix(const string& str,const string& suffix) { | 64 | string strip_suffix(const string& str,const string& suffix) { |
65 | if(str.compare(str.length()-suffix.length(),suffix.length(),suffix)) | 65 | if( (str.length()<suffix.length()) || str.compare(str.length()-suffix.length(),suffix.length(),suffix)) |
66 | throw utility_no_suffix(CODEPOINT,"no such suffix"); | 66 | throw utility_no_suffix(CODEPOINT,"no such suffix"); |
67 | return str.substr(0,str.length()-suffix.length()); | 67 | return str.substr(0,str.length()-suffix.length()); |
68 | } | 68 | } |