-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 @@ -43,4 +43,9 @@ class sitecing_enflesher : public sitecing_enflesherFlexLexer { */ ofstream outs; + /** + * the outs stream destination file. + * @see outs + */ + string outs_filename; /** @@ -62,4 +67,12 @@ 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 @@ -20,5 +20,5 @@ 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" }; @@ -117,13 +117,18 @@ namespace sitecing { // XXX: or just compare it off, instead of throwing things around. 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 { strip_prefix(dp,root_so); return file_factory::is_uptodate(dst,deps); - }catch(utility_no_prefix& unp) { - } + }catch(utility_no_prefix& unp) { } return true; } @@ -250,4 +255,6 @@ namespace sitecing { try { 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) { pe.component_name = noro; 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 @@ -40,5 +40,6 @@ namespace sitecing { for(file_list_t::const_iterator i=deps.begin();i!=deps.end();i++) make(*i); - build(dst); + if(!is_uptodate(dst,&deps)) + build(dst); } 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 @@ -23,10 +23,5 @@ ID [A-Za-z_][A-Za-z0-9_]* line.erase(0,3); 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(); anchoraged = true; @@ -36,10 +31,5 @@ ID [A-Za-z_][A-Za-z0-9_]* line.erase(0,2); 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; } @@ -198,4 +188,66 @@ void sitecing_enflesher::anchor() { anchor_time = false; } + +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"); +} /* * vim:set ft=lex: 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 @@ -57,5 +57,5 @@ 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"); return str.substr(prefix.length()); @@ -63,5 +63,5 @@ 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"); return str.substr(0,str.length()-suffix.length()); |