-rw-r--r-- | lib/component_factory.cc | 31 | ||||
-rw-r--r-- | lib/configuration.cc | 9 | ||||
-rw-r--r-- | lib/sitecing_parser.ll | 13 | ||||
-rw-r--r-- | lib/sitecing_util.cc | 117 | ||||
-rw-r--r-- | lib/sitespace.cc | 3 |
5 files changed, 30 insertions, 143 deletions
diff --git a/lib/component_factory.cc b/lib/component_factory.cc index d9692de..af3d911 100644 --- a/lib/component_factory.cc +++ b/lib/component_factory.cc | |||
@@ -1,344 +1,345 @@ | |||
1 | #ifdef USE_PCH | 1 | #ifdef USE_PCH |
2 | #include "pch.h" | 2 | #include "pch.h" |
3 | #else | 3 | #else |
4 | #include <sys/types.h> | 4 | #include <sys/types.h> |
5 | #include <sys/stat.h> | 5 | #include <sys/stat.h> |
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 <konforka/util.h> | ||
14 | #include "sitecing/component_factory.h" | 15 | #include "sitecing/component_factory.h" |
15 | #include "sitecing/sitecing_util.h" | 16 | #include "sitecing/sitecing_util.h" |
16 | #include "sitecing/sitecing_parser.h" | 17 | #include "sitecing/sitecing_parser.h" |
17 | #include "sitecing/sitecing_exception.h" | 18 | #include "sitecing/sitecing_exception.h" |
18 | #endif | 19 | #endif |
19 | 20 | ||
20 | namespace sitecing { | 21 | namespace sitecing { |
21 | 22 | ||
22 | static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; | 23 | static const char *pp_targets[] = { ".cc", ".h", ".imports", ".classname", ".baseclassname", ".ancestors", ".pp_stamp" }; |
23 | static const char *cc_targets[] = { ".o", ".d" }; | 24 | static const char *cc_targets[] = { ".o", ".d" }; |
24 | 25 | ||
25 | component_factory::component_factory(configuration& c) | 26 | component_factory::component_factory(configuration& c) |
26 | : config(c), | 27 | : config(c), |
27 | root_source(normalize_path(c.root_source,strip_trailing_slash)+'/'), | 28 | root_source(konforka::normalize_path(c.root_source,konforka::strip_trailing_slash)+'/'), |
28 | root_intermediate(normalize_path(c.root_intermediate,strip_trailing_slash)+'/'), | 29 | root_intermediate(konforka::normalize_path(c.root_intermediate,konforka::strip_trailing_slash)+'/'), |
29 | root_so(normalize_path(c.root_so,strip_trailing_slash)+'/') { | 30 | root_so(konforka::normalize_path(c.root_so,konforka::strip_trailing_slash)+'/') { |
30 | } | 31 | } |
31 | 32 | ||
32 | void component_factory::get_dependencies(const string& dst,file_list_t& deps) { | 33 | void component_factory::get_dependencies(const string& dst,file_list_t& deps) { |
33 | deps.clear(); | 34 | deps.clear(); |
34 | string dp = normalize_path(dst,strip_trailing_slash); | 35 | string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); |
35 | // source documents | 36 | // source documents |
36 | try { // XXX: or just compare it off? | 37 | try { // XXX: or just compare it off? |
37 | string noro = strip_prefix(dp,root_source); | 38 | string noro = strip_prefix(dp,root_source); |
38 | return; | 39 | return; |
39 | }catch(utility_no_affix& una) { } | 40 | }catch(utility_no_affix& una) { } |
40 | // .so binaries | 41 | // .so binaries |
41 | try { | 42 | try { |
42 | string noso = strip_suffix(dp,".so"); | 43 | string noso = strip_suffix(dp,".so"); |
43 | string noro = strip_prefix(noso,root_so); | 44 | string noro = strip_prefix(noso,root_so); |
44 | deps.push_back(root_intermediate+noro+".o"); | 45 | deps.push_back(root_intermediate+noro+".o"); |
45 | config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps); | 46 | config_options *co_so_deps = config.lookup_config(noro,config_options::flag_so_deps); |
46 | if(co_so_deps) { | 47 | if(co_so_deps) { |
47 | for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i) | 48 | for(list<string>::const_iterator i=co_so_deps->so_deps.begin();i!=co_so_deps->so_deps.end();++i) |
48 | deps.push_back(*i); | 49 | deps.push_back(*i); |
49 | } | 50 | } |
50 | return; | 51 | return; |
51 | }catch(utility_no_prefix& unp) { | 52 | }catch(utility_no_prefix& unp) { |
52 | throw konforka::exception(CODEPOINT,"component is outside of component root"); | 53 | throw konforka::exception(CODEPOINT,"component is outside of component root"); |
53 | }catch(utility_no_suffix& uns) { } | 54 | }catch(utility_no_suffix& uns) { } |
54 | try { | 55 | try { |
55 | // preprocessor targets | 56 | // preprocessor targets |
56 | string noro = strip_prefix(dp,root_intermediate); | 57 | string noro = strip_prefix(dp,root_intermediate); |
57 | for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { | 58 | for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { |
58 | try { | 59 | try { |
59 | string nos = strip_suffix(noro,pp_targets[ppt]); | 60 | string nos = strip_suffix(noro,pp_targets[ppt]); |
60 | deps.push_back(root_source+nos); // depends on the source | 61 | deps.push_back(root_source+nos); // depends on the source |
61 | ifstream imports((root_intermediate+nos+".imports").c_str(),ios::in); | 62 | ifstream imports((root_intermediate+nos+".imports").c_str(),ios::in); |
62 | if(imports.good()) { | 63 | if(imports.good()) { |
63 | string str; | 64 | string str; |
64 | while(!imports.eof()) { | 65 | while(!imports.eof()) { |
65 | imports >> str; | 66 | imports >> str; |
66 | if(!str.empty()) | 67 | if(!str.empty()) |
67 | deps.push_back(root_intermediate+str+".classname"); | 68 | deps.push_back(root_intermediate+str+".classname"); |
68 | } | 69 | } |
69 | } | 70 | } |
70 | ifstream ancestors((root_intermediate+nos+".ancestors").c_str(),ios::in); | 71 | ifstream ancestors((root_intermediate+nos+".ancestors").c_str(),ios::in); |
71 | if(ancestors.good()) { | 72 | if(ancestors.good()) { |
72 | string str; | 73 | string str; |
73 | while(!ancestors.eof()) { | 74 | while(!ancestors.eof()) { |
74 | ancestors >> str; | 75 | ancestors >> str; |
75 | if(!str.empty()) | 76 | if(!str.empty()) |
76 | deps.push_back(root_intermediate+str+".classname"); | 77 | deps.push_back(root_intermediate+str+".classname"); |
77 | } | 78 | } |
78 | } | 79 | } |
79 | // XXX: intermediate_deps should be broken down | 80 | // XXX: intermediate_deps should be broken down |
80 | config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); | 81 | config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); |
81 | if(co_intermediate_deps) { | 82 | if(co_intermediate_deps) { |
82 | for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) | 83 | for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) |
83 | deps.push_back(*i); | 84 | deps.push_back(*i); |
84 | } | 85 | } |
85 | return; | 86 | return; |
86 | }catch(utility_no_suffix& uns) { } | 87 | }catch(utility_no_suffix& uns) { } |
87 | } | 88 | } |
88 | // compiler targets | 89 | // compiler targets |
89 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { | 90 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { |
90 | try { | 91 | try { |
91 | string nos = strip_suffix(noro,cc_targets[cct]); | 92 | string nos = strip_suffix(noro,cc_targets[cct]); |
92 | deps.push_back(root_intermediate+nos+".cc"); | 93 | deps.push_back(root_intermediate+nos+".cc"); |
93 | config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); | 94 | config_options *co_cpp_deps = config.lookup_config(noro,config_options::flag_cpp_deps); |
94 | if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { | 95 | if( (!co_cpp_deps) || co_cpp_deps->cpp_deps) { |
95 | ifstream df((root_intermediate+nos+".d").c_str(),ios::in); | 96 | ifstream df((root_intermediate+nos+".d").c_str(),ios::in); |
96 | if(df.good()) { | 97 | if(df.good()) { |
97 | string str; | 98 | string str; |
98 | while(!df.eof()) { | 99 | while(!df.eof()) { |
99 | df >> str; | 100 | df >> str; |
100 | if(str.find_first_of("\\:")==string::npos) | 101 | if(str.find_first_of("\\:")==string::npos) |
101 | deps.push_back(combine_path(config.root_source+nos,str)); | 102 | deps.push_back(konforka::combine_path(config.root_source+nos,str)); |
102 | } | 103 | } |
103 | } | 104 | } |
104 | } | 105 | } |
105 | // XXX: intermediate_deps should be broken down | 106 | // XXX: intermediate_deps should be broken down |
106 | config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); | 107 | config_options *co_intermediate_deps = config.lookup_config(nos,config_options::flag_intermediate_deps); |
107 | if(co_intermediate_deps) { | 108 | if(co_intermediate_deps) { |
108 | for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) | 109 | for(list<string>::const_iterator i=co_intermediate_deps->intermediate_deps.begin();i!=co_intermediate_deps->intermediate_deps.end();++i) |
109 | deps.push_back(*i); | 110 | deps.push_back(*i); |
110 | } | 111 | } |
111 | }catch(utility_no_suffix& uns) { } | 112 | }catch(utility_no_suffix& uns) { } |
112 | } | 113 | } |
113 | }catch(utility_no_prefix& unp) { } | 114 | }catch(utility_no_prefix& unp) { } |
114 | } | 115 | } |
115 | 116 | ||
116 | bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { | 117 | bool component_factory::is_uptodate(const string& dst,file_list_t *deps) { |
117 | string dp = normalize_path(dst,strip_trailing_slash); | 118 | string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); |
118 | try { | 119 | try { |
119 | string noro = strip_prefix(dp,root_intermediate); | 120 | string noro = strip_prefix(dp,root_intermediate); |
120 | for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { | 121 | for(int ppt=0;(ppt+1)<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { |
121 | try { | 122 | try { |
122 | string nos = strip_suffix(noro,pp_targets[ppt]); | 123 | string nos = strip_suffix(noro,pp_targets[ppt]); |
123 | return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); | 124 | return file_factory::is_uptodate(root_intermediate+nos+".pp_stamp",deps); |
124 | }catch(utility_no_suffix& uns) { } | 125 | }catch(utility_no_suffix& uns) { } |
125 | } | 126 | } |
126 | bool rv = file_factory::is_uptodate(dst,deps); | 127 | bool rv = file_factory::is_uptodate(dst,deps); |
127 | return rv; | 128 | return rv; |
128 | }catch(utility_no_prefix& unp) { } | 129 | }catch(utility_no_prefix& unp) { } |
129 | // XXX: or just compare it off, instead of throwing things around. | 130 | // XXX: or just compare it off, instead of throwing things around. |
130 | try { | 131 | try { |
131 | strip_prefix(dp,root_so); | 132 | strip_prefix(dp,root_so); |
132 | return file_factory::is_uptodate(dst,deps); | 133 | return file_factory::is_uptodate(dst,deps); |
133 | }catch(utility_no_prefix& unp) { } | 134 | }catch(utility_no_prefix& unp) { } |
134 | return true; | 135 | return true; |
135 | } | 136 | } |
136 | 137 | ||
137 | void component_factory::build(const string& dst) { | 138 | void component_factory::build(const string& dst) { |
138 | string dp = normalize_path(dst,strip_trailing_slash); | 139 | string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); |
139 | // sources | 140 | // sources |
140 | try { | 141 | try { |
141 | string noro = strip_prefix(dp,root_source); | 142 | string noro = strip_prefix(dp,root_source); |
142 | // building the sources is left up to developer | 143 | // building the sources is left up to developer |
143 | return; | 144 | return; |
144 | }catch(utility_no_prefix& unp) { } | 145 | }catch(utility_no_prefix& unp) { } |
145 | // .so files | 146 | // .so files |
146 | try { | 147 | try { |
147 | string noso = strip_suffix(dp,".so"); | 148 | string noso = strip_suffix(dp,".so"); |
148 | string noro = strip_prefix(noso,root_so); | 149 | string noro = strip_prefix(noso,root_so); |
149 | string o = root_intermediate+noro+".o"; | 150 | string o = root_intermediate+noro+".o"; |
150 | cerr << "Linking " << noro << endl; | 151 | cerr << "Linking " << noro << endl; |
151 | if(access(o.c_str(),R_OK)) | 152 | if(access(o.c_str(),R_OK)) |
152 | throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); | 153 | throw konforka::exception(CODEPOINT,string("can't access compiled component code (")+o+")"); |
153 | make_path(dir_name(root_so+noro),0755); | 154 | konforka::make_path(konforka::dir_name(root_so+noro),0755); |
154 | file_lock lock_cc(root_intermediate+noro+".o.lock"); | 155 | file_lock lock_cc(root_intermediate+noro+".o.lock"); |
155 | file_lock lock_so(root_so+noro+".so.lock"); | 156 | file_lock lock_so(root_so+noro+".so.lock"); |
156 | int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 157 | int stdO = open((root_intermediate+noro+".ld.stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
157 | if(stdO<0) | 158 | if(stdO<0) |
158 | throw konforka::exception(CODEPOINT,"failed to open/create linker stdout"); | 159 | throw konforka::exception(CODEPOINT,"failed to open/create linker stdout"); |
159 | int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 160 | int stdE = open((root_intermediate+noro+".ld.stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
160 | if(stdE<0) { | 161 | if(stdE<0) { |
161 | close(stdO); | 162 | close(stdO); |
162 | throw konforka::exception(CODEPOINT,"failed to open/create linker stderr"); | 163 | throw konforka::exception(CODEPOINT,"failed to open/create linker stderr"); |
163 | } | 164 | } |
164 | list<string> args; | 165 | list<string> args; |
165 | config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags); | 166 | config_options *co_ld_flags = config.lookup_config(noro,config_options::flag_ld_flags); |
166 | if(co_ld_flags) { | 167 | if(co_ld_flags) { |
167 | args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end()); | 168 | args.insert(args.end(),co_ld_flags->ld_flags.begin(),co_ld_flags->ld_flags.end()); |
168 | } | 169 | } |
169 | args.push_back("-shared"); | 170 | args.push_back("-shared"); |
170 | args.push_back(o); | 171 | args.push_back(o); |
171 | file_list_t ancestors; | 172 | file_list_t ancestors; |
172 | get_ancestors(noro,ancestors); | 173 | get_ancestors(noro,ancestors); |
173 | for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) { | 174 | for(file_list_t::const_iterator i=ancestors.begin();i!=ancestors.end();++i) { |
174 | string aso=root_so+*i+".so"; | 175 | string aso=root_so+*i+".so"; |
175 | make(aso); | 176 | make(aso); |
176 | args.push_back(aso); | 177 | args.push_back(aso); |
177 | } | 178 | } |
178 | args.push_back("-o"); args.push_back(dp); | 179 | args.push_back("-o"); args.push_back(dp); |
179 | // TODO: "g++" configurable | 180 | // TODO: "g++" configurable |
180 | int rv = execute("g++",args,stdO,stdE); | 181 | int rv = execute("g++",args,stdO,stdE); |
181 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) | 182 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) |
182 | throw link_error(CODEPOINT,"failed to link component",noro); | 183 | throw link_error(CODEPOINT,"failed to link component",noro); |
183 | return; | 184 | return; |
184 | }catch(utility_no_prefix& unp) { | 185 | }catch(utility_no_prefix& unp) { |
185 | throw konforka::exception(CODEPOINT,"component is outside of component root"); | 186 | throw konforka::exception(CODEPOINT,"component is outside of component root"); |
186 | }catch(utility_no_suffix& uns) { } | 187 | }catch(utility_no_suffix& uns) { } |
187 | try { | 188 | try { |
188 | string noro = strip_prefix(dp,root_intermediate); | 189 | string noro = strip_prefix(dp,root_intermediate); |
189 | // compiler targets | 190 | // compiler targets |
190 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { | 191 | for(int cct=0;cct<sizeof(cc_targets)/sizeof(*cc_targets);cct++) { |
191 | try { | 192 | try { |
192 | string nos = strip_suffix(noro,cc_targets[cct]); | 193 | string nos = strip_suffix(noro,cc_targets[cct]); |
193 | string cc = root_intermediate+nos+".cc"; | 194 | string cc = root_intermediate+nos+".cc"; |
194 | string o = root_intermediate+nos+".o"; | 195 | string o = root_intermediate+nos+".o"; |
195 | cerr << "Compiling " << nos << endl; | 196 | cerr << "Compiling " << nos << endl; |
196 | if(access(cc.c_str(),R_OK)) | 197 | if(access(cc.c_str(),R_OK)) |
197 | throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); | 198 | throw konforka::exception(CODEPOINT,string("can't access preprocessed component code (")+cc+")"); |
198 | make_path(dir_name(cc),0755); | 199 | konforka::make_path(konforka::dir_name(cc),0755); |
199 | string pwd = dir_name(root_source+nos); | 200 | string pwd = konforka::dir_name(root_source+nos); |
200 | auto_chdir dir_changer(pwd); | 201 | auto_chdir dir_changer(pwd); |
201 | file_lock lock_source(root_intermediate+nos+".lock"); | 202 | file_lock lock_source(root_intermediate+nos+".lock"); |
202 | file_lock lock_cc(root_intermediate+nos+".o.lock"); | 203 | file_lock lock_cc(root_intermediate+nos+".o.lock"); |
203 | int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 204 | int stdO = open((root_intermediate+nos+".stdout").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
204 | if(stdO<0) | 205 | if(stdO<0) |
205 | throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); | 206 | throw konforka::exception(CODEPOINT,"failed to open/create compiler stdout"); |
206 | int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); | 207 | int stdE = open((root_intermediate+nos+".stderr").c_str(),O_CREAT|O_TRUNC|O_WRONLY,0664); |
207 | if(stdE<0) { | 208 | if(stdE<0) { |
208 | close(stdO); | 209 | close(stdO); |
209 | throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); | 210 | throw konforka::exception(CODEPOINT,"failed to open/create compiler's stderr"); |
210 | } | 211 | } |
211 | list<string> args; | 212 | list<string> args; |
212 | config_options *co_cpp_flags = config.lookup_config(nos,config_options::flag_cpp_flags); | 213 | config_options *co_cpp_flags = config.lookup_config(nos,config_options::flag_cpp_flags); |
213 | if(co_cpp_flags) { | 214 | if(co_cpp_flags) { |
214 | args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); | 215 | args.insert(args.end(),co_cpp_flags->cpp_flags.begin(),co_cpp_flags->cpp_flags.end()); |
215 | } | 216 | } |
216 | // TODO: maybe move it to separare config option like CoreCPPFLags? | 217 | // TODO: maybe move it to separare config option like CoreCPPFLags? |
217 | args.push_back("-I"+root_intermediate); | 218 | args.push_back("-I"+root_intermediate); |
218 | args.push_back("-I"+root_source); | 219 | args.push_back("-I"+root_source); |
219 | args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+nos+".d"); | 220 | args.push_back("-MD"); args.push_back("-MF"); args.push_back(root_intermediate+nos+".d"); |
220 | args.push_back("-c"); | 221 | args.push_back("-c"); |
221 | args.push_back(cc); | 222 | args.push_back(cc); |
222 | args.push_back("-o"); args.push_back(o); | 223 | args.push_back("-o"); args.push_back(o); |
223 | // TODO: "g++" configurable | 224 | // TODO: "g++" configurable |
224 | int rv = execute("g++",args,stdO,stdE); | 225 | int rv = execute("g++",args,stdO,stdE); |
225 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) | 226 | if(! (WIFEXITED(rv) && !WEXITSTATUS(rv)) ) |
226 | throw compile_error(CODEPOINT,"failed to compile component",nos); | 227 | throw compile_error(CODEPOINT,"failed to compile component",nos); |
227 | return; | 228 | return; |
228 | }catch(utility_no_suffix& uns) { } | 229 | }catch(utility_no_suffix& uns) { } |
229 | } | 230 | } |
230 | // preprocessor targets | 231 | // preprocessor targets |
231 | for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { | 232 | for(int ppt=0;ppt<sizeof(pp_targets)/sizeof(*pp_targets);ppt++) { |
232 | try { | 233 | try { |
233 | string nos = strip_suffix(noro,pp_targets[ppt]); | 234 | string nos = strip_suffix(noro,pp_targets[ppt]); |
234 | string src = root_source+nos; | 235 | string src = root_source+nos; |
235 | cerr << "Preprocessing " << nos << endl; | 236 | cerr << "Preprocessing " << nos << endl; |
236 | if(access(src.c_str(),R_OK)) | 237 | if(access(src.c_str(),R_OK)) |
237 | throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); | 238 | throw konforka::exception(CODEPOINT,string("can't access component source (")+src+")"); |
238 | make_path(dir_name(root_intermediate+nos),0755); | 239 | konforka::make_path(konforka::dir_name(root_intermediate+nos),0755); |
239 | file_lock lock(root_intermediate+nos+".lock"); | 240 | file_lock lock(root_intermediate+nos+".lock"); |
240 | sitecing_parser parser(*this); | 241 | sitecing_parser parser(*this); |
241 | config_options *co_skeleton = config.lookup_config(nos,config_options::flag_skeleton); | 242 | config_options *co_skeleton = config.lookup_config(nos,config_options::flag_skeleton); |
242 | if(co_skeleton) | 243 | if(co_skeleton) |
243 | parser.skeleton = co_skeleton->skeleton; | 244 | parser.skeleton = co_skeleton->skeleton; |
244 | static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 245 | static const char *id_chars = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
245 | parser.class_name = normalize_path(nos,strip_leading_slash|strip_trailing_slash); | 246 | parser.class_name = konforka::normalize_path(nos,konforka::strip_leading_slash|konforka::strip_trailing_slash); |
246 | 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)) { |
247 | 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); |
248 | int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; | 249 | int n = ((lc==string::npos)?parser.class_name.length():lc)-illc; |
249 | parser.class_name.replace(illc,n,n,'_'); | 250 | parser.class_name.replace(illc,n,n,'_'); |
250 | } | 251 | } |
251 | parser.class_name = "_SCC_"+parser.class_name; | 252 | parser.class_name = "_SCC_"+parser.class_name; |
252 | parser.output_basename = root_intermediate+nos; | 253 | parser.output_basename = root_intermediate+nos; |
253 | parser.component_basename = nos; | 254 | parser.component_basename = nos; |
254 | try { | 255 | try { |
255 | parser.preprocess(src); | 256 | parser.preprocess(src); |
256 | string sf = root_intermediate+nos+".pp_stamp"; | 257 | string sf = root_intermediate+nos+".pp_stamp"; |
257 | ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp | 258 | ofstream sfs(sf.c_str(),ios::trunc|ios::out); // touch .pp_stamp |
258 | }catch(preprocessor_error& pe) { | 259 | }catch(preprocessor_error& pe) { |
259 | pe.component_name = nos; | 260 | pe.component_name = nos; |
260 | pe.see(CODEPOINT); | 261 | pe.see(CODEPOINT); |
261 | throw; | 262 | throw; |
262 | } | 263 | } |
263 | return; | 264 | return; |
264 | }catch(utility_no_suffix& uns) { } | 265 | }catch(utility_no_suffix& uns) { } |
265 | } | 266 | } |
266 | }catch(utility_no_prefix& unp) { } | 267 | }catch(utility_no_prefix& unp) { } |
267 | cerr << "ignoring build request for " << dp << endl; | 268 | cerr << "ignoring build request for " << dp << endl; |
268 | } | 269 | } |
269 | 270 | ||
270 | void component_factory::make(const string& dst) { | 271 | void component_factory::make(const string& dst) { |
271 | string dp = normalize_path(dst,strip_trailing_slash); | 272 | string dp = konforka::normalize_path(dst,konforka::strip_trailing_slash); |
272 | try { | 273 | try { |
273 | string noso = strip_suffix(dp,".so"); | 274 | string noso = strip_suffix(dp,".so"); |
274 | string noro = strip_prefix(noso,root_so); | 275 | string noro = strip_prefix(noso,root_so); |
275 | file_list_t a; | 276 | file_list_t a; |
276 | get_ancestors(noro,a); | 277 | get_ancestors(noro,a); |
277 | for(file_list_t::const_iterator i=a.begin();i!=a.end();++i) { | 278 | for(file_list_t::const_iterator i=a.begin();i!=a.end();++i) { |
278 | make(root_so+*i+".so"); | 279 | make(root_so+*i+".so"); |
279 | } | 280 | } |
280 | }catch(utility_no_affix& una) { } | 281 | }catch(utility_no_affix& una) { } |
281 | file_factory::make(dst); | 282 | file_factory::make(dst); |
282 | } | 283 | } |
283 | 284 | ||
284 | int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { | 285 | int component_factory::execute(const string& cmd, const list<string>& args,int stdo,int stde) { |
285 | // XXX: is it right that we do stdio/stderr tricks outside of the function? | 286 | // XXX: is it right that we do stdio/stderr tricks outside of the function? |
286 | // cerr << "executing: " << cmd; | 287 | // cerr << "executing: " << cmd; |
287 | vector<const char*> argv(args.size()+2); | 288 | vector<const char*> argv(args.size()+2); |
288 | argv[0]=cmd.c_str(); | 289 | argv[0]=cmd.c_str(); |
289 | int an = 1; | 290 | int an = 1; |
290 | for(list<string>::const_iterator i=args.begin();i!=args.end();i++) { | 291 | for(list<string>::const_iterator i=args.begin();i!=args.end();i++) { |
291 | // cerr << " " << *i ; | 292 | // cerr << " " << *i ; |
292 | argv[an++] = i->c_str(); | 293 | argv[an++] = i->c_str(); |
293 | } | 294 | } |
294 | // cerr << endl; | 295 | // cerr << endl; |
295 | argv[an++]=NULL; | 296 | argv[an++]=NULL; |
296 | pid_t pid = vfork(); | 297 | pid_t pid = vfork(); |
297 | if(pid==-1) { | 298 | if(pid==-1) { |
298 | close(stdo); close(stde); | 299 | close(stdo); close(stde); |
299 | throw konforka::exception(CODEPOINT,"failed to vfork()"); | 300 | throw konforka::exception(CODEPOINT,"failed to vfork()"); |
300 | } | 301 | } |
301 | if(!pid) { | 302 | if(!pid) { |
302 | // child | 303 | // child |
303 | if(dup2(stdo,1)!=1) | 304 | if(dup2(stdo,1)!=1) |
304 | _exit(-1); | 305 | _exit(-1); |
305 | if(dup2(stde,2)!=2) | 306 | if(dup2(stde,2)!=2) |
306 | _exit(-1); | 307 | _exit(-1); |
307 | close(0); | 308 | close(0); |
308 | execvp(cmd.c_str(),(char**)&argv.front()); | 309 | execvp(cmd.c_str(),(char**)&argv.front()); |
309 | _exit(-1); | 310 | _exit(-1); |
310 | } | 311 | } |
311 | // parent | 312 | // parent |
312 | close(stdo); close(stde); | 313 | close(stdo); close(stde); |
313 | int rv; | 314 | int rv; |
314 | if(waitpid(pid,&rv,0)<0) | 315 | if(waitpid(pid,&rv,0)<0) |
315 | throw konforka::exception(CODEPOINT,"failed to waitpid()"); | 316 | throw konforka::exception(CODEPOINT,"failed to waitpid()"); |
316 | return rv; | 317 | return rv; |
317 | } | 318 | } |
318 | 319 | ||
319 | string component_factory::get_classname(const string& component) { | 320 | string component_factory::get_classname(const string& component) { |
320 | string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".classname"; | 321 | string cn = root_intermediate+konforka::normalize_path(component,konforka::strip_trailing_slash|konforka::strip_leading_slash)+".classname"; |
321 | make(cn); | 322 | make(cn); |
322 | ifstream ifs(cn.c_str()); | 323 | ifstream ifs(cn.c_str()); |
323 | if(!ifs.good()) | 324 | if(!ifs.good()) |
324 | throw konforka::exception(CODEPOINT,"failed to access component .classname"); | 325 | throw konforka::exception(CODEPOINT,"failed to access component .classname"); |
325 | ifs >> cn; | 326 | ifs >> cn; |
326 | return cn; | 327 | return cn; |
327 | } | 328 | } |
328 | 329 | ||
329 | void component_factory::get_ancestors(const string& component,file_list_t& rv) { | 330 | void component_factory::get_ancestors(const string& component,file_list_t& rv) { |
330 | string cn = root_intermediate+normalize_path(component,strip_trailing_slash|strip_leading_slash)+".ancestors"; | 331 | string cn = root_intermediate+konforka::normalize_path(component,konforka::strip_trailing_slash|konforka::strip_leading_slash)+".ancestors"; |
331 | make(cn); | 332 | make(cn); |
332 | ifstream ifs(cn.c_str()); | 333 | ifstream ifs(cn.c_str()); |
333 | if(!ifs.good()) | 334 | if(!ifs.good()) |
334 | throw konforka::exception(CODEPOINT,string("failed to access component '")+component+"' .ancestors"); | 335 | throw konforka::exception(CODEPOINT,string("failed to access component '")+component+"' .ancestors"); |
335 | rv.clear(); | 336 | rv.clear(); |
336 | while(!ifs.eof()) { | 337 | while(!ifs.eof()) { |
337 | string a; | 338 | string a; |
338 | ifs >> a; | 339 | ifs >> a; |
339 | if(!a.empty()) | 340 | if(!a.empty()) |
340 | rv.push_back(a); | 341 | rv.push_back(a); |
341 | } | 342 | } |
342 | } | 343 | } |
343 | 344 | ||
344 | } | 345 | } |
diff --git a/lib/configuration.cc b/lib/configuration.cc index 4ee1526..6b21690 100644 --- a/lib/configuration.cc +++ b/lib/configuration.cc | |||
@@ -1,474 +1,475 @@ | |||
1 | #ifdef USE_PCH | 1 | #ifdef USE_PCH |
2 | #include "pch.h" | 2 | #include "pch.h" |
3 | #else | 3 | #else |
4 | #include <unistd.h> | 4 | #include <unistd.h> |
5 | #include <fnmatch.h> | 5 | #include <fnmatch.h> |
6 | #include <cassert> | 6 | #include <cassert> |
7 | #include <stdexcept> | 7 | #include <stdexcept> |
8 | using namespace std; | 8 | using namespace std; |
9 | #include <konforka/util.h> | ||
9 | #include <dotconf.h> | 10 | #include <dotconf.h> |
10 | #include "sitecing/configuration.h" | 11 | #include "sitecing/configuration.h" |
11 | #include "sitecing/sitecing_util.h" | 12 | #include "sitecing/sitecing_util.h" |
12 | #include "sitecing/scoreboard.h" | 13 | #include "sitecing/scoreboard.h" |
13 | #endif | 14 | #endif |
14 | 15 | ||
15 | namespace sitecing { | 16 | namespace sitecing { |
16 | 17 | ||
17 | configuration::configuration() | 18 | configuration::configuration() |
18 | : flags(0), autobuild(false) { } | 19 | : flags(0), autobuild(false) { } |
19 | configuration::configuration(const string& cfile,bool ab) | 20 | configuration::configuration(const string& cfile,bool ab) |
20 | : flags(0), autobuild(ab) { | 21 | : flags(0), autobuild(ab) { |
21 | parse(cfile); | 22 | parse(cfile); |
22 | } | 23 | } |
23 | 24 | ||
24 | enum dc_ctx { | 25 | enum dc_ctx { |
25 | DCC_ROOT = 1, | 26 | DCC_ROOT = 1, |
26 | DCC_PATH = 2, | 27 | DCC_PATH = 2, |
27 | DCC_SCRC = 4 | 28 | DCC_SCRC = 4 |
28 | }; | 29 | }; |
29 | struct dc_context { | 30 | struct dc_context { |
30 | dc_ctx ctx; | 31 | dc_ctx ctx; |
31 | configuration* cf; | 32 | configuration* cf; |
32 | list<config_options*> co; | 33 | list<config_options*> co; |
33 | }; | 34 | }; |
34 | 35 | ||
35 | static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; | 36 | static DOTCONF_CB(dco_root_source) { dc_context *dcc = (dc_context*)ctx; |
36 | dcc->cf->root_source = cmd->data.str; | 37 | dcc->cf->root_source = cmd->data.str; |
37 | dcc->cf->flags |= configuration::flag_root_source; | 38 | dcc->cf->flags |= configuration::flag_root_source; |
38 | return NULL; | 39 | return NULL; |
39 | } | 40 | } |
40 | static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; | 41 | static DOTCONF_CB(dco_root_intermediate) { dc_context *dcc = (dc_context*)ctx; |
41 | dcc->cf->root_intermediate = cmd->data.str; | 42 | dcc->cf->root_intermediate = cmd->data.str; |
42 | dcc->cf->flags |= configuration::flag_root_intermediate; | 43 | dcc->cf->flags |= configuration::flag_root_intermediate; |
43 | return NULL; | 44 | return NULL; |
44 | } | 45 | } |
45 | static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx; | 46 | static DOTCONF_CB(dco_root_so) { dc_context *dcc = (dc_context*)ctx; |
46 | dcc->cf->root_so = cmd->data.str; | 47 | dcc->cf->root_so = cmd->data.str; |
47 | dcc->cf->flags |= configuration::flag_root_so; | 48 | dcc->cf->flags |= configuration::flag_root_so; |
48 | return NULL; | 49 | return NULL; |
49 | } | 50 | } |
50 | static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx; | 51 | static DOTCONF_CB(dco_listen_socket) { dc_context *dcc = (dc_context*)ctx; |
51 | dcc->cf->listen_socket = cmd->data.str; | 52 | dcc->cf->listen_socket = cmd->data.str; |
52 | dcc->cf->flags |= configuration::flag_listen_socket; | 53 | dcc->cf->flags |= configuration::flag_listen_socket; |
53 | return NULL; | 54 | return NULL; |
54 | } | 55 | } |
55 | static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx; | 56 | static DOTCONF_CB(dco_rc_file_name) { dc_context *dcc = (dc_context*)ctx; |
56 | dcc->cf->rc_file_name = cmd->data.str; | 57 | dcc->cf->rc_file_name = cmd->data.str; |
57 | dcc->cf->flags |= configuration::flag_rc_file_name; | 58 | dcc->cf->flags |= configuration::flag_rc_file_name; |
58 | return NULL; | 59 | return NULL; |
59 | } | 60 | } |
60 | static DOTCONF_CB(dco_min_children) { dc_context *dcc = (dc_context*)ctx; | 61 | static DOTCONF_CB(dco_min_children) { dc_context *dcc = (dc_context*)ctx; |
61 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) | 62 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) |
62 | return "MinChildren is too big"; | 63 | return "MinChildren is too big"; |
63 | dcc->cf->min_children = cmd->data.value; | 64 | dcc->cf->min_children = cmd->data.value; |
64 | dcc->cf->flags |= configuration::flag_min_children; | 65 | dcc->cf->flags |= configuration::flag_min_children; |
65 | return NULL; | 66 | return NULL; |
66 | } | 67 | } |
67 | static DOTCONF_CB(dco_max_children) { dc_context *dcc = (dc_context*)ctx; | 68 | static DOTCONF_CB(dco_max_children) { dc_context *dcc = (dc_context*)ctx; |
68 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) | 69 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) |
69 | return "MaxChildren is too big"; | 70 | return "MaxChildren is too big"; |
70 | dcc->cf->max_children = cmd->data.value; | 71 | dcc->cf->max_children = cmd->data.value; |
71 | dcc->cf->flags |= configuration::flag_max_children; | 72 | dcc->cf->flags |= configuration::flag_max_children; |
72 | return NULL; | 73 | return NULL; |
73 | } | 74 | } |
74 | static DOTCONF_CB(dco_min_spare_children) { dc_context *dcc = (dc_context*)ctx; | 75 | static DOTCONF_CB(dco_min_spare_children) { dc_context *dcc = (dc_context*)ctx; |
75 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) | 76 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) |
76 | return "MinSpareChildren is too big"; | 77 | return "MinSpareChildren is too big"; |
77 | dcc->cf->min_spare_children = cmd->data.value; | 78 | dcc->cf->min_spare_children = cmd->data.value; |
78 | dcc->cf->flags |= configuration::flag_min_spare_children; | 79 | dcc->cf->flags |= configuration::flag_min_spare_children; |
79 | return NULL; | 80 | return NULL; |
80 | } | 81 | } |
81 | static DOTCONF_CB(dco_max_spare_children) { dc_context *dcc = (dc_context*)ctx; | 82 | static DOTCONF_CB(dco_max_spare_children) { dc_context *dcc = (dc_context*)ctx; |
82 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) | 83 | if(cmd->data.value>=MAX_SITECING_SCOREBOARD_SLOTS) |
83 | return "MaxSpareChildren is too big"; | 84 | return "MaxSpareChildren is too big"; |
84 | dcc->cf->max_spare_children = cmd->data.value; | 85 | dcc->cf->max_spare_children = cmd->data.value; |
85 | dcc->cf->flags |= configuration::flag_max_spare_children; | 86 | dcc->cf->flags |= configuration::flag_max_spare_children; |
86 | return NULL; | 87 | return NULL; |
87 | } | 88 | } |
88 | static DOTCONF_CB(dco_requests_per_child) { dc_context *dcc = (dc_context*)ctx; | 89 | static DOTCONF_CB(dco_requests_per_child) { dc_context *dcc = (dc_context*)ctx; |
89 | dcc->cf->requests_per_child = cmd->data.value; | 90 | dcc->cf->requests_per_child = cmd->data.value; |
90 | dcc->cf->flags |= configuration::flag_requests_per_child; | 91 | dcc->cf->flags |= configuration::flag_requests_per_child; |
91 | return NULL; | 92 | return NULL; |
92 | } | 93 | } |
93 | static DOTCONF_CB(dco_multi_process) { dc_context *dcc = (dc_context*)ctx; | 94 | static DOTCONF_CB(dco_multi_process) { dc_context *dcc = (dc_context*)ctx; |
94 | dcc->cf->multi_process = cmd->data.value; | 95 | dcc->cf->multi_process = cmd->data.value; |
95 | dcc->cf->flags |= configuration::flag_multi_process; | 96 | dcc->cf->flags |= configuration::flag_multi_process; |
96 | return NULL; | 97 | return NULL; |
97 | } | 98 | } |
98 | static DOTCONF_CB(dco_user) { dc_context *dcc = (dc_context*)ctx; | 99 | static DOTCONF_CB(dco_user) { dc_context *dcc = (dc_context*)ctx; |
99 | dcc->cf->user = cmd->data.str; | 100 | dcc->cf->user = cmd->data.str; |
100 | dcc->cf->flags |= configuration::flag_user; | 101 | dcc->cf->flags |= configuration::flag_user; |
101 | return NULL; | 102 | return NULL; |
102 | } | 103 | } |
103 | static DOTCONF_CB(dco_group) { dc_context *dcc = (dc_context*)ctx; | 104 | static DOTCONF_CB(dco_group) { dc_context *dcc = (dc_context*)ctx; |
104 | dcc->cf->group = cmd->data.str; | 105 | dcc->cf->group = cmd->data.str; |
105 | dcc->cf->flags |= configuration::flag_group; | 106 | dcc->cf->flags |= configuration::flag_group; |
106 | return NULL; | 107 | return NULL; |
107 | } | 108 | } |
108 | static DOTCONF_CB(dco_chroot) { dc_context *dcc = (dc_context*)ctx; | 109 | static DOTCONF_CB(dco_chroot) { dc_context *dcc = (dc_context*)ctx; |
109 | dcc->cf->chroot = cmd->data.str; | 110 | dcc->cf->chroot = cmd->data.str; |
110 | dcc->cf->flags |= configuration::flag_chroot; | 111 | dcc->cf->flags |= configuration::flag_chroot; |
111 | return NULL; | 112 | return NULL; |
112 | } | 113 | } |
113 | static DOTCONF_CB(dco_pid_file) { dc_context *dcc = (dc_context*)ctx; | 114 | static DOTCONF_CB(dco_pid_file) { dc_context *dcc = (dc_context*)ctx; |
114 | dcc->cf->pid_file = cmd->data.str; | 115 | dcc->cf->pid_file = cmd->data.str; |
115 | dcc->cf->flags |= configuration::flag_pid_file; | 116 | dcc->cf->flags |= configuration::flag_pid_file; |
116 | return NULL; | 117 | return NULL; |
117 | } | 118 | } |
118 | static DOTCONF_CB(dco_daemonize) { dc_context *dcc = (dc_context*) ctx; | 119 | static DOTCONF_CB(dco_daemonize) { dc_context *dcc = (dc_context*) ctx; |
119 | dcc->cf->daemonize = cmd->data.value; | 120 | dcc->cf->daemonize = cmd->data.value; |
120 | dcc->cf->flags |= configuration::flag_daemonize; | 121 | dcc->cf->flags |= configuration::flag_daemonize; |
121 | return NULL; | 122 | return NULL; |
122 | } | 123 | } |
123 | 124 | ||
124 | static DOTCONF_CB(dco_path) { dc_context *dcc = (dc_context*)ctx; | 125 | static DOTCONF_CB(dco_path) { dc_context *dcc = (dc_context*)ctx; |
125 | string path = cmd->data.str; | 126 | string path = cmd->data.str; |
126 | if(path[path.length()-1]=='>') | 127 | if(path[path.length()-1]=='>') |
127 | path.erase(path.length()-1); | 128 | path.erase(path.length()-1); |
128 | // TODO: normalize path | 129 | // TODO: normalize path |
129 | dcc->co.push_front(&(dcc->cf->specs[path])); | 130 | dcc->co.push_front(&(dcc->cf->specs[path])); |
130 | dcc->ctx = DCC_PATH; // TODO: stack it, instead | 131 | dcc->ctx = DCC_PATH; // TODO: stack it, instead |
131 | return NULL; | 132 | return NULL; |
132 | } | 133 | } |
133 | static DOTCONF_CB(dco__path) { dc_context *dcc = (dc_context*)ctx; | 134 | static DOTCONF_CB(dco__path) { dc_context *dcc = (dc_context*)ctx; |
134 | dcc->co.pop_front(); | 135 | dcc->co.pop_front(); |
135 | assert(dcc->co.size()); | 136 | assert(dcc->co.size()); |
136 | dcc->ctx = DCC_ROOT; // TODO: stack it, instead | 137 | dcc->ctx = DCC_ROOT; // TODO: stack it, instead |
137 | return NULL; | 138 | return NULL; |
138 | } | 139 | } |
139 | 140 | ||
140 | static DOTCONF_CB(dco_skeleton) { dc_context *dcc = (dc_context*)ctx; | 141 | static DOTCONF_CB(dco_skeleton) { dc_context *dcc = (dc_context*)ctx; |
141 | dcc->co.front()->skeleton = cmd->data.str; | 142 | dcc->co.front()->skeleton = cmd->data.str; |
142 | dcc->co.front()->flags |= config_options::flag_skeleton; | 143 | dcc->co.front()->flags |= config_options::flag_skeleton; |
143 | return NULL; | 144 | return NULL; |
144 | } | 145 | } |
145 | static DOTCONF_CB(dco_cpp_flags) { dc_context *dcc = (dc_context*)ctx; | 146 | static DOTCONF_CB(dco_cpp_flags) { dc_context *dcc = (dc_context*)ctx; |
146 | for(char **arg=cmd->data.list;*arg;arg++) | 147 | for(char **arg=cmd->data.list;*arg;arg++) |
147 | dcc->co.front()->cpp_flags.push_back(*arg); | 148 | dcc->co.front()->cpp_flags.push_back(*arg); |
148 | dcc->co.front()->flags |= config_options::flag_cpp_flags; | 149 | dcc->co.front()->flags |= config_options::flag_cpp_flags; |
149 | return NULL; | 150 | return NULL; |
150 | } | 151 | } |
151 | static DOTCONF_CB(dco_ld_flags) { dc_context *dcc = (dc_context*)ctx; | 152 | static DOTCONF_CB(dco_ld_flags) { dc_context *dcc = (dc_context*)ctx; |
152 | for(char **arg=cmd->data.list;*arg;arg++) | 153 | for(char **arg=cmd->data.list;*arg;arg++) |
153 | dcc->co.front()->ld_flags.push_back(*arg); | 154 | dcc->co.front()->ld_flags.push_back(*arg); |
154 | dcc->co.front()->flags |= config_options::flag_ld_flags; | 155 | dcc->co.front()->flags |= config_options::flag_ld_flags; |
155 | return NULL; | 156 | return NULL; |
156 | } | 157 | } |
157 | static DOTCONF_CB(dco_intermediate_deps) { dc_context *dcc = (dc_context*) ctx; | 158 | static DOTCONF_CB(dco_intermediate_deps) { dc_context *dcc = (dc_context*) ctx; |
158 | for(char **arg=cmd->data.list;*arg;arg++) | 159 | for(char **arg=cmd->data.list;*arg;arg++) |
159 | dcc->co.front()->intermediate_deps.push_back(*arg); | 160 | dcc->co.front()->intermediate_deps.push_back(*arg); |
160 | dcc->co.front()->flags |= config_options::flag_intermediate_deps; | 161 | dcc->co.front()->flags |= config_options::flag_intermediate_deps; |
161 | return NULL; | 162 | return NULL; |
162 | } | 163 | } |
163 | static DOTCONF_CB(dco_so_deps) { dc_context *dcc = (dc_context*) ctx; | 164 | static DOTCONF_CB(dco_so_deps) { dc_context *dcc = (dc_context*) ctx; |
164 | for(char **arg=cmd->data.list;*arg;arg++) | 165 | for(char **arg=cmd->data.list;*arg;arg++) |
165 | dcc->co.front()->so_deps.push_back(*arg); | 166 | dcc->co.front()->so_deps.push_back(*arg); |
166 | dcc->co.front()->flags |= config_options::flag_so_deps; | 167 | dcc->co.front()->flags |= config_options::flag_so_deps; |
167 | return NULL; | 168 | return NULL; |
168 | } | 169 | } |
169 | static DOTCONF_CB(dco_build) { dc_context *dcc = (dc_context*)ctx; | 170 | static DOTCONF_CB(dco_build) { dc_context *dcc = (dc_context*)ctx; |
170 | dcc->co.front()->build = cmd->data.value; | 171 | dcc->co.front()->build = cmd->data.value; |
171 | dcc->co.front()->flags |= config_options::flag_build; | 172 | dcc->co.front()->flags |= config_options::flag_build; |
172 | return NULL; | 173 | return NULL; |
173 | } | 174 | } |
174 | static DOTCONF_CB(dco_cpp_deps) { dc_context *dcc = (dc_context*)ctx; | 175 | static DOTCONF_CB(dco_cpp_deps) { dc_context *dcc = (dc_context*)ctx; |
175 | dcc->co.front()->cpp_deps = cmd->data.value; | 176 | dcc->co.front()->cpp_deps = cmd->data.value; |
176 | dcc->co.front()->flags |= config_options::flag_cpp_deps; | 177 | dcc->co.front()->flags |= config_options::flag_cpp_deps; |
177 | return NULL; | 178 | return NULL; |
178 | } | 179 | } |
179 | static DOTCONF_CB(dco_exception_handler) { dc_context *dcc = (dc_context*)ctx; | 180 | static DOTCONF_CB(dco_exception_handler) { dc_context *dcc = (dc_context*)ctx; |
180 | dcc->co.front()->exception_handler = cmd->data.str; | 181 | dcc->co.front()->exception_handler = cmd->data.str; |
181 | dcc->co.front()->flags |= config_options::flag_exception_handler; | 182 | dcc->co.front()->flags |= config_options::flag_exception_handler; |
182 | return NULL; | 183 | return NULL; |
183 | } | 184 | } |
184 | static DOTCONF_CB(dco_http_status_handler) { dc_context *dcc = (dc_context*)ctx; | 185 | static DOTCONF_CB(dco_http_status_handler) { dc_context *dcc = (dc_context*)ctx; |
185 | if(cmd->arg_count!=2) | 186 | if(cmd->arg_count!=2) |
186 | return "Invalid number of arguments"; | 187 | return "Invalid number of arguments"; |
187 | dcc->co.front()->http_status_handlers[cmd->data.list[0]] = cmd->data.list[1]; | 188 | dcc->co.front()->http_status_handlers[cmd->data.list[0]] = cmd->data.list[1]; |
188 | dcc->co.front()->flags |= config_options::flag_http_status_handlers; | 189 | dcc->co.front()->flags |= config_options::flag_http_status_handlers; |
189 | return NULL; | 190 | return NULL; |
190 | } | 191 | } |
191 | static DOTCONF_CB(dco_action) { dc_context *dcc = (dc_context*)ctx; | 192 | static DOTCONF_CB(dco_action) { dc_context *dcc = (dc_context*)ctx; |
192 | if(cmd->arg_count<2) | 193 | if(cmd->arg_count<2) |
193 | return "Invalid number of arguments"; | 194 | return "Invalid number of arguments"; |
194 | try { | 195 | try { |
195 | char **arg=cmd->data.list; | 196 | char **arg=cmd->data.list; |
196 | dcc->co.front()->action_handlers.push_back(config_options::action_handler_t(arg[0],arg[1])); | 197 | dcc->co.front()->action_handlers.push_back(config_options::action_handler_t(arg[0],arg[1])); |
197 | for(arg+=2;*arg;arg++) | 198 | for(arg+=2;*arg;arg++) |
198 | dcc->co.front()->action_handlers.back().args.push_back(*arg); | 199 | dcc->co.front()->action_handlers.back().args.push_back(*arg); |
199 | dcc->co.front()->flags |= config_options::flag_action_handlers; | 200 | dcc->co.front()->flags |= config_options::flag_action_handlers; |
200 | }catch(exception& e) { | 201 | }catch(exception& e) { |
201 | return "Error processing Action directive"; // XXX: could be done better | 202 | return "Error processing Action directive"; // XXX: could be done better |
202 | } | 203 | } |
203 | return NULL; | 204 | return NULL; |
204 | } | 205 | } |
205 | static DOTCONF_CB(dco_auto_build_files) { dc_context *dcc = (dc_context*)ctx; | 206 | static DOTCONF_CB(dco_auto_build_files) { dc_context *dcc = (dc_context*)ctx; |
206 | if(!( dcc->cf && dcc->cf->autobuild)) | 207 | if(!( dcc->cf && dcc->cf->autobuild)) |
207 | return NULL; | 208 | return NULL; |
208 | for(char **arg=cmd->data.list;*arg;arg++) | 209 | for(char **arg=cmd->data.list;*arg;arg++) |
209 | dcc->co.front()->auto_build_files.push_back(*arg); | 210 | dcc->co.front()->auto_build_files.push_back(*arg); |
210 | dcc->co.front()->flags |= config_options::flag_auto_build_files; | 211 | dcc->co.front()->flags |= config_options::flag_auto_build_files; |
211 | return NULL; | 212 | return NULL; |
212 | } | 213 | } |
213 | 214 | ||
214 | static const configoption_t dc_options[] = { | 215 | static const configoption_t dc_options[] = { |
215 | { "RootSource", ARG_STR, dco_root_source, NULL, DCC_ROOT }, | 216 | { "RootSource", ARG_STR, dco_root_source, NULL, DCC_ROOT }, |
216 | { "RootIntermediate", ARG_STR, dco_root_intermediate, NULL, DCC_ROOT }, | 217 | { "RootIntermediate", ARG_STR, dco_root_intermediate, NULL, DCC_ROOT }, |
217 | { "RootSO", ARG_STR, dco_root_so, NULL, DCC_ROOT }, | 218 | { "RootSO", ARG_STR, dco_root_so, NULL, DCC_ROOT }, |
218 | { "ListenSocket", ARG_STR, dco_listen_socket, NULL, DCC_ROOT }, | 219 | { "ListenSocket", ARG_STR, dco_listen_socket, NULL, DCC_ROOT }, |
219 | { "RCFileName", ARG_STR, dco_rc_file_name, NULL, DCC_ROOT }, | 220 | { "RCFileName", ARG_STR, dco_rc_file_name, NULL, DCC_ROOT }, |
220 | { "MinChildren", ARG_INT, dco_min_children, NULL, DCC_ROOT }, | 221 | { "MinChildren", ARG_INT, dco_min_children, NULL, DCC_ROOT }, |
221 | { "MaxChildren", ARG_INT, dco_max_children, NULL, DCC_ROOT }, | 222 | { "MaxChildren", ARG_INT, dco_max_children, NULL, DCC_ROOT }, |
222 | { "MinSpareChildren", ARG_INT, dco_min_spare_children, NULL, DCC_ROOT }, | 223 | { "MinSpareChildren", ARG_INT, dco_min_spare_children, NULL, DCC_ROOT }, |
223 | { "MaxSpareChildren", ARG_INT, dco_max_spare_children, NULL, DCC_ROOT }, | 224 | { "MaxSpareChildren", ARG_INT, dco_max_spare_children, NULL, DCC_ROOT }, |
224 | { "RequestsPerChild", ARG_INT, dco_requests_per_child, NULL, DCC_ROOT }, | 225 | { "RequestsPerChild", ARG_INT, dco_requests_per_child, NULL, DCC_ROOT }, |
225 | { "MultiProcess", ARG_TOGGLE, dco_multi_process, NULL, DCC_ROOT }, | 226 | { "MultiProcess", ARG_TOGGLE, dco_multi_process, NULL, DCC_ROOT }, |
226 | { "User", ARG_STR, dco_user, NULL, DCC_ROOT }, | 227 | { "User", ARG_STR, dco_user, NULL, DCC_ROOT }, |
227 | { "Group", ARG_STR, dco_group, NULL, DCC_ROOT }, | 228 | { "Group", ARG_STR, dco_group, NULL, DCC_ROOT }, |
228 | { "Chroot", ARG_STR, dco_chroot, NULL, DCC_ROOT }, | 229 | { "Chroot", ARG_STR, dco_chroot, NULL, DCC_ROOT }, |
229 | { "PidFile", ARG_STR, dco_pid_file, NULL, DCC_ROOT }, | 230 | { "PidFile", ARG_STR, dco_pid_file, NULL, DCC_ROOT }, |
230 | { "Daemonize", ARG_TOGGLE, dco_daemonize, NULL, DCC_ROOT }, | 231 | { "Daemonize", ARG_TOGGLE, dco_daemonize, NULL, DCC_ROOT }, |
231 | { "<Path", ARG_STR, dco_path, NULL, DCC_ROOT }, | 232 | { "<Path", ARG_STR, dco_path, NULL, DCC_ROOT }, |
232 | { "Skeleton", ARG_STR, dco_skeleton, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 233 | { "Skeleton", ARG_STR, dco_skeleton, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
233 | { "CPPFLAGS", ARG_LIST, dco_cpp_flags, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 234 | { "CPPFLAGS", ARG_LIST, dco_cpp_flags, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
234 | { "LDFLAGS", ARG_LIST, dco_ld_flags, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 235 | { "LDFLAGS", ARG_LIST, dco_ld_flags, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
235 | { "Build", ARG_TOGGLE, dco_build, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 236 | { "Build", ARG_TOGGLE, dco_build, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
236 | { "CPPDeps", ARG_TOGGLE, dco_cpp_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 237 | { "CPPDeps", ARG_TOGGLE, dco_cpp_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
237 | { "ExceptionHandler", ARG_STR, dco_exception_handler, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 238 | { "ExceptionHandler", ARG_STR, dco_exception_handler, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
238 | { "HTTPStatusHandler", ARG_LIST, dco_http_status_handler, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 239 | { "HTTPStatusHandler", ARG_LIST, dco_http_status_handler, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
239 | { "IntermediateDeps", ARG_LIST, dco_intermediate_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 240 | { "IntermediateDeps", ARG_LIST, dco_intermediate_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
240 | { "SODeps", ARG_LIST, dco_so_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 241 | { "SODeps", ARG_LIST, dco_so_deps, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
241 | { "Action", ARG_LIST, dco_action, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 242 | { "Action", ARG_LIST, dco_action, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
242 | { "AutoBuildFiles", ARG_LIST, dco_auto_build_files, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, | 243 | { "AutoBuildFiles", ARG_LIST, dco_auto_build_files, NULL, DCC_ROOT|DCC_PATH|DCC_SCRC }, |
243 | { "</Path>", ARG_NONE, dco__path, NULL, DCC_PATH }, | 244 | { "</Path>", ARG_NONE, dco__path, NULL, DCC_PATH }, |
244 | LAST_OPTION | 245 | LAST_OPTION |
245 | }; | 246 | }; |
246 | 247 | ||
247 | static const char *dc_context_checker(command_t *cmd,unsigned long mask) { | 248 | static const char *dc_context_checker(command_t *cmd,unsigned long mask) { |
248 | dc_context *dcc = (dc_context*)cmd->context; | 249 | dc_context *dcc = (dc_context*)cmd->context; |
249 | if( (mask==CTX_ALL) || ((mask&dcc->ctx)==dcc->ctx) ) | 250 | if( (mask==CTX_ALL) || ((mask&dcc->ctx)==dcc->ctx) ) |
250 | return NULL; | 251 | return NULL; |
251 | return "misplaced option"; | 252 | return "misplaced option"; |
252 | } | 253 | } |
253 | static FUNC_ERRORHANDLER(dc_error_handler) { | 254 | static FUNC_ERRORHANDLER(dc_error_handler) { |
254 | throw konforka::exception(CODEPOINT,string("error parsing config file: ")+msg); | 255 | throw konforka::exception(CODEPOINT,string("error parsing config file: ")+msg); |
255 | } | 256 | } |
256 | 257 | ||
257 | bool loaded_options::is_valid() { | 258 | bool loaded_options::is_valid() { |
258 | struct stat nst; | 259 | struct stat nst; |
259 | if(stat(source_file.c_str(),&nst)) | 260 | if(stat(source_file.c_str(),&nst)) |
260 | return false; | 261 | return false; |
261 | if(st.st_mtime!=nst.st_mtime) | 262 | if(st.st_mtime!=nst.st_mtime) |
262 | return false; | 263 | return false; |
263 | return true; | 264 | return true; |
264 | } | 265 | } |
265 | 266 | ||
266 | loaded_options *configuration::lookup_loaded_options(const string& target) { | 267 | loaded_options *configuration::lookup_loaded_options(const string& target) { |
267 | // we assume 'target' is a directory with trailing slash appended | 268 | // we assume 'target' is a directory with trailing slash appended |
268 | string scrc = root_source+target; | 269 | string scrc = root_source+target; |
269 | if(flags&flag_rc_file_name) | 270 | if(flags&flag_rc_file_name) |
270 | scrc += rc_file_name; | 271 | scrc += rc_file_name; |
271 | else | 272 | else |
272 | scrc += ".scrc"; | 273 | scrc += ".scrc"; |
273 | // TODO: normalize me, anyway. | 274 | // TODO: normalize me, anyway. |
274 | if(access(scrc.c_str(),R_OK)) | 275 | if(access(scrc.c_str(),R_OK)) |
275 | return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal | 276 | return 0; // TODO FIXME: this approach leaves already loaded .scrcs around in case of removal |
276 | loaded_specs_t::iterator i = loaded_specs.find(target); | 277 | loaded_specs_t::iterator i = loaded_specs.find(target); |
277 | if(i==loaded_specs.end() || !i->second.is_valid()) { | 278 | if(i==loaded_specs.end() || !i->second.is_valid()) { |
278 | if(i!=loaded_specs.end()) | 279 | if(i!=loaded_specs.end()) |
279 | loaded_specs.erase(i); | 280 | loaded_specs.erase(i); |
280 | pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); | 281 | pair<loaded_specs_t::iterator,bool> ii = loaded_specs.insert(loaded_specs_t::value_type(target,loaded_options())); |
281 | assert(ii.first!=loaded_specs.end()); | 282 | assert(ii.first!=loaded_specs.end()); |
282 | ii.first->second.parse(this,scrc); | 283 | ii.first->second.parse(this,scrc); |
283 | i = ii.first; | 284 | i = ii.first; |
284 | } | 285 | } |
285 | assert(i!=loaded_specs.end()); | 286 | assert(i!=loaded_specs.end()); |
286 | return &(i->second); | 287 | return &(i->second); |
287 | } | 288 | } |
288 | 289 | ||
289 | config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { | 290 | config_options::action_handler_t *config_options::lookup_action_handler(const string& target) { |
290 | for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) { | 291 | for(action_handlers_t::iterator i=action_handlers.begin();i!=action_handlers.end();++i) { |
291 | if(i->regex.search(target)) | 292 | if(i->regex.search(target)) |
292 | return &*i; | 293 | return &*i; |
293 | } | 294 | } |
294 | return NULL; | 295 | return NULL; |
295 | } | 296 | } |
296 | 297 | ||
297 | string config_options::lookup_http_status_handler(const string& status) { | 298 | string config_options::lookup_http_status_handler(const string& status) { |
298 | http_status_handlers_t::const_iterator i = http_status_handlers.find(status); | 299 | http_status_handlers_t::const_iterator i = http_status_handlers.find(status); |
299 | string rv; | 300 | string rv; |
300 | if(i!=http_status_handlers.end()) | 301 | if(i!=http_status_handlers.end()) |
301 | rv = i->second; | 302 | rv = i->second; |
302 | return rv; | 303 | return rv; |
303 | } | 304 | } |
304 | 305 | ||
305 | string configuration::lookup_http_status_handler(const string& target,const string& status) { | 306 | string configuration::lookup_http_status_handler(const string& target,const string& status) { |
306 | string t = "/"; | 307 | string t = "/"; |
307 | t += normalize_path(target,strip_leading_slash); | 308 | t += konforka::normalize_path(target,konforka::strip_leading_slash); |
308 | string rv; | 309 | string rv; |
309 | for(;;) { | 310 | for(;;) { |
310 | if(t[t.length()-1]=='/') { | 311 | if(t[t.length()-1]=='/') { |
311 | loaded_options* lo = lookup_loaded_options(t); | 312 | loaded_options* lo = lookup_loaded_options(t); |
312 | if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { | 313 | if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { |
313 | rv = lo->lookup_http_status_handler(status); | 314 | rv = lo->lookup_http_status_handler(status); |
314 | if(!rv.empty()) | 315 | if(!rv.empty()) |
315 | return rv; | 316 | return rv; |
316 | } | 317 | } |
317 | } | 318 | } |
318 | specs_t::iterator i = specs.find(t); | 319 | specs_t::iterator i = specs.find(t); |
319 | if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { | 320 | if( i!=specs.end() && (i->second.flags&&config_options::flag_http_status_handlers) ) { |
320 | rv = i->second.lookup_http_status_handler(status); | 321 | rv = i->second.lookup_http_status_handler(status); |
321 | if(!rv.empty()) | 322 | if(!rv.empty()) |
322 | return rv; | 323 | return rv; |
323 | } | 324 | } |
324 | if(t.empty()) | 325 | if(t.empty()) |
325 | return rv; | 326 | return rv; |
326 | string::size_type sl=t.rfind('/'); | 327 | string::size_type sl=t.rfind('/'); |
327 | if(sl==string::npos) { | 328 | if(sl==string::npos) { |
328 | t.erase(); | 329 | t.erase(); |
329 | }else{ | 330 | }else{ |
330 | if(sl==(t.length()-1)) | 331 | if(sl==(t.length()-1)) |
331 | t.erase(sl); | 332 | t.erase(sl); |
332 | else | 333 | else |
333 | t.erase(sl+1); | 334 | t.erase(sl+1); |
334 | } | 335 | } |
335 | } | 336 | } |
336 | } | 337 | } |
337 | 338 | ||
338 | config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { | 339 | config_options::action_handler_t *configuration::lookup_action_handler(const string& target) { |
339 | string t = "/"; | 340 | string t = "/"; |
340 | t += normalize_path(target,strip_leading_slash); | 341 | t += konforka::normalize_path(target,konforka::strip_leading_slash); |
341 | for(;;) { | 342 | for(;;) { |
342 | if(t[t.length()-1]=='/') { | 343 | if(t[t.length()-1]=='/') { |
343 | loaded_options* lo = lookup_loaded_options(t); | 344 | loaded_options* lo = lookup_loaded_options(t); |
344 | if( lo && (lo->flags&config_options::flag_action_handlers) ) { | 345 | if( lo && (lo->flags&config_options::flag_action_handlers) ) { |
345 | config_options::action_handler_t *rv = lo->lookup_action_handler(target); | 346 | config_options::action_handler_t *rv = lo->lookup_action_handler(target); |
346 | if(rv) | 347 | if(rv) |
347 | return rv; | 348 | return rv; |
348 | } | 349 | } |
349 | } | 350 | } |
350 | specs_t::iterator i = specs.find(t); | 351 | specs_t::iterator i = specs.find(t); |
351 | if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { | 352 | if( i!=specs.end() && (i->second.flags&&config_options::flag_action_handlers) ) { |
352 | config_options::action_handler_t *rv = i->second.lookup_action_handler(target); | 353 | config_options::action_handler_t *rv = i->second.lookup_action_handler(target); |
353 | if(rv) | 354 | if(rv) |
354 | return rv; | 355 | return rv; |
355 | } | 356 | } |
356 | if(t.empty()) | 357 | if(t.empty()) |
357 | return NULL; | 358 | return NULL; |
358 | string::size_type sl=t.rfind('/'); | 359 | string::size_type sl=t.rfind('/'); |
359 | if(sl==string::npos) { | 360 | if(sl==string::npos) { |
360 | t.erase(); | 361 | t.erase(); |
361 | }else{ | 362 | }else{ |
362 | if(sl==(t.length()-1)) | 363 | if(sl==(t.length()-1)) |
363 | t.erase(sl); | 364 | t.erase(sl); |
364 | else | 365 | else |
365 | t.erase(sl+1); | 366 | t.erase(sl+1); |
366 | } | 367 | } |
367 | } | 368 | } |
368 | } | 369 | } |
369 | 370 | ||
370 | config_options* configuration::lookup_config(const string& target,int flag) { | 371 | config_options* configuration::lookup_config(const string& target,int flag) { |
371 | string t = "/"; // always assume leading slash | 372 | string t = "/"; // always assume leading slash |
372 | t += normalize_path(target,strip_leading_slash); | 373 | t += konforka::normalize_path(target,konforka::strip_leading_slash); |
373 | // XXX: reconsider precedence | 374 | // XXX: reconsider precedence |
374 | for(;;) { | 375 | for(;;) { |
375 | if(t[t.length()-1]=='/') { | 376 | if(t[t.length()-1]=='/') { |
376 | loaded_options* lo = lookup_loaded_options(t); | 377 | loaded_options* lo = lookup_loaded_options(t); |
377 | if( lo && (lo->flags&flag)==flag ) | 378 | if( lo && (lo->flags&flag)==flag ) |
378 | return lo; | 379 | return lo; |
379 | } | 380 | } |
380 | specs_t::iterator i = specs.find(t); | 381 | specs_t::iterator i = specs.find(t); |
381 | if( i!=specs.end() && (i->second.flags&flag)==flag ) | 382 | if( i!=specs.end() && (i->second.flags&flag)==flag ) |
382 | return &(i->second); | 383 | return &(i->second); |
383 | if(t.empty()) | 384 | if(t.empty()) |
384 | return NULL; | 385 | return NULL; |
385 | string::size_type sl=t.rfind('/'); | 386 | string::size_type sl=t.rfind('/'); |
386 | if(sl==string::npos) { | 387 | if(sl==string::npos) { |
387 | t.erase(); | 388 | t.erase(); |
388 | }else{ | 389 | }else{ |
389 | if(sl==(t.length()-1)) | 390 | if(sl==(t.length()-1)) |
390 | t.erase(sl); | 391 | t.erase(sl); |
391 | else | 392 | else |
392 | t.erase(sl+1); | 393 | t.erase(sl+1); |
393 | } | 394 | } |
394 | } | 395 | } |
395 | } | 396 | } |
396 | 397 | ||
397 | bool config_options::match_autobuild_files(const char *fn,bool &rv) { | 398 | bool config_options::match_autobuild_files(const char *fn,bool &rv) { |
398 | for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) { | 399 | for(list<string>::reverse_iterator i=auto_build_files.rbegin();i!=auto_build_files.rend();++i) { |
399 | const char *pat = i->c_str(); | 400 | const char *pat = i->c_str(); |
400 | bool plus = true; | 401 | bool plus = true; |
401 | if((*pat)=='+') | 402 | if((*pat)=='+') |
402 | pat++; | 403 | pat++; |
403 | else if((*pat)=='-') { | 404 | else if((*pat)=='-') { |
404 | plus = false; | 405 | plus = false; |
405 | pat++; | 406 | pat++; |
406 | } | 407 | } |
407 | if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { | 408 | if(!fnmatch(pat,fn,FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD)) { |
408 | rv = plus; | 409 | rv = plus; |
409 | return true; | 410 | return true; |
410 | } | 411 | } |
411 | } | 412 | } |
412 | return false; | 413 | return false; |
413 | } | 414 | } |
414 | 415 | ||
415 | bool configuration::match_autobuild_files(const string& target,const char *fn) { | 416 | bool configuration::match_autobuild_files(const string& target,const char *fn) { |
416 | string t = "/"; | 417 | string t = "/"; |
417 | t += normalize_path(target,strip_leading_slash|strip_trailing_slash); | 418 | t += konforka::normalize_path(target,konforka::strip_leading_slash|konforka::strip_trailing_slash); |
418 | t += "/"; | 419 | t += "/"; |
419 | bool rv = false; | 420 | bool rv = false; |
420 | for(;;) { | 421 | for(;;) { |
421 | if(t[t.length()-1]=='/') { | 422 | if(t[t.length()-1]=='/') { |
422 | loaded_options* lo = lookup_loaded_options(t); | 423 | loaded_options* lo = lookup_loaded_options(t); |
423 | if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) ) | 424 | if(lo && (lo->flags&config_options::flag_auto_build_files) && lo->match_autobuild_files(fn,rv) ) |
424 | return rv; | 425 | return rv; |
425 | } | 426 | } |
426 | specs_t::iterator i = specs.find(t); | 427 | specs_t::iterator i = specs.find(t); |
427 | if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) ) | 428 | if( i!=specs.end() && (i->second.flags&config_options::flag_auto_build_files) && i->second.match_autobuild_files(fn,rv) ) |
428 | return rv; | 429 | return rv; |
429 | if(t.empty()) | 430 | if(t.empty()) |
430 | return rv; | 431 | return rv; |
431 | string::size_type sl=t.rfind('/'); | 432 | string::size_type sl=t.rfind('/'); |
432 | if(sl==string::npos) { | 433 | if(sl==string::npos) { |
433 | t.erase(); | 434 | t.erase(); |
434 | }else{ | 435 | }else{ |
435 | if(sl==(t.length()-1)) | 436 | if(sl==(t.length()-1)) |
436 | t.erase(sl); | 437 | t.erase(sl); |
437 | else | 438 | else |
438 | t.erase(sl+1); | 439 | t.erase(sl+1); |
439 | } | 440 | } |
440 | } | 441 | } |
441 | } | 442 | } |
442 | 443 | ||
443 | void configuration::parse(const string& cfile) { | 444 | void configuration::parse(const string& cfile) { |
444 | struct dc_context dcc; | 445 | struct dc_context dcc; |
445 | dcc.cf = this; | 446 | dcc.cf = this; |
446 | dcc.ctx = DCC_ROOT; | 447 | dcc.ctx = DCC_ROOT; |
447 | dcc.co.push_front(&root_options()); | 448 | dcc.co.push_front(&root_options()); |
448 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); | 449 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); |
449 | if(!cf) | 450 | if(!cf) |
450 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); | 451 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); |
451 | cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; | 452 | cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; |
452 | cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; | 453 | cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; |
453 | if(!dotconf_command_loop(cf)) | 454 | if(!dotconf_command_loop(cf)) |
454 | throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); | 455 | throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); |
455 | dotconf_cleanup(cf); | 456 | dotconf_cleanup(cf); |
456 | } | 457 | } |
457 | 458 | ||
458 | void loaded_options::parse(configuration *config,const string& cfile) { | 459 | void loaded_options::parse(configuration *config,const string& cfile) { |
459 | struct dc_context dcc; | 460 | struct dc_context dcc; |
460 | dcc.cf = config; | 461 | dcc.cf = config; |
461 | dcc.ctx = DCC_SCRC; | 462 | dcc.ctx = DCC_SCRC; |
462 | dcc.co.push_front(this); | 463 | dcc.co.push_front(this); |
463 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); | 464 | configfile_t *cf = dotconf_create((char*)cfile.c_str(),dc_options,(context_t*)&dcc,CASE_INSENSITIVE); |
464 | if(!cf) | 465 | if(!cf) |
465 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); | 466 | throw konforka::exception(CODEPOINT,"failed to dotconf_create()"); |
466 | cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; | 467 | cf->errorhandler = (dotconf_errorhandler_t) dc_error_handler; |
467 | cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; | 468 | cf->contextchecker = (dotconf_contextchecker_t) dc_context_checker; |
468 | if(!dotconf_command_loop(cf)) | 469 | if(!dotconf_command_loop(cf)) |
469 | throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); | 470 | throw konforka::exception(CODEPOINT,"failed to dotconf_command_loop()"); |
470 | dotconf_cleanup(cf); | 471 | dotconf_cleanup(cf); |
471 | source_file = cfile; | 472 | source_file = cfile; |
472 | stat(cfile.c_str(),&st); // TODO: handle errors? | 473 | stat(cfile.c_str(),&st); // TODO: handle errors? |
473 | } | 474 | } |
474 | } | 475 | } |
diff --git a/lib/sitecing_parser.ll b/lib/sitecing_parser.ll index 4fd6709..8dd8d5f 100644 --- a/lib/sitecing_parser.ll +++ b/lib/sitecing_parser.ll | |||
@@ -1,642 +1,643 @@ | |||
1 | %{ | 1 | %{ |
2 | /* | 2 | /* |
3 | * XXX: I have a strong feeling that this parser should be completely rewritten. | 3 | * XXX: I have a strong feeling that this parser should be completely rewritten. |
4 | */ | 4 | */ |
5 | #include <iostream> | 5 | #include <iostream> |
6 | #include <fstream> | 6 | #include <fstream> |
7 | #include <cassert> | 7 | #include <cassert> |
8 | #include <stdexcept> | 8 | #include <stdexcept> |
9 | using namespace std; | 9 | using namespace std; |
10 | #include <konforka/util.h> | ||
10 | #include "sitecing/sitecing_util.h" | 11 | #include "sitecing/sitecing_util.h" |
11 | #include "sitecing/sitecing_exception.h" | 12 | #include "sitecing/sitecing_exception.h" |
12 | using namespace sitecing; | 13 | using namespace sitecing; |
13 | #define sitecing_parser_flexlexer_once | 14 | #define sitecing_parser_flexlexer_once |
14 | #include "sitecing/sitecing_parser.h" | 15 | #include "sitecing/sitecing_parser.h" |
15 | #include "sitecing/sitecing_enflesher.h" | 16 | #include "sitecing/sitecing_enflesher.h" |
16 | #undef yyFlexLexer | 17 | #undef yyFlexLexer |
17 | #define yyFlexLexer sitecing_parserFlexLexer | 18 | #define yyFlexLexer sitecing_parserFlexLexer |
18 | %} | 19 | %} |
19 | %x SLASHSTAR_COMMENT SLASHSLASH_COMMENT STRING | 20 | %x SLASHSTAR_COMMENT SLASHSLASH_COMMENT STRING |
20 | %x CODELINE CLASSLINE DECLLINE IMPLLINE DECLBLOCK IMPLBLOCK VARLINE VARINIT | 21 | %x CODELINE CLASSLINE DECLLINE IMPLLINE DECLBLOCK IMPLBLOCK VARLINE VARINIT |
21 | %x IMPORTLINE IMPORTCOMPONENT | 22 | %x IMPORTLINE IMPORTCOMPONENT |
22 | %x IMPORTTYPELINE IMPORTTYPECOMPONENT | 23 | %x IMPORTTYPELINE IMPORTTYPECOMPONENT |
23 | %x DERIVELINE DERIVECOMPONENT | 24 | %x DERIVELINE DERIVECOMPONENT |
24 | %x CONSTRUCTOR DESTRUCTOR CODEMETHODLINE CODEMETHODARGS | 25 | %x CONSTRUCTOR DESTRUCTOR CODEMETHODLINE CODEMETHODARGS |
25 | %x CODEMETHODBLOCK INLINE METHODLINE METHODARGS METHODBLOCK CODEBLOCK OUTPUTBLOCK | 26 | %x CODEMETHODBLOCK INLINE METHODLINE METHODARGS METHODBLOCK CODEBLOCK OUTPUTBLOCK |
26 | %x PRAGMALINE | 27 | %x PRAGMALINE |
27 | %option 8bit c++ verbose noyywrap yyclass="sitecing_parser" prefix="sitecing_parser" stack yylineno | 28 | %option 8bit c++ verbose noyywrap yyclass="sitecing_parser" prefix="sitecing_parser" stack yylineno |
28 | 29 | ||
29 | WHITESPACE[ \t] | 30 | WHITESPACE[ \t] |
30 | ID [A-Za-z_][A-Za-z0-9_]* | 31 | ID [A-Za-z_][A-Za-z0-9_]* |
31 | NOIDCHAR[^A-Za-z0-9_] | 32 | NOIDCHAR[^A-Za-z0-9_] |
32 | 33 | ||
33 | %% | 34 | %% |
34 | 35 | ||
35 | <INITIAL>{ | 36 | <INITIAL>{ |
36 | ^\%\%class{WHITESPACE}+{ | 37 | ^\%\%class{WHITESPACE}+{ |
37 | // TODO: signal error if we already have class name acquired from source. | 38 | // TODO: signal error if we already have class name acquired from source. |
38 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments|modus_operandi::flag_devour_whitespace)); | 39 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments|modus_operandi::flag_devour_whitespace)); |
39 | BEGIN(CLASSLINE); | 40 | BEGIN(CLASSLINE); |
40 | } | 41 | } |
41 | ^\%\%decl{WHITESPACE}+{ | 42 | ^\%\%decl{WHITESPACE}+{ |
42 | modi.push_front(modus_operandi(0)); | 43 | modi.push_front(modus_operandi(0)); |
43 | anchor(); | 44 | anchor(); |
44 | BEGIN(DECLLINE); | 45 | BEGIN(DECLLINE); |
45 | } | 46 | } |
46 | ^\%\%impl{WHITESPACE}+{ | 47 | ^\%\%impl{WHITESPACE}+{ |
47 | modi.push_front(modus_operandi(0)); | 48 | modi.push_front(modus_operandi(0)); |
48 | anchor(); | 49 | anchor(); |
49 | BEGIN(IMPLLINE); | 50 | BEGIN(IMPLLINE); |
50 | } | 51 | } |
51 | \<\%decl\> { | 52 | \<\%decl\> { |
52 | modi.push_front(modus_operandi(0)); | 53 | modi.push_front(modus_operandi(0)); |
53 | anchor(); | 54 | anchor(); |
54 | BEGIN(DECLBLOCK); | 55 | BEGIN(DECLBLOCK); |
55 | } | 56 | } |
56 | \<\%impl\> { | 57 | \<\%impl\> { |
57 | modi.push_front(modus_operandi(0)); | 58 | modi.push_front(modus_operandi(0)); |
58 | anchor(); | 59 | anchor(); |
59 | BEGIN(IMPLBLOCK); | 60 | BEGIN(IMPLBLOCK); |
60 | } | 61 | } |
61 | ^\%\%var{WHITESPACE}+{ | 62 | ^\%\%var{WHITESPACE}+{ |
62 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); | 63 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); |
63 | anchor(); | 64 | anchor(); |
64 | BEGIN(VARLINE); | 65 | BEGIN(VARLINE); |
65 | } | 66 | } |
66 | ^\%\%import{WHITESPACE}+{ | 67 | ^\%\%import{WHITESPACE}+{ |
67 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); | 68 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); |
68 | BEGIN(IMPORTLINE); | 69 | BEGIN(IMPORTLINE); |
69 | } | 70 | } |
70 | ^\%\%import_type{WHITESPACE}+ { | 71 | ^\%\%import_type{WHITESPACE}+ { |
71 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); | 72 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); |
72 | BEGIN(IMPORTTYPELINE); | 73 | BEGIN(IMPORTTYPELINE); |
73 | } | 74 | } |
74 | ^\%\%derive{WHITESPACE}+{ | 75 | ^\%\%derive{WHITESPACE}+{ |
75 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); | 76 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); |
76 | BEGIN(DERIVELINE); | 77 | BEGIN(DERIVELINE); |
77 | } | 78 | } |
78 | \<\%constructor\>{ | 79 | \<\%constructor\>{ |
79 | modi.push_front(modus_operandi()); | 80 | modi.push_front(modus_operandi()); |
80 | anchor(); | 81 | anchor(); |
81 | BEGIN(CONSTRUCTOR); | 82 | BEGIN(CONSTRUCTOR); |
82 | } | 83 | } |
83 | \<\%destructor\>{ | 84 | \<\%destructor\>{ |
84 | modi.push_front(modus_operandi()); | 85 | modi.push_front(modus_operandi()); |
85 | anchor(); | 86 | anchor(); |
86 | BEGIN(DESTRUCTOR); | 87 | BEGIN(DESTRUCTOR); |
87 | } | 88 | } |
88 | \<\%codemethod{WHITESPACE}+{ | 89 | \<\%codemethod{WHITESPACE}+{ |
89 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); | 90 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); |
90 | anchor(); | 91 | anchor(); |
91 | BEGIN(CODEMETHODLINE); | 92 | BEGIN(CODEMETHODLINE); |
92 | } | 93 | } |
93 | \<\%method{WHITESPACE}+ { | 94 | \<\%method{WHITESPACE}+ { |
94 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); | 95 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); |
95 | anchor(); | 96 | anchor(); |
96 | BEGIN(METHODLINE); | 97 | BEGIN(METHODLINE); |
97 | } | 98 | } |
98 | ^\%\%pragma{WHITESPACE}+{ | 99 | ^\%\%pragma{WHITESPACE}+{ |
99 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); | 100 | modi.push_front(modus_operandi(modus_operandi::flag_devour_comments)); |
100 | BEGIN(PRAGMALINE); | 101 | BEGIN(PRAGMALINE); |
101 | } | 102 | } |
102 | <<EOF>>{ | 103 | <<EOF>>{ |
103 | assert(modi.size()==1); | 104 | assert(modi.size()==1); |
104 | M().modify(modus_operandi::modus_preop); | 105 | M().modify(modus_operandi::modus_preop); |
105 | LexerOutput(";",1); | 106 | LexerOutput(";",1); |
106 | return 0; | 107 | return 0; |
107 | } | 108 | } |
108 | } | 109 | } |
109 | <<EOF>>throw preprocessor_error(CODEPOINT,"unexpected end of file",lineno()); | 110 | <<EOF>>throw preprocessor_error(CODEPOINT,"unexpected end of file",lineno()); |
110 | 111 | ||
111 | <CODEBLOCK,CODEMETHODBLOCK>{ | 112 | <CODEBLOCK,CODEMETHODBLOCK>{ |
112 | "<%output>"{ | 113 | "<%output>"{ |
113 | anchor(); | 114 | anchor(); |
114 | yy_push_state(OUTPUTBLOCK); | 115 | yy_push_state(OUTPUTBLOCK); |
115 | } | 116 | } |
116 | } | 117 | } |
117 | 118 | ||
118 | <PRAGMALINE>{ | 119 | <PRAGMALINE>{ |
119 | {WHITESPACE}+{ | 120 | {WHITESPACE}+{ |
120 | modus_operandi& m = M(); | 121 | modus_operandi& m = M(); |
121 | if(!m.output.empty()) { | 122 | if(!m.output.empty()) { |
122 | string::size_type eq = m.output.find('='); | 123 | string::size_type eq = m.output.find('='); |
123 | if(eq==string::npos) { | 124 | if(eq==string::npos) { |
124 | pragmas[m.output]=m.output; | 125 | pragmas[m.output]=m.output; |
125 | }else{ | 126 | }else{ |
126 | pragmas[m.output.substr(0,eq)] = m.output.substr(eq+1); | 127 | pragmas[m.output.substr(0,eq)] = m.output.substr(eq+1); |
127 | } | 128 | } |
128 | m.output.erase(); | 129 | m.output.erase(); |
129 | } | 130 | } |
130 | } | 131 | } |
131 | \n { | 132 | \n { |
132 | modus_operandi& m = M(); | 133 | modus_operandi& m = M(); |
133 | if(!m.output.empty()) { | 134 | if(!m.output.empty()) { |
134 | string::size_type eq = m.output.find('='); | 135 | string::size_type eq = m.output.find('='); |
135 | if(eq==string::npos) { | 136 | if(eq==string::npos) { |
136 | pragmas[m.output]=m.output; | 137 | pragmas[m.output]=m.output; |
137 | }else{ | 138 | }else{ |
138 | pragmas[m.output.substr(0,eq)] = m.output.substr(eq+1); | 139 | pragmas[m.output.substr(0,eq)] = m.output.substr(eq+1); |
139 | } | 140 | } |
140 | m.output.erase(); | 141 | m.output.erase(); |
141 | } | 142 | } |
142 | modi.pop_front(); | 143 | modi.pop_front(); |
143 | BEGIN(INITIAL); | 144 | BEGIN(INITIAL); |
144 | anchor(); | 145 | anchor(); |
145 | } | 146 | } |
146 | } | 147 | } |
147 | 148 | ||
148 | <METHODLINE>{ | 149 | <METHODLINE>{ |
149 | {WHITESPACE}+{ | 150 | {WHITESPACE}+{ |
150 | modus_operandi& m = M(); | 151 | modus_operandi& m = M(); |
151 | if(!m.output.empty()) { | 152 | if(!m.output.empty()) { |
152 | if(!m._lastid.empty()) { | 153 | if(!m._lastid.empty()) { |
153 | if(!m._type.empty()) m._type += ' '; | 154 | if(!m._type.empty()) m._type += ' '; |
154 | m._type += m._lastid; | 155 | m._type += m._lastid; |
155 | } | 156 | } |
156 | m._lastid = m.output; | 157 | m._lastid = m.output; |
157 | m.output.clear(); | 158 | m.output.clear(); |
158 | } | 159 | } |
159 | } | 160 | } |
160 | \*{ | 161 | \*{ |
161 | modus_operandi& m = M(); | 162 | modus_operandi& m = M(); |
162 | ECHO; | 163 | ECHO; |
163 | if(!m._lastid.empty()) { | 164 | if(!m._lastid.empty()) { |
164 | if(!m._type.empty()) m._type += ' '; | 165 | if(!m._type.empty()) m._type += ' '; |
165 | m._type += m._lastid; | 166 | m._type += m._lastid; |
166 | } | 167 | } |
167 | m._lastid = m.output; | 168 | m._lastid = m.output; |
168 | m.output.clear(); | 169 | m.output.clear(); |
169 | } | 170 | } |
170 | \({ | 171 | \({ |
171 | modus_operandi& m = M(); | 172 | modus_operandi& m = M(); |
172 | if(m.output.empty()) { | 173 | if(m.output.empty()) { |
173 | m._name=m._lastid; | 174 | m._name=m._lastid; |
174 | }else{ | 175 | }else{ |
175 | if(!m._lastid.empty()) { // XXX: lastid, I believe should never be emtpy... | 176 | if(!m._lastid.empty()) { // XXX: lastid, I believe should never be emtpy... |
176 | if(!m._type.empty()) m._type += ' '; | 177 | if(!m._type.empty()) m._type += ' '; |
177 | m._type += m._lastid; | 178 | m._type += m._lastid; |
178 | } | 179 | } |
179 | m._name = m.output; | 180 | m._name = m.output; |
180 | m.output.clear(); | 181 | m.output.clear(); |
181 | } | 182 | } |
182 | ECHO; | 183 | ECHO; |
183 | BEGIN(METHODARGS); | 184 | BEGIN(METHODARGS); |
184 | } | 185 | } |
185 | } | 186 | } |
186 | <METHODARGS>{ | 187 | <METHODARGS>{ |
187 | \%\>{ | 188 | \%\>{ |
188 | modus_operandi& m = M(); | 189 | modus_operandi& m = M(); |
189 | m._args = m.output; | 190 | m._args = m.output; |
190 | m.output.clear(); | 191 | m.output.clear(); |
191 | anchor(); | 192 | anchor(); |
192 | BEGIN(METHODBLOCK); | 193 | BEGIN(METHODBLOCK); |
193 | } | 194 | } |
194 | } | 195 | } |
195 | 196 | ||
196 | <INITIAL,METHODBLOCK,OUTPUTBLOCK>{ | 197 | <INITIAL,METHODBLOCK,OUTPUTBLOCK>{ |
197 | \<\%{WHITESPACE}+{ | 198 | \<\%{WHITESPACE}+{ |
198 | M().modify(modus_operandi::modus_postop); | 199 | M().modify(modus_operandi::modus_postop); |
199 | anchor(); | 200 | anchor(); |
200 | LexerOutput("(",1); | 201 | LexerOutput("(",1); |
201 | yy_push_state(INLINE); | 202 | yy_push_state(INLINE); |
202 | } | 203 | } |
203 | ^\%{WHITESPACE}{ | 204 | ^\%{WHITESPACE}{ |
204 | M().modify(modus_operandi::modus_code); | 205 | M().modify(modus_operandi::modus_code); |
205 | anchor(); | 206 | anchor(); |
206 | yy_push_state(CODELINE); | 207 | yy_push_state(CODELINE); |
207 | } | 208 | } |
208 | \<\%code\>{ | 209 | \<\%code\>{ |
209 | M().modify(modus_operandi::modus_code); | 210 | M().modify(modus_operandi::modus_code); |
210 | anchor(); | 211 | anchor(); |
211 | yy_push_state(CODEBLOCK); | 212 | yy_push_state(CODEBLOCK); |
212 | } | 213 | } |
213 | "</%output>" { | 214 | "</%output>" { |
214 | if(YY_START!=OUTPUTBLOCK) throw preprocessor_error(CODEPOINT,"unexpected tag",lineno()); | 215 | if(YY_START!=OUTPUTBLOCK) throw preprocessor_error(CODEPOINT,"unexpected tag",lineno()); |
215 | M().modify(modus_operandi::modus_code); | 216 | M().modify(modus_operandi::modus_code); |
216 | anchor(); | 217 | anchor(); |
217 | yy_pop_state(); | 218 | yy_pop_state(); |
218 | } | 219 | } |
219 | } | 220 | } |
220 | 221 | ||
221 | <INLINE>\%\>LexerOutput(")",1); M().modus=modus_operandi::modus_preop; yy_pop_state(); | 222 | <INLINE>\%\>LexerOutput(")",1); M().modus=modus_operandi::modus_preop; yy_pop_state(); |
222 | <CODELINE>\nyy_pop_state(); | 223 | <CODELINE>\nyy_pop_state(); |
223 | 224 | ||
224 | <CODEMETHODLINE>{ | 225 | <CODEMETHODLINE>{ |
225 | {WHITESPACE}+{ | 226 | {WHITESPACE}+{ |
226 | modus_operandi& m = M(); | 227 | modus_operandi& m = M(); |
227 | if(!m.output.empty()) { | 228 | if(!m.output.empty()) { |
228 | if(!m._lastid.empty()) { | 229 | if(!m._lastid.empty()) { |
229 | if(!m._type.empty()) m._type += ' '; | 230 | if(!m._type.empty()) m._type += ' '; |
230 | m._type += m._lastid; | 231 | m._type += m._lastid; |
231 | } | 232 | } |
232 | m._lastid = m.output; | 233 | m._lastid = m.output; |
233 | m.output.clear(); | 234 | m.output.clear(); |
234 | } | 235 | } |
235 | } | 236 | } |
236 | \*{ | 237 | \*{ |
237 | modus_operandi& m = M(); | 238 | modus_operandi& m = M(); |
238 | ECHO; | 239 | ECHO; |
239 | if(!m._lastid.empty()) { | 240 | if(!m._lastid.empty()) { |
240 | if(!m._type.empty()) m._type += ' '; | 241 | if(!m._type.empty()) m._type += ' '; |
241 | m._type += m._lastid; | 242 | m._type += m._lastid; |
242 | } | 243 | } |
243 | m._lastid = m.output; | 244 | m._lastid = m.output; |
244 | m.output.clear(); | 245 | m.output.clear(); |
245 | } | 246 | } |
246 | \({ | 247 | \({ |
247 | modus_operandi& m = M(); | 248 | modus_operandi& m = M(); |
248 | if(m.output.empty()) { | 249 | if(m.output.empty()) { |
249 | m._name=m._lastid; | 250 | m._name=m._lastid; |
250 | }else{ | 251 | }else{ |
251 | if(!m._lastid.empty()) { // XXX: lastid, I believe should never be emtpy... | 252 | if(!m._lastid.empty()) { // XXX: lastid, I believe should never be emtpy... |
252 | if(!m._type.empty()) m._type += ' '; | 253 | if(!m._type.empty()) m._type += ' '; |
253 | m._type += m._lastid; | 254 | m._type += m._lastid; |
254 | } | 255 | } |
255 | m._name = m.output; | 256 | m._name = m.output; |
256 | m.output.clear(); | 257 | m.output.clear(); |
257 | } | 258 | } |
258 | ECHO; | 259 | ECHO; |
259 | BEGIN(CODEMETHODARGS); | 260 | BEGIN(CODEMETHODARGS); |
260 | } | 261 | } |
261 | } | 262 | } |
262 | <CODEMETHODARGS>{ | 263 | <CODEMETHODARGS>{ |
263 | \%\>{ | 264 | \%\>{ |
264 | modus_operandi& m = M(); | 265 | modus_operandi& m = M(); |
265 | m._args = m.output; | 266 | m._args = m.output; |
266 | m.output.clear(); | 267 | m.output.clear(); |
267 | m.flags=0; | 268 | m.flags=0; |
268 | anchor(); | 269 | anchor(); |
269 | BEGIN(CODEMETHODBLOCK); | 270 | BEGIN(CODEMETHODBLOCK); |
270 | } | 271 | } |
271 | } | 272 | } |
272 | 273 | ||
273 | <IMPORTLINE>{ | 274 | <IMPORTLINE>{ |
274 | {WHITESPACE}+{ } | 275 | {WHITESPACE}+{ } |
275 | {ID}{ | 276 | {ID}{ |
276 | modus_operandi& m = M(); | 277 | modus_operandi& m = M(); |
277 | if(!m._name.empty()) | 278 | if(!m._name.empty()) |
278 | throw preprocessor_error(CODEPOINT,"syntax error",lineno()); | 279 | throw preprocessor_error(CODEPOINT,"syntax error",lineno()); |
279 | m._name = yytext; | 280 | m._name = yytext; |
280 | } | 281 | } |
281 | \= { | 282 | \= { |
282 | M().output.clear(); | 283 | M().output.clear(); |
283 | BEGIN(IMPORTCOMPONENT); | 284 | BEGIN(IMPORTCOMPONENT); |
284 | } | 285 | } |
285 | } | 286 | } |
286 | <IMPORTCOMPONENT>{ | 287 | <IMPORTCOMPONENT>{ |
287 | {WHITESPACE}+{ } | 288 | {WHITESPACE}+{ } |
288 | \n{ | 289 | \n{ |
289 | modus_operandi& m = M(); | 290 | modus_operandi& m = M(); |
290 | string::size_type t = m.output.find_first_not_of(" \t"); | 291 | string::size_type t = m.output.find_first_not_of(" \t"); |
291 | if(t!=string::npos) | 292 | if(t!=string::npos) |
292 | m.output.erase(0,t); | 293 | m.output.erase(0,t); |
293 | t = m.output.find_last_not_of(" \t;"); | 294 | t = m.output.find_last_not_of(" \t;"); |
294 | if(t!=string::npos) | 295 | if(t!=string::npos) |
295 | m.output.erase(t+1); | 296 | m.output.erase(t+1); |
296 | if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { | 297 | if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { |
297 | m.output.erase(0,1); | 298 | m.output.erase(0,1); |
298 | m.output.erase(m.output.length()-1); | 299 | m.output.erase(m.output.length()-1); |
299 | } | 300 | } |
300 | string c = combine_path(component_basename,m.output); | 301 | string c = konforka::combine_path(component_basename,m.output); |
301 | member_variables.push_back(member_variable(m._type,m._name,normalize_path(c,strip_leading_slash),true)); | 302 | member_variables.push_back(member_variable(m._type,m._name,konforka::normalize_path(c,konforka::strip_leading_slash),true)); |
302 | modi.pop_front(); | 303 | modi.pop_front(); |
303 | BEGIN(INITIAL); | 304 | BEGIN(INITIAL); |
304 | } | 305 | } |
305 | } | 306 | } |
306 | 307 | ||
307 | <IMPORTTYPELINE>{ | 308 | <IMPORTTYPELINE>{ |
308 | {WHITESPACE}+{ } | 309 | {WHITESPACE}+{ } |
309 | {ID}{ | 310 | {ID}{ |
310 | modus_operandi& m = M(); | 311 | modus_operandi& m = M(); |
311 | if(!m._name.empty()) | 312 | if(!m._name.empty()) |
312 | throw preprocessor_error(CODEPOINT,"syntax error",lineno()); | 313 | throw preprocessor_error(CODEPOINT,"syntax error",lineno()); |
313 | m._name = yytext; | 314 | m._name = yytext; |
314 | } | 315 | } |
315 | \= { | 316 | \= { |
316 | M().output.clear(); | 317 | M().output.clear(); |
317 | BEGIN(IMPORTTYPECOMPONENT); | 318 | BEGIN(IMPORTTYPECOMPONENT); |
318 | } | 319 | } |
319 | } | 320 | } |
320 | <IMPORTTYPECOMPONENT>{ | 321 | <IMPORTTYPECOMPONENT>{ |
321 | {WHITESPACE}+{ } | 322 | {WHITESPACE}+{ } |
322 | \n{ | 323 | \n{ |
323 | modus_operandi& m = M(); | 324 | modus_operandi& m = M(); |
324 | string::size_type t = m.output.find_first_not_of(" \t"); | 325 | string::size_type t = m.output.find_first_not_of(" \t"); |
325 | if(t!=string::npos) | 326 | if(t!=string::npos) |
326 | m.output.erase(0,t); | 327 | m.output.erase(0,t); |
327 | t = m.output.find_last_not_of(" \t;"); | 328 | t = m.output.find_last_not_of(" \t;"); |
328 | if(t!=string::npos) | 329 | if(t!=string::npos) |
329 | m.output.erase(t+1); | 330 | m.output.erase(t+1); |
330 | if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { | 331 | if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { |
331 | m.output.erase(0,1); | 332 | m.output.erase(0,1); |
332 | m.output.erase(m.output.length()-1); | 333 | m.output.erase(m.output.length()-1); |
333 | } | 334 | } |
334 | string c = combine_path(component_basename,m.output); | 335 | string c = konforka::combine_path(component_basename,m.output); |
335 | member_variables.push_back(member_variable(m._type,m._name,normalize_path(c,strip_leading_slash),true,true)); | 336 | member_variables.push_back(member_variable(m._type,m._name,konforka::normalize_path(c,konforka::strip_leading_slash),true,true)); |
336 | modi.pop_front(); | 337 | modi.pop_front(); |
337 | BEGIN(INITIAL); | 338 | BEGIN(INITIAL); |
338 | } | 339 | } |
339 | } | 340 | } |
340 | 341 | ||
341 | <DERIVELINE>{ | 342 | <DERIVELINE>{ |
342 | {WHITESPACE}+{ } | 343 | {WHITESPACE}+{ } |
343 | {ID}{ | 344 | {ID}{ |
344 | modus_operandi& m = M(); | 345 | modus_operandi& m = M(); |
345 | if(!m._name.empty()) | 346 | if(!m._name.empty()) |
346 | throw preprocessor_error(CODEPOINT,"syntax_error",lineno()); | 347 | throw preprocessor_error(CODEPOINT,"syntax_error",lineno()); |
347 | m._name = yytext; | 348 | m._name = yytext; |
348 | } | 349 | } |
349 | \= { | 350 | \= { |
350 | M().output.clear(); | 351 | M().output.clear(); |
351 | BEGIN(DERIVECOMPONENT); | 352 | BEGIN(DERIVECOMPONENT); |
352 | } | 353 | } |
353 | } | 354 | } |
354 | <DERIVECOMPONENT>{ | 355 | <DERIVECOMPONENT>{ |
355 | {WHITESPACE}+{ } | 356 | {WHITESPACE}+{ } |
356 | \n { | 357 | \n { |
357 | modus_operandi& m = M(); | 358 | modus_operandi& m = M(); |
358 | string::size_type t = m.output.find_first_not_of(" \t"); | 359 | string::size_type t = m.output.find_first_not_of(" \t"); |
359 | if(t!=string::npos) | 360 | if(t!=string::npos) |
360 | m.output.erase(0,t); | 361 | m.output.erase(0,t); |
361 | t = m.output.find_last_not_of(" \t;"); | 362 | t = m.output.find_last_not_of(" \t;"); |
362 | if(t!=string::npos) | 363 | if(t!=string::npos) |
363 | m.output.erase(t+1); | 364 | m.output.erase(t+1); |
364 | if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { | 365 | if(m.output[0]=='"' && m.output[m.output.length()-1]=='"') { |
365 | m.output.erase(0,1); | 366 | m.output.erase(0,1); |
366 | m.output.erase(m.output.length()-1); | 367 | m.output.erase(m.output.length()-1); |
367 | } | 368 | } |
368 | string c = combine_path(component_basename,m.output); | 369 | string c = konforka::combine_path(component_basename,m.output); |
369 | ancestor_classes.push_back(ancestor_class(m._name,normalize_path(c,strip_leading_slash))); | 370 | ancestor_classes.push_back(ancestor_class(m._name,konforka::normalize_path(c,konforka::strip_leading_slash))); |
370 | modi.pop_front(); | 371 | modi.pop_front(); |
371 | BEGIN(INITIAL); | 372 | BEGIN(INITIAL); |
372 | } | 373 | } |
373 | } | 374 | } |
374 | 375 | ||
375 | <VARLINE>{ | 376 | <VARLINE>{ |
376 | {WHITESPACE}+{ | 377 | {WHITESPACE}+{ |
377 | modus_operandi& m = M(); | 378 | modus_operandi& m = M(); |
378 | if(!m.output.empty()) { | 379 | if(!m.output.empty()) { |
379 | if(!m._lastid.empty()) { | 380 | if(!m._lastid.empty()) { |
380 | if(!m._type.empty()) m._type += ' '; | 381 | if(!m._type.empty()) m._type += ' '; |
381 | m._type += m._lastid; | 382 | m._type += m._lastid; |
382 | } | 383 | } |
383 | m._lastid = m.output; | 384 | m._lastid = m.output; |
384 | m.output.clear(); | 385 | m.output.clear(); |
385 | } | 386 | } |
386 | } | 387 | } |
387 | \*{ | 388 | \*{ |
388 | modus_operandi& m = M(); | 389 | modus_operandi& m = M(); |
389 | ECHO; | 390 | ECHO; |
390 | if(!m._lastid.empty()) { | 391 | if(!m._lastid.empty()) { |
391 | if(!m._type.empty()) m._type += ' '; | 392 | if(!m._type.empty()) m._type += ' '; |
392 | m._type += m._lastid; | 393 | m._type += m._lastid; |
393 | } | 394 | } |
394 | m._lastid = m.output; | 395 | m._lastid = m.output; |
395 | m.output.clear(); | 396 | m.output.clear(); |
396 | } | 397 | } |
397 | \;|\n|\={ | 398 | \;|\n|\={ |
398 | modus_operandi& m = M(); | 399 | modus_operandi& m = M(); |
399 | if(m.output.empty()) { | 400 | if(m.output.empty()) { |
400 | m._name=m._lastid; | 401 | m._name=m._lastid; |
401 | }else{ | 402 | }else{ |
402 | if(!m._lastid.empty()) { // XXX: lastid should never be emtpy, I believe? | 403 | if(!m._lastid.empty()) { // XXX: lastid should never be emtpy, I believe? |
403 | if(!m._type.empty()) m._type += ' '; | 404 | if(!m._type.empty()) m._type += ' '; |
404 | m._type += m._lastid; | 405 | m._type += m._lastid; |
405 | } | 406 | } |
406 | m._name=m.output; | 407 | m._name=m.output; |
407 | m.output.clear(); | 408 | m.output.clear(); |
408 | } | 409 | } |
409 | BEGIN(VARINIT); | 410 | BEGIN(VARINIT); |
410 | if(*yytext!='=') | 411 | if(*yytext!='=') |
411 | unput('\n'); | 412 | unput('\n'); |
412 | } | 413 | } |
413 | } | 414 | } |
414 | <VARINIT>{ | 415 | <VARINIT>{ |
415 | \n{ | 416 | \n{ |
416 | modus_operandi& m = M(); | 417 | modus_operandi& m = M(); |
417 | string::size_type t = m.output.find_first_not_of(" \t"); | 418 | string::size_type t = m.output.find_first_not_of(" \t"); |
418 | if(t!=string::npos) | 419 | if(t!=string::npos) |
419 | m.output.erase(0,t); | 420 | m.output.erase(0,t); |
420 | t = m.output.find_last_not_of(" \t;"); | 421 | t = m.output.find_last_not_of(" \t;"); |
421 | if(t!=string::npos) | 422 | if(t!=string::npos) |
422 | m.output.erase(t+1); | 423 | m.output.erase(t+1); |
423 | member_variables.push_back(member_variable(m._type,m._name,m.output)); | 424 | member_variables.push_back(member_variable(m._type,m._name,m.output)); |
424 | if(!m.output.empty()) | 425 | if(!m.output.empty()) |
425 | have_initializers=true; | 426 | have_initializers=true; |
426 | modi.pop_front(); | 427 | modi.pop_front(); |
427 | BEGIN(INITIAL); | 428 | BEGIN(INITIAL); |
428 | } | 429 | } |
429 | } | 430 | } |
430 | <DECLLINE>\n{ | 431 | <DECLLINE>\n{ |
431 | ECHO; | 432 | ECHO; |
432 | decl += M().output; | 433 | decl += M().output; |
433 | modi.pop_front(); | 434 | modi.pop_front(); |
434 | BEGIN(INITIAL); | 435 | BEGIN(INITIAL); |
435 | } | 436 | } |
436 | <IMPLLINE>\n{ | 437 | <IMPLLINE>\n{ |
437 | ECHO; | 438 | ECHO; |
438 | impl += M().output; | 439 | impl += M().output; |
439 | modi.pop_front(); | 440 | modi.pop_front(); |
440 | BEGIN(INITIAL); | 441 | BEGIN(INITIAL); |
441 | } | 442 | } |
442 | <CLASSLINE>\n{ | 443 | <CLASSLINE>\n{ |
443 | class_name = M().output; | 444 | class_name = M().output; |
444 | modi.pop_front(); | 445 | modi.pop_front(); |
445 | BEGIN(INITIAL); | 446 | BEGIN(INITIAL); |
446 | } | 447 | } |
447 | <CLASSLINE,DECLLINE,IMPLLINE,VARLINE,VARINIT,IMPORTLINE,IMPORTCOMPONENT,CODEMETHODLINE,CODEMETHODARGS,INLINE,METHODLINE,METHODARGS,DECLBLOCK,IMPLBLOCK,CONSTRUCTOR,DESTRUCTOR,CODEMETHODBLOCK,CODELINE,CODEBLOCK,PRAGMALINE,DERIVELINE,DERIVECOMPONENT>{ | 448 | <CLASSLINE,DECLLINE,IMPLLINE,VARLINE,VARINIT,IMPORTLINE,IMPORTCOMPONENT,CODEMETHODLINE,CODEMETHODARGS,INLINE,METHODLINE,METHODARGS,DECLBLOCK,IMPLBLOCK,CONSTRUCTOR,DESTRUCTOR,CODEMETHODBLOCK,CODELINE,CODEBLOCK,PRAGMALINE,DERIVELINE,DERIVECOMPONENT>{ |
448 | "/*"{ | 449 | "/*"{ |
449 | yy_push_state(SLASHSTAR_COMMENT); | 450 | yy_push_state(SLASHSTAR_COMMENT); |
450 | if(!M().devour_comments()) { | 451 | if(!M().devour_comments()) { |
451 | ECHO; | 452 | ECHO; |
452 | } | 453 | } |
453 | } | 454 | } |
454 | "//"{ | 455 | "//"{ |
455 | yy_push_state(SLASHSLASH_COMMENT); | 456 | yy_push_state(SLASHSLASH_COMMENT); |
456 | if(!M().devour_comments()) { | 457 | if(!M().devour_comments()) { |
457 | ECHO; | 458 | ECHO; |
458 | } | 459 | } |
459 | } | 460 | } |
460 | \" { | 461 | \" { |
461 | yy_push_state(STRING); | 462 | yy_push_state(STRING); |
462 | ECHO; | 463 | ECHO; |
463 | } | 464 | } |
464 | \'\\.\'{ | 465 | \'\\.\'{ |
465 | ECHO; | 466 | ECHO; |
466 | } | 467 | } |
467 | } | 468 | } |
468 | 469 | ||
469 | <INITIAL,METHODBLOCK,OUTPUTBLOCK>{ | 470 | <INITIAL,METHODBLOCK,OUTPUTBLOCK>{ |
470 | \"soft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\\"",2); | 471 | \"soft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\\"",2); |
471 | \nsoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\n",2); | 472 | \nsoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\n",2); |
472 | \rsoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\r",2); | 473 | \rsoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\r",2); |
473 | \tsoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\t",2); | 474 | \tsoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\t",2); |
474 | \bsoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\b",2); | 475 | \bsoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\b",2); |
475 | \asoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\a",2); | 476 | \asoft_anchor(); M().modify(modus_operandi::modus_text); LexerOutput("\\a",2); |
476 | .soft_anchor(); M().modify(modus_operandi::modus_text); ECHO; | 477 | .soft_anchor(); M().modify(modus_operandi::modus_text); ECHO; |
477 | {WHITESPACE}+soft_anchor(); M().modify(modus_operandi::modus_text); ECHO; | 478 | {WHITESPACE}+soft_anchor(); M().modify(modus_operandi::modus_text); ECHO; |
478 | } | 479 | } |
479 | 480 | ||
480 | <DECLBLOCK,IMPLBLOCK,CONSTRUCTOR,DESTRUCTOR,CODEMETHODBLOCK,METHODBLOCK,CODEBLOCK>{ | 481 | <DECLBLOCK,IMPLBLOCK,CONSTRUCTOR,DESTRUCTOR,CODEMETHODBLOCK,METHODBLOCK,CODEBLOCK>{ |
481 | \<\/\%decl\>{ | 482 | \<\/\%decl\>{ |
482 | if(YY_START!=DECLBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); | 483 | if(YY_START!=DECLBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); |
483 | decl += M().output; | 484 | decl += M().output; |
484 | modi.pop_front(); | 485 | modi.pop_front(); |
485 | BEGIN(INITIAL); | 486 | BEGIN(INITIAL); |
486 | } | 487 | } |
487 | \<\/\%impl\>{ | 488 | \<\/\%impl\>{ |
488 | if(YY_START!=IMPLBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); | 489 | if(YY_START!=IMPLBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); |
489 | impl += M().output; | 490 | impl += M().output; |
490 | modi.pop_front(); | 491 | modi.pop_front(); |
491 | BEGIN(INITIAL); | 492 | BEGIN(INITIAL); |
492 | } | 493 | } |
493 | \<\/\%constructor\>{ | 494 | \<\/\%constructor\>{ |
494 | if(YY_START!=CONSTRUCTOR) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); | 495 | if(YY_START!=CONSTRUCTOR) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); |
495 | member_functions.push_back(member_function("","","",M().output)); | 496 | member_functions.push_back(member_function("","","",M().output)); |
496 | have_constructor = true; | 497 | have_constructor = true; |
497 | modi.pop_front(); | 498 | modi.pop_front(); |
498 | BEGIN(INITIAL); | 499 | BEGIN(INITIAL); |
499 | } | 500 | } |
500 | \<\/\%destructor\>{ | 501 | \<\/\%destructor\>{ |
501 | if(YY_START!=DESTRUCTOR) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); | 502 | if(YY_START!=DESTRUCTOR) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); |
502 | member_functions.push_back(member_function("","~","",M().output)); | 503 | member_functions.push_back(member_function("","~","",M().output)); |
503 | modi.pop_front(); | 504 | modi.pop_front(); |
504 | BEGIN(INITIAL); | 505 | BEGIN(INITIAL); |
505 | } | 506 | } |
506 | \<\/\%codemethod\>{ | 507 | \<\/\%codemethod\>{ |
507 | if(YY_START!=CODEMETHODBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); | 508 | if(YY_START!=CODEMETHODBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); |
508 | modus_operandi& m = M(); | 509 | modus_operandi& m = M(); |
509 | member_functions.push_back(member_function(m._type,m._name,m._args,m.output)); | 510 | member_functions.push_back(member_function(m._type,m._name,m._args,m.output)); |
510 | modi.pop_front(); | 511 | modi.pop_front(); |
511 | BEGIN(INITIAL); | 512 | BEGIN(INITIAL); |
512 | } | 513 | } |
513 | \<\/%method\> { | 514 | \<\/%method\> { |
514 | if(YY_START!=METHODBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); | 515 | if(YY_START!=METHODBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); |
515 | modus_operandi& m = M(); | 516 | modus_operandi& m = M(); |
516 | m.modify(modus_operandi::modus_code); | 517 | m.modify(modus_operandi::modus_code); |
517 | member_functions.push_back(member_function(m._type,m._name,m._args,m.output)); | 518 | member_functions.push_back(member_function(m._type,m._name,m._args,m.output)); |
518 | modi.pop_front(); | 519 | modi.pop_front(); |
519 | BEGIN(INITIAL); | 520 | BEGIN(INITIAL); |
520 | } | 521 | } |
521 | \<\/%code\> { | 522 | \<\/%code\> { |
522 | if(YY_START!=CODEBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); | 523 | if(YY_START!=CODEBLOCK) throw preprocessor_error(CODEPOINT,"tags mismatch",lineno()); |
523 | yy_pop_state(); | 524 | yy_pop_state(); |
524 | } | 525 | } |
525 | \n ECHO; | 526 | \n ECHO; |
526 | } | 527 | } |
527 | 528 | ||
528 | <SLASHSTAR_COMMENT>{ | 529 | <SLASHSTAR_COMMENT>{ |
529 | "*/"{ | 530 | "*/"{ |
530 | if(!M().devour_comments()) { | 531 | if(!M().devour_comments()) { |
531 | ECHO; | 532 | ECHO; |
532 | } | 533 | } |
533 | yy_pop_state(); | 534 | yy_pop_state(); |
534 | unput(' '); | 535 | unput(' '); |
535 | } | 536 | } |
536 | \n{ | 537 | \n{ |
537 | if(!M().devour_comments()) { | 538 | if(!M().devour_comments()) { |
538 | ECHO; | 539 | ECHO; |
539 | } | 540 | } |
540 | } | 541 | } |
541 | } | 542 | } |
542 | <SLASHSLASH_COMMENT>{ | 543 | <SLASHSLASH_COMMENT>{ |
543 | \n{ | 544 | \n{ |
544 | if(!M().devour_comments()) { | 545 | if(!M().devour_comments()) { |
545 | ECHO; | 546 | ECHO; |
546 | } | 547 | } |
547 | yy_pop_state(); | 548 | yy_pop_state(); |
548 | if(YY_START!=CODEBLOCK && YY_START!=CODEMETHODBLOCK && YY_START!=IMPLBLOCK && YY_START!=DECLBLOCK) | 549 | if(YY_START!=CODEBLOCK && YY_START!=CODEMETHODBLOCK && YY_START!=IMPLBLOCK && YY_START!=DECLBLOCK) |
549 | unput('\n'); | 550 | unput('\n'); |
550 | } | 551 | } |
551 | } | 552 | } |
552 | <SLASHSTAR_COMMENT,SLASHSLASH_COMMENT>.{ | 553 | <SLASHSTAR_COMMENT,SLASHSLASH_COMMENT>.{ |
553 | if(!M().devour_comments()) { | 554 | if(!M().devour_comments()) { |
554 | ECHO; | 555 | ECHO; |
555 | } | 556 | } |
556 | } | 557 | } |
557 | <STRING>{ | 558 | <STRING>{ |
558 | \\.ECHO; | 559 | \\.ECHO; |
559 | \"ECHO; yy_pop_state(); | 560 | \"ECHO; yy_pop_state(); |
560 | .ECHO; | 561 | .ECHO; |
561 | } | 562 | } |
562 | 563 | ||
563 | {WHITESPACE}+{ | 564 | {WHITESPACE}+{ |
564 | if(!(M().flags&modus_operandi::flag_devour_whitespace)) { | 565 | if(!(M().flags&modus_operandi::flag_devour_whitespace)) { |
565 | ECHO; | 566 | ECHO; |
566 | } | 567 | } |
567 | } | 568 | } |
568 | 569 | ||
569 | %% | 570 | %% |
570 | 571 | ||
571 | sitecing_parser::sitecing_parser(component_factory& f) | 572 | sitecing_parser::sitecing_parser(component_factory& f) |
572 | : factory(f), have_initializers(false), have_constructor(false), | 573 | : factory(f), have_initializers(false), have_constructor(false), |
573 | base_class("sitecing::cgi_component"), | 574 | base_class("sitecing::cgi_component"), |
574 | base_header("sitecing/cgi_component.h"), | 575 | base_header("sitecing/cgi_component.h"), |
575 | skeleton(__SC_DEFAULT_SKELETON) { | 576 | skeleton(__SC_DEFAULT_SKELETON) { |
576 | } | 577 | } |
577 | 578 | ||
578 | void sitecing_parser::preprocess(const string& in) { | 579 | void sitecing_parser::preprocess(const string& in) { |
579 | ifstream ifs(in.c_str(),ios::in); | 580 | ifstream ifs(in.c_str(),ios::in); |
580 | if(!ifs.good()) | 581 | if(!ifs.good()) |
581 | throw preprocessor_error(CODEPOINT,"failed to open input file"); | 582 | throw preprocessor_error(CODEPOINT,"failed to open input file"); |
582 | input_file = in; | 583 | input_file = in; |
583 | modi.push_front(modus_operandi(0)); | 584 | modi.push_front(modus_operandi(0)); |
584 | switch_streams(&ifs,NULL); | 585 | switch_streams(&ifs,NULL); |
585 | if(yylex()) | 586 | if(yylex()) |
586 | throw preprocessor_error(CODEPOINT,"unknown error"); | 587 | throw preprocessor_error(CODEPOINT,"unknown error"); |
587 | pragmas_t::const_iterator mp = pragmas.find("main"); | 588 | pragmas_t::const_iterator mp = pragmas.find("main"); |
588 | if(mp==pragmas.end()) { | 589 | if(mp==pragmas.end()) { |
589 | member_functions.push_back(member_function("void","main","(int _magic,va_list _args)",M().output)); | 590 | member_functions.push_back(member_function("void","main","(int _magic,va_list _args)",M().output)); |
590 | }else{ | 591 | }else{ |
591 | member_functions.push_back( | 592 | member_functions.push_back( |
592 | member_function( | 593 | member_function( |
593 | "void","main","(int _magic,va_list _args)", | 594 | "void","main","(int _magic,va_list _args)", |
594 | mp->second+"::main(_magic,_args);" | 595 | mp->second+"::main(_magic,_args);" |
595 | ) | 596 | ) |
596 | ); | 597 | ); |
597 | } | 598 | } |
598 | if(have_initializers && !have_constructor) | 599 | if(have_initializers && !have_constructor) |
599 | member_functions.push_back(member_function("","","","")); | 600 | member_functions.push_back(member_function("","","","")); |
600 | sitecing_enflesher enflesher(*this); | 601 | sitecing_enflesher enflesher(*this); |
601 | enflesher.enflesh(); | 602 | enflesher.enflesh(); |
602 | } | 603 | } |
603 | 604 | ||
604 | void sitecing_parser::LexerOutput(const char* buf,int size) { | 605 | void sitecing_parser::LexerOutput(const char* buf,int size) { |
605 | assert(modi.size()); | 606 | assert(modi.size()); |
606 | M().output.append(buf,size); | 607 | M().output.append(buf,size); |
607 | } | 608 | } |
608 | 609 | ||
609 | static const char *modus_transitions | 610 | static const char *modus_transitions |
610 | [sitecing_parser::modus_operandi::modi] | 611 | [sitecing_parser::modus_operandi::modi] |
611 | [sitecing_parser::modus_operandi::modi] = { | 612 | [sitecing_parser::modus_operandi::modi] = { |
612 | // To: | 613 | // To: |
613 | // code preop postop text From: | 614 | // code preop postop text From: |
614 | { "", "(*(__SCIF->out))", "(*(__SCIF->out))<<", "(*(__SCIF->out))<<\"" }, // code | 615 | { "", "(*(__SCIF->out))", "(*(__SCIF->out))<<", "(*(__SCIF->out))<<\"" }, // code |
615 | { ";", "", "<<", "<<\"" }, // preop | 616 | { ";", "", "<<", "<<\"" }, // preop |
616 | { NULL, NULL, "", "\"" }, // postop | 617 | { NULL, NULL, "", "\"" }, // postop |
617 | { "\";", "\"", "\"<<", "" } // text | 618 | { "\";", "\"", "\"<<", "" } // text |
618 | }; | 619 | }; |
619 | 620 | ||
620 | void sitecing_parser::modus_operandi::modify(modus_t m) { | 621 | void sitecing_parser::modus_operandi::modify(modus_t m) { |
621 | const char * x = modus_transitions[modus][m]; | 622 | const char * x = modus_transitions[modus][m]; |
622 | assert(x); | 623 | assert(x); |
623 | output += x; | 624 | output += x; |
624 | modus = m; | 625 | modus = m; |
625 | } | 626 | } |
626 | 627 | ||
627 | void sitecing_parser::soft_anchor() { | 628 | void sitecing_parser::soft_anchor() { |
628 | if(M().modus!=modus_operandi::modus_text) | 629 | if(M().modus!=modus_operandi::modus_text) |
629 | anchor(); | 630 | anchor(); |
630 | } | 631 | } |
631 | void sitecing_parser::anchor() { | 632 | void sitecing_parser::anchor() { |
632 | if(M().modus==modus_operandi::modus_text) | 633 | if(M().modus==modus_operandi::modus_text) |
633 | M().modify(modus_operandi::modus_preop); | 634 | M().modify(modus_operandi::modus_preop); |
634 | M().output += "\n#line "; | 635 | M().output += "\n#line "; |
635 | char tmp[7]; | 636 | char tmp[7]; |
636 | snprintf(tmp,sizeof(tmp),"%d",lineno()); | 637 | snprintf(tmp,sizeof(tmp),"%d",lineno()); |
637 | M().output += tmp; | 638 | M().output += tmp; |
638 | M().output += " \""; | 639 | M().output += " \""; |
639 | M().output += input_file; | 640 | M().output += input_file; |
640 | M().output += "\"\n"; | 641 | M().output += "\"\n"; |
641 | } | 642 | } |
642 | /* vim:set ft=lex: */ | 643 | /* vim:set ft=lex: */ |
diff --git a/lib/sitecing_util.cc b/lib/sitecing_util.cc index f892a60..f1432df 100644 --- a/lib/sitecing_util.cc +++ b/lib/sitecing_util.cc | |||
@@ -1,279 +1,162 @@ | |||
1 | #ifdef USE_PCH | 1 | #ifdef USE_PCH |
2 | #include "pch.h" | 2 | #include "pch.h" |
3 | #else | 3 | #else |
4 | #include <sys/stat.h> | 4 | #include <sys/stat.h> |
5 | #include <sys/types.h> | 5 | #include <sys/types.h> |
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <fcntl.h> | 7 | #include <fcntl.h> |
8 | #include <sys/ipc.h> | 8 | #include <sys/ipc.h> |
9 | #include <sys/sem.h> | 9 | #include <sys/sem.h> |
10 | #include <errno.h> | 10 | #include <errno.h> |
11 | #include <iostream> | 11 | #include <iostream> |
12 | #include <fstream> | 12 | #include <fstream> |
13 | #include <cassert> | 13 | #include <cassert> |
14 | #include "sitecing/sitecing_util.h" | 14 | #include "sitecing/sitecing_util.h" |
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | namespace sitecing { | 17 | namespace sitecing { |
18 | 18 | ||
19 | /* | 19 | /* |
20 | * XXX: all of these utilities could be sheerly optimized. | 20 | * XXX: all of these utilities could be sheerly optimized. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | string normalize_path(const string& path,int opts) { | ||
24 | const char *s = path.c_str(); | ||
25 | string rv; | ||
26 | string::size_type notslash = 0; | ||
27 | if( (*s)=='.' && s[1]=='/' ) | ||
28 | s+=2; | ||
29 | if(opts&strip_leading_slash) | ||
30 | for(;(*s) && (*s)=='/';s++); | ||
31 | for(;*s;s++) { | ||
32 | if( (*s)=='/' ) { | ||
33 | if(s[1]=='/') | ||
34 | continue; | ||
35 | if(s[1]=='.' && s[2]=='/') { | ||
36 | s+=2; | ||
37 | continue; | ||
38 | } | ||
39 | } | ||
40 | if(opts&restrict_dotdot) { | ||
41 | if( | ||
42 | ( rv.empty() && s[0]=='.' && s[1]=='.' && s[2]=='/' )// "^../" | ||
43 | || ( s[0]=='/' && s[1]=='.' && s[2]=='.' && (s[3]==0 || s[3]=='/') ) // "/..(/|$)" | ||
44 | ) | ||
45 | throw utility_restricted_sequence(CODEPOINT,"restricted updir sequence encountered"); | ||
46 | } | ||
47 | rv += *s; | ||
48 | if( (*s) != '/' ) | ||
49 | notslash=rv.length(); | ||
50 | } | ||
51 | if(!(opts&strip_trailing_slash)) | ||
52 | notslash++; | ||
53 | if(notslash<rv.length()) | ||
54 | rv.erase(notslash); // XXX: check the logic of stripping/not strippling trailing slash | ||
55 | return rv; | ||
56 | } | ||
57 | |||
58 | string strip_prefix(const string& str,const string& prefix) { | 23 | string strip_prefix(const string& str,const string& prefix) { |
59 | if( (str.length()<prefix.length()) || str.compare(0,prefix.length(),prefix)) | 24 | if( (str.length()<prefix.length()) || str.compare(0,prefix.length(),prefix)) |
60 | throw utility_no_prefix(CODEPOINT,"no such prefix"); | 25 | throw utility_no_prefix(CODEPOINT,"no such prefix"); |
61 | return str.substr(prefix.length()); | 26 | return str.substr(prefix.length()); |
62 | } | 27 | } |
63 | 28 | ||
64 | string strip_suffix(const string& str,const string& suffix) { | 29 | string strip_suffix(const string& str,const string& suffix) { |
65 | if( (str.length()<suffix.length()) || str.compare(str.length()-suffix.length(),suffix.length(),suffix)) | 30 | if( (str.length()<suffix.length()) || str.compare(str.length()-suffix.length(),suffix.length(),suffix)) |
66 | throw utility_no_suffix(CODEPOINT,"no such suffix"); | 31 | throw utility_no_suffix(CODEPOINT,"no such suffix"); |
67 | return str.substr(0,str.length()-suffix.length()); | 32 | return str.substr(0,str.length()-suffix.length()); |
68 | } | 33 | } |
69 | 34 | ||
70 | string dir_name(const string& filename) { | ||
71 | string::size_type sl = filename.find_last_of('/'); | ||
72 | if(sl==string::npos) | ||
73 | return ""; // no slashes -- no dir. | ||
74 | string::size_type nosl = filename.find_last_not_of('/',sl); | ||
75 | if(nosl==string::npos) | ||
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); | ||
78 | } | ||
79 | |||
80 | void make_path(const string& path,mode_t mode) { | ||
81 | struct stat st; | ||
82 | for(string::size_type sl=0;sl!=string::npos;sl=path.find('/',sl+1)) { | ||
83 | if(!sl) | ||
84 | continue; | ||
85 | string p = path.substr(0,sl); | ||
86 | if(stat(p.c_str(),&st) || !S_ISDIR(st.st_mode)) { | ||
87 | if(mkdir(p.c_str(),mode)) | ||
88 | throw konforka::exception(CODEPOINT,"failed to mkdir()"); | ||
89 | } | ||
90 | } | ||
91 | if(stat(path.c_str(),&st) || !S_ISDIR(st.st_mode)) { | ||
92 | if(mkdir(path.c_str(),mode)) | ||
93 | throw konforka::exception(CODEPOINT,"failed to mkdir()"); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | void file_lock::lock(const string& f) { | 35 | void file_lock::lock(const string& f) { |
98 | unlock(); | 36 | unlock(); |
99 | fd = open(f.c_str(),O_CREAT|O_RDWR,S_IRUSR|S_IWUSR); | 37 | fd = open(f.c_str(),O_CREAT|O_RDWR,S_IRUSR|S_IWUSR); |
100 | if(fd<0) | 38 | if(fd<0) |
101 | throw konforka::exception(CODEPOINT,"failed to open/create lockfile"); | 39 | throw konforka::exception(CODEPOINT,"failed to open/create lockfile"); |
102 | try { | 40 | try { |
103 | lock(); | 41 | lock(); |
104 | }catch(konforka::exception& ke) { | 42 | }catch(konforka::exception& ke) { |
105 | ke.see(CODEPOINT); | 43 | ke.see(CODEPOINT); |
106 | close(fd); fd=-1; | 44 | close(fd); fd=-1; |
107 | throw; | 45 | throw; |
108 | }catch(...) { | 46 | }catch(...) { |
109 | close(fd); fd=-1; | 47 | close(fd); fd=-1; |
110 | throw; | 48 | throw; |
111 | } | 49 | } |
112 | } | 50 | } |
113 | void file_lock::lock() { | 51 | void file_lock::lock() { |
114 | assert(fd>=0); | 52 | assert(fd>=0); |
115 | struct flock fl; | 53 | struct flock fl; |
116 | fl.l_type = F_WRLCK; | 54 | fl.l_type = F_WRLCK; |
117 | fl.l_whence=SEEK_SET; | 55 | fl.l_whence=SEEK_SET; |
118 | fl.l_start=fl.l_len=0; | 56 | fl.l_start=fl.l_len=0; |
119 | for(int tries=3;tries;tries--) { | 57 | for(int tries=3;tries;tries--) { |
120 | if(!fcntl(fd,F_SETLK,&fl)) | 58 | if(!fcntl(fd,F_SETLK,&fl)) |
121 | return; | 59 | return; |
122 | sleep(8); | 60 | sleep(8); |
123 | } | 61 | } |
124 | throw konforka::exception(CODEPOINT,"failed to obtain file lock"); | 62 | throw konforka::exception(CODEPOINT,"failed to obtain file lock"); |
125 | } | 63 | } |
126 | void file_lock::unlock() { | 64 | void file_lock::unlock() { |
127 | if(fd<0) | 65 | if(fd<0) |
128 | return; | 66 | return; |
129 | struct flock fl; | 67 | struct flock fl; |
130 | fl.l_type = F_UNLCK; | 68 | fl.l_type = F_UNLCK; |
131 | fl.l_whence=SEEK_SET; | 69 | fl.l_whence=SEEK_SET; |
132 | fl.l_start=fl.l_len=0; | 70 | fl.l_start=fl.l_len=0; |
133 | int rv = fcntl(fd,F_SETLK,&fl); | 71 | int rv = fcntl(fd,F_SETLK,&fl); |
134 | close(fd); | 72 | close(fd); |
135 | fd=-1; | 73 | fd=-1; |
136 | if(rv) | 74 | if(rv) |
137 | throw konforka::exception(CODEPOINT,"failed to release file lock"); | 75 | throw konforka::exception(CODEPOINT,"failed to release file lock"); |
138 | } | 76 | } |
139 | 77 | ||
140 | void pid_file::set(const string& f,bool u) { | 78 | void pid_file::set(const string& f,bool u) { |
141 | ofstream of(f.c_str(),ios::trunc); | 79 | ofstream of(f.c_str(),ios::trunc); |
142 | if(!of) | 80 | if(!of) |
143 | throw konforka::exception(CODEPOINT,"failed to open file for writing pid"); | 81 | throw konforka::exception(CODEPOINT,"failed to open file for writing pid"); |
144 | of << getpid() << endl; | 82 | of << getpid() << endl; |
145 | of.close(); | 83 | of.close(); |
146 | file_name = f; | 84 | file_name = f; |
147 | unlink_pid = u; | 85 | unlink_pid = u; |
148 | } | 86 | } |
149 | void pid_file::unlink() { | 87 | void pid_file::unlink() { |
150 | if(!unlink_pid) | 88 | if(!unlink_pid) |
151 | return; | 89 | return; |
152 | ::unlink(file_name.c_str()); | 90 | ::unlink(file_name.c_str()); |
153 | } | 91 | } |
154 | 92 | ||
155 | void semaphore::init() { | 93 | void semaphore::init() { |
156 | deinit(); | 94 | deinit(); |
157 | semid = semget(IPC_PRIVATE,1,IPC_CREAT|0600); | 95 | semid = semget(IPC_PRIVATE,1,IPC_CREAT|0600); |
158 | if(semid<0) | 96 | if(semid<0) |
159 | throw konforka::exception(CODEPOINT,"failed to semget()"); | 97 | throw konforka::exception(CODEPOINT,"failed to semget()"); |
160 | if(semctl(semid,0,SETVAL,1)) | 98 | if(semctl(semid,0,SETVAL,1)) |
161 | throw konforka::exception(CODEPOINT,"failed to semctl()"); | 99 | throw konforka::exception(CODEPOINT,"failed to semctl()"); |
162 | } | 100 | } |
163 | void semaphore::deinit() { | 101 | void semaphore::deinit() { |
164 | if(semid<0) | 102 | if(semid<0) |
165 | return; | 103 | return; |
166 | semctl(semid,0,IPC_RMID,0); | 104 | semctl(semid,0,IPC_RMID,0); |
167 | } | 105 | } |
168 | void semaphore::on() { | 106 | void semaphore::on() { |
169 | assert(semid>=0); | 107 | assert(semid>=0); |
170 | struct sembuf sb; | 108 | struct sembuf sb; |
171 | sb.sem_num=0; | 109 | sb.sem_num=0; |
172 | sb.sem_op=-1; | 110 | sb.sem_op=-1; |
173 | sb.sem_flg = SEM_UNDO; | 111 | sb.sem_flg = SEM_UNDO; |
174 | while(semop(semid,&sb,1)<0) { | 112 | while(semop(semid,&sb,1)<0) { |
175 | if(errno!=EINTR) | 113 | if(errno!=EINTR) |
176 | throw konforka::exception(CODEPOINT,"failed to semop()"); | 114 | throw konforka::exception(CODEPOINT,"failed to semop()"); |
177 | } | 115 | } |
178 | } | 116 | } |
179 | void semaphore::off() { | 117 | void semaphore::off() { |
180 | assert(semid>=0); | 118 | assert(semid>=0); |
181 | struct sembuf sb; | 119 | struct sembuf sb; |
182 | sb.sem_num=0; | 120 | sb.sem_num=0; |
183 | sb.sem_op=1; | 121 | sb.sem_op=1; |
184 | sb.sem_flg = SEM_UNDO; | 122 | sb.sem_flg = SEM_UNDO; |
185 | while(semop(semid,&sb,1)<0) { | 123 | while(semop(semid,&sb,1)<0) { |
186 | if(errno!=EINTR) | 124 | if(errno!=EINTR) |
187 | throw konforka::exception(CODEPOINT,"failed to semop()"); | 125 | throw konforka::exception(CODEPOINT,"failed to semop()"); |
188 | } | 126 | } |
189 | } | 127 | } |
190 | 128 | ||
191 | void semaphore_lock::lock() { | 129 | void semaphore_lock::lock() { |
192 | assert(sem); | 130 | assert(sem); |
193 | if(locked) | 131 | if(locked) |
194 | return; | 132 | return; |
195 | sem->on(); | 133 | sem->on(); |
196 | locked = true; | 134 | locked = true; |
197 | } | 135 | } |
198 | void semaphore_lock::unlock() { | 136 | void semaphore_lock::unlock() { |
199 | if(!sem) | 137 | if(!sem) |
200 | return; | 138 | return; |
201 | if(!locked) | 139 | if(!locked) |
202 | return; | 140 | return; |
203 | sem->off(); | 141 | sem->off(); |
204 | locked=false; | 142 | locked=false; |
205 | } | 143 | } |
206 | 144 | ||
207 | string combine_path(const string& origin,const string& relative,int opts) { | ||
208 | string r = normalize_path(relative,0); | ||
209 | string rv; | ||
210 | // XXX: what to do if relative is empty is a question, really. | ||
211 | if(r.empty()) { | ||
212 | return normalize_path( (opts&origin_is_file)?dir_name(origin):origin ,strip_leading_slash|restrict_dotdot|strip_trailing_slash); | ||
213 | }else{ | ||
214 | if(r[0]=='/') { | ||
215 | r.erase(0,1); | ||
216 | }else{ | ||
217 | rv = normalize_path((opts&origin_is_file)?dir_name(origin):origin,restrict_dotdot|strip_trailing_slash); | ||
218 | } | ||
219 | } | ||
220 | string::size_type lsl = rv.rfind('/'); | ||
221 | for(string::size_type sl=r.find('/');sl!=string::npos;sl=r.find('/')) { | ||
222 | assert(sl!=0); | ||
223 | if(sl==1 && r[0]=='.') { | ||
224 | // it's a "./" | ||
225 | r.erase(0,2); | ||
226 | }else if(sl==2 && r[0]=='.' && r[1]=='.') { | ||
227 | // we have a "../" | ||
228 | if(lsl==string::npos) { | ||
229 | if(rv.empty() && (opts&fail_beyond_root)) | ||
230 | throw utility_beyond_root(CODEPOINT,"went beyond root while combining path"); | ||
231 | rv.clear(); | ||
232 | }else{ | ||
233 | rv.erase(lsl); | ||
234 | lsl = rv.rfind('/'); | ||
235 | } | ||
236 | r.erase(0,3); | ||
237 | }else{ | ||
238 | // we have a "something/" | ||
239 | lsl = rv.length(); | ||
240 | rv += '/'; | ||
241 | rv += r.substr(0,sl); | ||
242 | r.erase(0,sl+1); | ||
243 | } | ||
244 | } | ||
245 | if(r.empty()) | ||
246 | return rv+'/'; | ||
247 | if(r.length()==2 && r[0]=='.' && r[0]=='.') { | ||
248 | if(lsl==string::npos) { | ||
249 | if(rv.empty() & (opts&fail_beyond_root)) | ||
250 | throw utility_beyond_root(CODEPOINT,"went beyond root while combining path"); | ||
251 | return "/"; | ||
252 | }else{ | ||
253 | rv.erase(lsl+1); | ||
254 | return rv; | ||
255 | } | ||
256 | } | ||
257 | rv += '/'; | ||
258 | rv += r; | ||
259 | return rv; | ||
260 | } | ||
261 | |||
262 | void auto_chdir::pushdir(const string& td,bool ap) { | 145 | void auto_chdir::pushdir(const string& td,bool ap) { |
263 | /* TODO: make use of fchdir(2) instead */ | 146 | /* TODO: make use of fchdir(2) instead */ |
264 | char *tmp = getcwd(0,0); | 147 | char *tmp = getcwd(0,0); |
265 | assert(tmp); | 148 | assert(tmp); |
266 | saved_pwd = tmp; | 149 | saved_pwd = tmp; |
267 | free(tmp); | 150 | free(tmp); |
268 | autopop=ap; | 151 | autopop=ap; |
269 | if(chdir(td.c_str())) | 152 | if(chdir(td.c_str())) |
270 | throw konforka::exception(CODEPOINT,"failed to chdir()"); | 153 | throw konforka::exception(CODEPOINT,"failed to chdir()"); |
271 | } | 154 | } |
272 | void auto_chdir::popdir() { | 155 | void auto_chdir::popdir() { |
273 | autopop=false; | 156 | autopop=false; |
274 | if(chdir(saved_pwd.c_str())) | 157 | if(chdir(saved_pwd.c_str())) |
275 | throw konforka::exception(CODEPOINT,"failed to chdir()"); | 158 | throw konforka::exception(CODEPOINT,"failed to chdir()"); |
276 | // XXX: or should it be thrown? after all we call it from destructor... | 159 | // XXX: or should it be thrown? after all we call it from destructor... |
277 | } | 160 | } |
278 | 161 | ||
279 | } | 162 | } |
diff --git a/lib/sitespace.cc b/lib/sitespace.cc index 0406d11..d5592bf 100644 --- a/lib/sitespace.cc +++ b/lib/sitespace.cc | |||
@@ -1,52 +1,53 @@ | |||
1 | #ifdef USE_PCH | 1 | #ifdef USE_PCH |
2 | #include "pch.h" | 2 | #include "pch.h" |
3 | #else | 3 | #else |
4 | #include <cassert> | 4 | #include <cassert> |
5 | #include <konforka/util.h> | ||
5 | #include "sitecing/sitespace.h" | 6 | #include "sitecing/sitespace.h" |
6 | #include "sitecing/sitecing_util.h" | 7 | #include "sitecing/sitecing_util.h" |
7 | #endif | 8 | #endif |
8 | 9 | ||
9 | namespace sitecing { | 10 | namespace sitecing { |
10 | 11 | ||
11 | sitespace::sitespace(configuration& c) | 12 | sitespace::sitespace(configuration& c) |
12 | : config(c), factory(c) { } | 13 | : config(c), factory(c) { } |
13 | 14 | ||
14 | sitespace::~sitespace() { | 15 | sitespace::~sitespace() { |
15 | for(sentenced_t::iterator i = sentenced.begin();i!=sentenced.end();++i) { | 16 | for(sentenced_t::iterator i = sentenced.begin();i!=sentenced.end();++i) { |
16 | assert((*i)->chickens_used.empty()); | 17 | assert((*i)->chickens_used.empty()); |
17 | delete *i; | 18 | delete *i; |
18 | } | 19 | } |
19 | } | 20 | } |
20 | 21 | ||
21 | so_component sitespace::fetch(const string& c,sitecing_interface* scif) { | 22 | so_component sitespace::fetch(const string& c,sitecing_interface* scif) { |
22 | execute_sentenced(); | 23 | execute_sentenced(); |
23 | string sobase = normalize_path(c); | 24 | string sobase = konforka::normalize_path(c); |
24 | string sopath = factory.root_so+sobase+".so"; | 25 | string sopath = factory.root_so+sobase+".so"; |
25 | config_options *co_build = config.lookup_config(sobase,config_options::flag_build); | 26 | config_options *co_build = config.lookup_config(sobase,config_options::flag_build); |
26 | if( (!co_build) || co_build->build ) | 27 | if( (!co_build) || co_build->build ) |
27 | factory.make(sopath); | 28 | factory.make(sopath); |
28 | components_t::iterator i = components.find(sopath); | 29 | components_t::iterator i = components.find(sopath); |
29 | if(i!=components.end()) { | 30 | if(i!=components.end()) { |
30 | if(i->second->is_uptodate()) | 31 | if(i->second->is_uptodate()) |
31 | return so_component(i->second,scif); | 32 | return so_component(i->second,scif); |
32 | if(i->second->chickens_used.empty()) { | 33 | if(i->second->chickens_used.empty()) { |
33 | delete i->second; | 34 | delete i->second; |
34 | }else{ | 35 | }else{ |
35 | sentenced.push_back(i->second); | 36 | sentenced.push_back(i->second); |
36 | } | 37 | } |
37 | components.erase(i); | 38 | components.erase(i); |
38 | } | 39 | } |
39 | pair<components_t::iterator,bool> ins = components.insert(components_t::value_type(sopath,new component_so(sopath))); | 40 | pair<components_t::iterator,bool> ins = components.insert(components_t::value_type(sopath,new component_so(sopath))); |
40 | return so_component(ins.first->second,scif); | 41 | return so_component(ins.first->second,scif); |
41 | } | 42 | } |
42 | 43 | ||
43 | void sitespace::execute_sentenced() { | 44 | void sitespace::execute_sentenced() { |
44 | for(sentenced_t::iterator i = sentenced.begin();i!=sentenced.end();++i) { | 45 | for(sentenced_t::iterator i = sentenced.begin();i!=sentenced.end();++i) { |
45 | if((*i)->chickens_used.empty()) { | 46 | if((*i)->chickens_used.empty()) { |
46 | delete *i; | 47 | delete *i; |
47 | sentenced.erase(i); | 48 | sentenced.erase(i); |
48 | } | 49 | } |
49 | } | 50 | } |
50 | } | 51 | } |
51 | 52 | ||
52 | } | 53 | } |