From 3ddbfeafde93d1aab16a710498d86eef4e787406 Mon Sep 17 00:00:00 2001 From: Michael Krelin Date: Wed, 30 Mar 2005 15:50:28 +0000 Subject: 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 --- (limited to 'lib/sitecing_enflesher.ll') 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_]* 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; } @@ -35,12 +30,7 @@ ID [A-Za-z_][A-Za-z0-9_]* 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; } @@ -197,6 +187,68 @@ void sitecing_enflesher::anchor() { 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: */ -- cgit v0.9.0.2