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) (unidiff) | |
tree | d53ef21cf3b2bddfeb957c98344d0be8759ed555 | |
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-- | 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 | |||
@@ -29,38 +29,51 @@ class sitecing_enflesher : public sitecing_enflesherFlexLexer { | |||
29 | * It is time to anchor output with the #line directive. | 29 | * It is time to anchor output with the #line directive. |
30 | */ | 30 | */ |
31 | bool anchor_time; | 31 | bool anchor_time; |
32 | /** | 32 | /** |
33 | * The file currently being written is supposed to have #line | 33 | * The file currently being written is supposed to have #line |
34 | * directives all around the place. | 34 | * directives all around the place. |
35 | */ | 35 | */ |
36 | bool anchoraged; | 36 | bool anchoraged; |
37 | /** | 37 | /** |
38 | * The reference to the parser object containg the parsed source. | 38 | * The reference to the parser object containg the parsed source. |
39 | */ | 39 | */ |
40 | sitecing_parser& parser; | 40 | sitecing_parser& parser; |
41 | /** | 41 | /** |
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. |
48 | */ | 53 | */ |
49 | sitecing_enflesher(sitecing_parser& p) | 54 | sitecing_enflesher(sitecing_parser& p) |
50 | : parser(p), anchor_time(true) { } | 55 | : parser(p), anchor_time(true) { } |
51 | 56 | ||
52 | /** | 57 | /** |
53 | * Do the job. | 58 | * Do the job. |
54 | */ | 59 | */ |
55 | void enflesh(); | 60 | void enflesh(); |
56 | 61 | ||
57 | virtual void LexerOutput(const char *buf,int size); | 62 | virtual void LexerOutput(const char *buf,int size); |
58 | virtual int yylex(); | 63 | virtual int yylex(); |
59 | 64 | ||
60 | /** | 65 | /** |
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 | |||
@@ -6,33 +6,33 @@ | |||
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <sys/wait.h> | 7 | #include <sys/wait.h> |
8 | #include <fcntl.h> | 8 | #include <fcntl.h> |
9 | #include <iostream> | 9 | #include <iostream> |
10 | #include <fstream> | 10 | #include <fstream> |
11 | #include <stdexcept> | 11 | #include <stdexcept> |
12 | #include <vector> | 12 | #include <vector> |
13 | using namespace std; | 13 | using namespace std; |
14 | #include "sitecing/component_factory.h" | 14 | #include "sitecing/component_factory.h" |
15 | #include "sitecing/sitecing_util.h" | 15 | #include "sitecing/sitecing_util.h" |
16 | #include "sitecing/sitecing_parser.h" | 16 | #include "sitecing/sitecing_parser.h" |
17 | #include "sitecing/sitecing_exception.h" | 17 | #include "sitecing/sitecing_exception.h" |
18 | #endif | 18 | #endif |
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) |
26 | : config(c), | 26 | : config(c), |
27 | root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), | 27 | root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), |
28 | root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), | 28 | root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), |
29 | root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { | 29 | root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { |
30 | } | 30 | } |
31 | 31 | ||
32 | void component_factory::get_dependencies(const string& dst,file_list_t& deps) { | 32 | void component_factory::get_dependencies(const string& dst,file_list_t& deps) { |
33 | deps.clear(); | 33 | deps.clear(); |
34 | string dp = normalize_path(dst,strip_trailing_slash); | 34 | string dp = normalize_path(dst,strip_trailing_slash); |
35 | // source documents | 35 | // source documents |
36 | try { // XXX: or just compare it off? | 36 | try { // XXX: or just compare it off? |
37 | string noro = strip_prefix(dp,root_source); | 37 | string noro = strip_prefix(dp,root_source); |
38 | return; | 38 | return; |
@@ -103,41 +103,46 @@ namespace sitecing { | |||
103 | if(str.find_first_of("\\:")==string::npos) | 103 | if(str.find_first_of("\\:")==string::npos) |
104 | deps.push_back(combine_path(config.root_source+noro,str)); | 104 | deps.push_back(combine_path(config.root_source+noro,str)); |
105 | } | 105 | } |
106 | } | 106 | } |
107 | } | 107 | } |
108 | // XXX: extra deps like IntermediateDeps? | 108 | // XXX: extra deps like IntermediateDeps? |
109 | }catch(utility_no_affix& una) { | 109 | }catch(utility_no_affix& una) { |
110 | // do nothing. | 110 | // do nothing. |
111 | } | 111 | } |
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { | 115 | bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { |
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 | } | 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) { } | ||
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 | ||
131 | void component_factory::build(const string& dst) { | 136 | void component_factory::build(const string& dst) { |
132 | string dp = normalize_path(dst,strip_trailing_slash); | 137 | string dp = normalize_path(dst,strip_trailing_slash); |
133 | // sources | 138 | // sources |
134 | try { | 139 | try { |
135 | string noro = strip_prefix(dp,root_source); | 140 | string noro = strip_prefix(dp,root_source); |
136 | // building the sources is left up to developer | 141 | // building the sources is left up to developer |
137 | return; | 142 | return; |
138 | }catch(utility_no_prefix& unp) { | 143 | }catch(utility_no_prefix& unp) { |
139 | } | 144 | } |
140 | // .so files | 145 | // .so files |
141 | try { | 146 | try { |
142 | string noso = strip_suffix(dp,".so"); | 147 | string noso = strip_suffix(dp,".so"); |
143 | string noro = strip_prefix(noso,root_so); | 148 | string noro = strip_prefix(noso,root_so); |
@@ -236,32 +241,34 @@ namespace sitecing { | |||
236 | sitecing_parser parser(*this); | 241 | sitecing_parser parser(*this); |
237 | config_options *co_skeleton = config.lookup_config(noro,config_options::flag_skeleton); | 242 | config_options *co_skeleton = config.lookup_config(noro,config_options::flag_skeleton); |
238 | if(co_skeleton) | 243 | if(co_skeleton) |
239 | parser.skeleton = co_skeleton->skeleton; | 244 | parser.skeleton = co_skeleton->skeleton; |
240 | static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 245 | static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
241 | parser.class_name = normalize_path(noro,strip_leading_slash|strip_trailing_slash); | 246 | parser.class_name = normalize_path(noro,strip_leading_slash|strip_trailing_slash); |
242 | for(string::size_type illc = parser.class_name.find_first_not_of(id_chars);illc!=string::npos;illc=parser.class_name.find_first_not_of(id_chars,illc)) { | 247 | for(string::size_type illc = parser.class_name.find_first_not_of(id_chars);illc!=string::npos;illc=parser.class_name.find_first_not_of(id_chars,illc)) { |
243 | string::size_type lc = parser.class_name.find_first_of(id_chars,illc); | 248 | string::size_type lc = parser.class_name.find_first_of(id_chars,illc); |
244 | int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; | 249 | int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; |
245 | parser.class_name.replace(illc,n,n,'_'); | 250 | parser.class_name.replace(illc,n,n,'_'); |
246 | } | 251 | } |
247 | parser.class_name = "_SCC_"+parser.class_name; | 252 | parser.class_name = "_SCC_"+parser.class_name; |
248 | parser.output_basename = nos; | 253 | parser.output_basename = nos; |
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); |
255 | throw; | 262 | throw; |
256 | } | 263 | } |
257 | return; | 264 | return; |
258 | }catch(utility_no_affix& una) { | 265 | }catch(utility_no_affix& una) { |
259 | // must be a crap from .d file | 266 | // must be a crap from .d file |
260 | } | 267 | } |
261 | } | 268 | } |
262 | cerr << "ignoring build request for " << dp << endl; | 269 | cerr << "ignoring build request for " << dp << endl; |
263 | } | 270 | } |
264 | 271 | ||
265 | int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { | 272 | int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { |
266 | // XXX: is it right that we do stdio/stderr tricks outside of the function? | 273 | // XXX: is it right that we do stdio/stderr tricks outside of the function? |
267 | cerr << "executing: " << cmd; | 274 | cerr << "executing: " << cmd; |
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 | |||
@@ -26,30 +26,31 @@ namespace sitecing { | |||
26 | return false; | 26 | return false; |
27 | if(!is_uptodate(*i)) | 27 | if(!is_uptodate(*i)) |
28 | return false; | 28 | return false; |
29 | } | 29 | } |
30 | return true; | 30 | return true; |
31 | } | 31 | } |
32 | 32 | ||
33 | void file_factory::make(const string& dst) { | 33 | void file_factory::make(const string& dst) { |
34 | try { | 34 | try { |
35 | depth++; | 35 | depth++; |
36 | if(depth>25) | 36 | if(depth>25) |
37 | throw konforka::exception(CODEPOINT,"recursed too deeply."); | 37 | throw konforka::exception(CODEPOINT,"recursed too deeply."); |
38 | file_list_t deps; | 38 | file_list_t deps; |
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 | build(dst); | 42 | if(!is_uptodate(dst,&deps)) |
43 | build(dst); | ||
43 | } | 44 | } |
44 | depth--; | 45 | depth--; |
45 | }catch(konforka::exception& ke) { | 46 | }catch(konforka::exception& ke) { |
46 | depth--; | 47 | depth--; |
47 | ke.see(CODEPOINT); | 48 | ke.see(CODEPOINT); |
48 | throw; | 49 | throw; |
49 | }catch(...) { | 50 | }catch(...) { |
50 | depth--; | 51 | depth--; |
51 | throw; | 52 | throw; |
52 | } | 53 | } |
53 | } | 54 | } |
54 | 55 | ||
55 | } | 56 | } |
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 | |||
@@ -9,51 +9,41 @@ using namespace sitecing; | |||
9 | #define sitecing_enflesher_flexlexer_once | 9 | #define sitecing_enflesher_flexlexer_once |
10 | #include "sitecing/sitecing_enflesher.h" | 10 | #include "sitecing/sitecing_enflesher.h" |
11 | #include "sitecing/sitecing_parser.h" | 11 | #include "sitecing/sitecing_parser.h" |
12 | #undef yyFlexLexer | 12 | #undef yyFlexLexer |
13 | #define yyFlexLexer sitecing_enflesherFlexLexer | 13 | #define yyFlexLexer sitecing_enflesherFlexLexer |
14 | %} | 14 | %} |
15 | %option 8bit c++ verbose noyywrap yyclass="sitecing_enflesher" yylineno prefix="sitecing_enflesher" stack debug | 15 | %option 8bit c++ verbose noyywrap yyclass="sitecing_enflesher" yylineno prefix="sitecing_enflesher" stack debug |
16 | 16 | ||
17 | ID[A-Za-z_][A-Za-z0-9_]* | 17 | ID[A-Za-z_][A-Za-z0-9_]* |
18 | 18 | ||
19 | %% | 19 | %% |
20 | 20 | ||
21 | ^\%\%\#[^\n]+\n{ | 21 | ^\%\%\#[^\n]+\n{ |
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 | } |
34 | ^\%\%[^\n]+\n{ | 29 | ^\%\%[^\n]+\n{ |
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 | ||
47 | \<\%component_basename\%\>outs << parser.component_basename; anchor_time = true; | 37 | \<\%component_basename\%\>outs << parser.component_basename; anchor_time = true; |
48 | \<\%impl\%\> outs << parser.impl; anchor_time = true; | 38 | \<\%impl\%\> outs << parser.impl; anchor_time = true; |
49 | \<\%member_functions:impl\%\>{ | 39 | \<\%member_functions:impl\%\>{ |
50 | for(sitecing_parser::member_functions_t::const_iterator i=parser.member_functions.begin();i!=parser.member_functions.end();i++) { | 40 | for(sitecing_parser::member_functions_t::const_iterator i=parser.member_functions.begin();i!=parser.member_functions.end();i++) { |
51 | outs << i->type << " " << parser.class_name << "::"; | 41 | outs << i->type << " " << parser.class_name << "::"; |
52 | if(i->name.empty()) { | 42 | if(i->name.empty()) { |
53 | outs << parser.class_name << "()"; | 43 | outs << parser.class_name << "()"; |
54 | bool first = true; | 44 | bool first = true; |
55 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { | 45 | for(sitecing_parser::member_variables_t::iterator i=parser.member_variables.begin();i!=parser.member_variables.end();i++) { |
56 | if(i->initializer.empty()) | 46 | if(i->initializer.empty()) |
57 | continue; | 47 | continue; |
58 | if(first) { | 48 | if(first) { |
59 | outs << ":"; | 49 | outs << ":"; |
@@ -184,19 +174,81 @@ void sitecing_enflesher::LexerOutput(const char *buf,int size) { | |||
184 | } | 174 | } |
185 | 175 | ||
186 | void sitecing_enflesher::enflesh() { | 176 | void sitecing_enflesher::enflesh() { |
187 | ifstream ifs(parser.skeleton.c_str()); | 177 | ifstream ifs(parser.skeleton.c_str()); |
188 | if(!ifs.good()) | 178 | if(!ifs.good()) |
189 | throw preprocessor_error(CODEPOINT,"failed to open skeleton file"); | 179 | throw preprocessor_error(CODEPOINT,"failed to open skeleton file"); |
190 | switch_streams(&ifs,NULL); | 180 | switch_streams(&ifs,NULL); |
191 | yylex(); | 181 | yylex(); |
192 | } | 182 | } |
193 | 183 | ||
194 | void sitecing_enflesher::anchor() { | 184 | void sitecing_enflesher::anchor() { |
195 | if(!anchoraged) | 185 | if(!anchoraged) |
196 | return; | 186 | return; |
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 | |||
@@ -43,39 +43,39 @@ namespace sitecing { | |||
43 | || ( s[0]=='/' && s[1]=='.' && s[2]=='.' && (s[3]==0 || s[3]=='/') ) // "/..(/|$)" | 43 | || ( s[0]=='/' && s[1]=='.' && s[2]=='.' && (s[3]==0 || s[3]=='/') ) // "/..(/|$)" |
44 | ) | 44 | ) |
45 | throw utility_restricted_sequence(CODEPOINT,"restricted updir sequence encountered"); | 45 | throw utility_restricted_sequence(CODEPOINT,"restricted updir sequence encountered"); |
46 | } | 46 | } |
47 | rv += *s; | 47 | rv += *s; |
48 | if( (*s) != '/' ) | 48 | if( (*s) != '/' ) |
49 | notslash=rv.length(); | 49 | notslash=rv.length(); |
50 | } | 50 | } |
51 | if(!(opts&strip_trailing_slash)) | 51 | if(!(opts&strip_trailing_slash)) |
52 | notslash++; | 52 | notslash++; |
53 | if(notslash<rv.length()) | 53 | if(notslash<rv.length()) |
54 | rv.erase(notslash); // XXX: check the logic of stripping/not strippling trailing slash | 54 | rv.erase(notslash); // XXX: check the logic of stripping/not strippling trailing slash |
55 | return rv; | 55 | return rv; |
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 | } |
69 | 69 | ||
70 | string dir_name(const string& filename) { | 70 | string dir_name(const string& filename) { |
71 | string::size_type sl = filename.find_last_of('/'); | 71 | string::size_type sl = filename.find_last_of('/'); |
72 | if(sl==string::npos) | 72 | if(sl==string::npos) |
73 | return ""; // no slashes -- no dir. | 73 | return ""; // no slashes -- no dir. |
74 | string::size_type nosl = filename.find_last_not_of('/',sl); | 74 | string::size_type nosl = filename.find_last_not_of('/',sl); |
75 | if(nosl==string::npos) | 75 | if(nosl==string::npos) |
76 | return ""; // only slashes -- no dir. XXX: only slashes after the last slash... does it mean no dir? | 76 | return ""; // only slashes -- no dir. XXX: only slashes after the last slash... does it mean no dir? |
77 | return filename.substr(0,nosl+1); | 77 | return filename.substr(0,nosl+1); |
78 | } | 78 | } |
79 | 79 | ||
80 | void make_path(const string& path,mode_t mode) { | 80 | void make_path(const string& path,mode_t mode) { |
81 | struct stat st; | 81 | struct stat st; |