-rw-r--r-- | include/sitecing/sitecing_enflesher.h | 13 | ||||
-rw-r--r-- | lib/component_factory.cc | 21 | ||||
-rw-r--r-- | lib/file_factory.cc | 3 | ||||
-rw-r--r-- | lib/sitecing_enflesher.ll | 76 | ||||
-rw-r--r-- | lib/sitecing_util.cc | 4 |
5 files changed, 95 insertions, 22 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 @@ -44,2 +44,7 @@ class sitecing_enflesher : public sitecing_enflesherFlexLexer { ofstream outs; + /** + * the outs stream destination file. + * @see outs + */ + string outs_filename; @@ -63,2 +68,10 @@ class sitecing_enflesher : public sitecing_enflesherFlexLexer { void anchor(); + + /** + * Close previously opened output stream, rename to the 'correct' + * destination filename, if needed, and open new file. + * @see outs + * @see outs_filename + */ + void outs_open(const string& nfile); }; 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 @@ -21,3 +21,3 @@ namespace sitecing { - static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors" }; + static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; static const char *cc_targets[] = { ".o", ".d" }; @@ -118,6 +118,12 @@ namespace sitecing { try { - strip_prefix(dp,root_intermediate); - return file_factory::is_uptodate(dst,deps); - }catch(utility_no_prefix& unp) { - } + string noro = strip_prefix(dp,root_intermediate); + for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { + try { + string nos = strip_suffix(noro,pp_targets[ppt]); + return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); + }catch(utility_no_suffix& uns) { } + } + bool rv = file_factory::is_uptodate(dst,deps); + return rv; + }catch(utility_no_prefix& unp) { } try { @@ -125,4 +131,3 @@ namespace sitecing { return file_factory::is_uptodate(dst,deps); - }catch(utility_no_prefix& unp) { - } + }catch(utility_no_prefix& unp) { } return true; @@ -251,2 +256,4 @@ namespace sitecing { parser.preprocess(src); + string sf = root_intermediate+noro+".pp_stamp"; + ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp }catch(preprocessor_error& pe) { 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 @@ -41,3 +41,4 @@ namespace sitecing { make(*i); - build(dst); + if(!is_uptodate(dst,&deps)) + build(dst); } 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 @@ -24,8 +24,3 @@ ID [A-Za-z_][A-Za-z0-9_]* line.erase(line.length()-1); - outs.flush(); - outs.close(); - outs.clear(); - outs.open((parser.output_basename+line).c_str(),ios::trunc); - if(!outs.good()) - throw preprocessor_error(CODEPOINT,"failed to write preprocessor output"); + outs_open(parser.output_basename+line); anchor(); @@ -37,8 +32,3 @@ ID [A-Za-z_][A-Za-z0-9_]* line.erase(line.length()-1); - outs.flush(); - outs.close(); - outs.clear(); - outs.open((parser.output_basename+line).c_str(),ios::trunc); - if(!outs.good()) - throw preprocessor_error(CODEPOINT,"failed to write preprocessor output"); + outs_open(parser.output_basename+line); anchoraged = false; @@ -199,2 +189,64 @@ void sitecing_enflesher::anchor() { } + +void sitecing_enflesher::outs_open(const string& nfile) { + if(!outs_filename.empty()) { + outs.flush(); + outs.close(); + outs.clear(); + /* + * compare source and destination files. + * + * one can also keep a hash for the old one and compute one for the + * output while writing, but I'm not sure if it's any better. Surely a + * bit less accurate, unless we're going to compare it in case of + * difference, anyway. + */ + bool overwrite = false; + struct stat st_s, st_d; + string fn_s = outs_filename+".new"; + string fn_d = outs_filename; + if(stat(fn_d.c_str(),&st_d)) { + overwrite = true; + }else{ + if(stat(fn_s.c_str(),&st_s)) + throw preprocessor_error(CODEPOINT,"failed to stat() supposedly created file"); + if(st_s.st_size!=st_d.st_size) { + overwrite = true; + }else{ + ifstream i_s(fn_s.c_str(),ios::in); + if(!i_s) + throw preprocessor_error(CODEPOINT,"failed to open supposedly created file"); + ifstream i_d(fn_d.c_str(),ios::in); + if(!i_d) + throw preprocessor_error(CODEPOINT,"failed to open the old preprocessed source"); + off_t remaining = st_s.st_size; + char t1[2048]; + char t2[sizeof(t1)]; + while(remaining) { + int rb = remaining; + if(rb>sizeof(t1)) + rb = sizeof(t1); + if(i_s.read(t1,rb).gcount()!=rb) + throw preprocessor_error(CODEPOINT,"error reading just created file"); + if(i_d.read(t2,rb).gcount()!=rb) + throw preprocessor_error(CODEPOINT,"error reading the old preprocessed source"); + if(memcmp(t1,t2,rb)) { + overwrite = true; + break; + } + remaining -= rb; + } + } + } + if(overwrite) { + cerr << "renaming '" << fn_s << "'" << endl; + if(rename(fn_s.c_str(),fn_d.c_str())) + throw preprocessor_error(CODEPOINT,"failed to rename() generated output"); + } + } + outs_filename = nfile; + outs.open((nfile+".new").c_str(),ios::trunc); + if(!outs.good()) + throw preprocessor_error(CODEPOINT,"failed to write preprocessor output"); +} /* 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 @@ -58,3 +58,3 @@ namespace sitecing { string strip_prefix(const string& str,const string& prefix) { - if(str.compare(0,prefix.length(),prefix)) + if( (str.length()<prefix.length()) || str.compare(0,prefix.length(),prefix)) throw utility_no_prefix(CODEPOINT,"no such prefix"); @@ -64,3 +64,3 @@ namespace sitecing { string strip_suffix(const string& str,const string& suffix) { - if(str.compare(str.length()-suffix.length(),suffix.length(),suffix)) + if( (str.length()<suffix.length()) || str.compare(str.length()-suffix.length(),suffix.length(),suffix)) throw utility_no_suffix(CODEPOINT,"no such suffix"); |