summaryrefslogtreecommitdiffabout
path: root/lib
Unidiff
Diffstat (limited to 'lib') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/component_factory.cc31
-rw-r--r--lib/configuration.cc9
-rw-r--r--lib/sitecing_parser.ll13
-rw-r--r--lib/sitecing_util.cc117
-rw-r--r--lib/sitespace.cc3
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
20namespace sitecing { 21namespace 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
15namespace sitecing { 16namespace 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>
9using namespace std; 9using 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"
12using namespace sitecing; 13using 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
571sitecing_parser::sitecing_parser(component_factory& f) 572sitecing_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
578void sitecing_parser::preprocess(const string& in) { 579void 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
604void sitecing_parser::LexerOutput(const char* buf,int size) { 605void 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
609static const char *modus_transitions 610static 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
620void sitecing_parser::modus_operandi::modify(modus_t m) { 621void 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
627void sitecing_parser::soft_anchor() { 628void 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}
631void sitecing_parser::anchor() { 632void 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
17namespace sitecing { 17namespace 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
9namespace sitecing { 10namespace 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}