author | Michael Krelin <hacker@klever.net> | 2005-03-30 15:50:28 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2005-03-30 15:50:28 (UTC) |
commit | 3ddbfeafde93d1aab16a710498d86eef4e787406 (patch) (side-by-side diff) | |
tree | d53ef21cf3b2bddfeb957c98344d0be8759ed555 /lib/sitecing_enflesher.ll | |
parent | 642dc685bd0a3f1526e22827a4539aa0e06aeff7 (diff) | |
download | sitecing-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
-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 @@ -21,27 +21,17 @@ ID [A-Za-z_][A-Za-z0-9_]* ^\%\%\#[^\n]+\n { string line = yytext; 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; } ^\%\%[^\n]+\n { string line = yytext; 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; } \<\%component_basename\%\> outs << parser.component_basename; anchor_time = true; @@ -196,7 +186,69 @@ void sitecing_enflesher::anchor() { return; outs << "\n#line " << lineno() << " \"" << parser.skeleton << "\"\n"; 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: */ |