summaryrefslogtreecommitdiffabout
authorMichael Krelin <hacker@klever.net>2005-04-25 16:36:32 (UTC)
committer Michael Krelin <hacker@klever.net>2005-04-25 16:36:32 (UTC)
commit981b219f5297ad2ccc1fc1d0e24e41ec009c35a3 (patch) (unidiff)
tree9fa81d7fe70883ad26d946c902ba06edcebd4516
parent54e344b7e3623e807b893b7febad3adfc6c1648f (diff)
downloadsitecing-981b219f5297ad2ccc1fc1d0e24e41ec009c35a3.zip
sitecing-981b219f5297ad2ccc1fc1d0e24e41ec009c35a3.tar.gz
sitecing-981b219f5297ad2ccc1fc1d0e24e41ec009c35a3.tar.bz2
moved a few utility functions to konforka and bumped konforka version requirement accordingly
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--components/exception_dev7
-rw-r--r--configure.ac4
-rw-r--r--include/sitecing/sitecing_util.h87
-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
-rw-r--r--src/sitecing-build.cc5
-rw-r--r--src/sitecing-fastcgi.cc4
-rw-r--r--src/sitecing-plaincgi.cc4
11 files changed, 48 insertions, 236 deletions
diff --git a/components/exception_dev b/components/exception_dev
index d8c84e1..d62f462 100644
--- a/components/exception_dev
+++ b/components/exception_dev
@@ -1,346 +1,347 @@
1%%decl using namespace std; 1%%decl using namespace std;
2<%impl> 2<%impl>
3 #include <iostream> 3 #include <iostream>
4 #include <fstream> 4 #include <fstream>
5 #include <sstream> 5 #include <sstream>
6 #include <cassert> 6 #include <cassert>
7 #include <cstdarg> 7 #include <cstdarg>
8 #include <stdexcept> 8 #include <stdexcept>
9 #include <cxxabi.h> 9 #include <cxxabi.h>
10 #include <sitecing/sitecing_util.h> 10 #include <sitecing/sitecing_util.h>
11 #include <sitecing/util.h> 11 #include <sitecing/util.h>
12 #include <sitecing/magic.h> 12 #include <sitecing/magic.h>
13 #include <konforka/util.h>
13 #include <konforka/exception.h> 14 #include <konforka/exception.h>
14</%impl> 15</%impl>
15%%var string message; 16%%var string message;
16%%var string root_source; 17%%var string root_source;
17%%var string root_intermediate; 18%%var string root_intermediate;
18%%var string root_so; 19%%var string root_so;
19%%var string component; 20%%var string component;
20%%var int line_number = -1; 21%%var int line_number = -1;
21%%var const exception* exception_caught; 22%%var const exception* exception_caught;
22<%code> 23<%code>
23 __SCIF->headers.clear(); 24 __SCIF->headers.clear();
24 __SCIF->out->seekp(0); 25 __SCIF->out->seekp(0);
25 int magic = _magic; 26 int magic = _magic;
26 va_list va = _args; 27 va_list va = _args;
27 switch(magic) { 28 switch(magic) {
28 case sitecing::__magic_compile_error: 29 case sitecing::__magic_compile_error:
29 message = va_arg(va,const char*); 30 message = va_arg(va,const char*);
30 root_source = va_arg(va,const char*); 31 root_source = va_arg(va,const char*);
31 root_intermediate = va_arg(va,const char*); 32 root_intermediate = va_arg(va,const char*);
32 root_so = va_arg(va,const char*); 33 root_so = va_arg(va,const char*);
33 component = va_arg(va,const char*); 34 component = va_arg(va,const char*);
34 break; 35 break;
35 case sitecing::__magic_preprocess_error: 36 case sitecing::__magic_preprocess_error:
36 message = va_arg(va,const char*); 37 message = va_arg(va,const char*);
37 root_source = va_arg(va,const char*); 38 root_source = va_arg(va,const char*);
38 root_intermediate = va_arg(va,const char*); 39 root_intermediate = va_arg(va,const char*);
39 root_so = va_arg(va,const char*); 40 root_so = va_arg(va,const char*);
40 component = va_arg(va,const char*); 41 component = va_arg(va,const char*);
41 line_number = va_arg(va,int); 42 line_number = va_arg(va,int);
42 break; 43 break;
43 case sitecing::__magic_generic_exception: 44 case sitecing::__magic_generic_exception:
44 message = va_arg(va,const char*); 45 message = va_arg(va,const char*);
45 root_source = va_arg(va,const char*); 46 root_source = va_arg(va,const char*);
46 root_intermediate = va_arg(va,const char *); 47 root_intermediate = va_arg(va,const char *);
47 root_so = va_arg(va,const char *); 48 root_so = va_arg(va,const char *);
48 component = va_arg(va,const char*); 49 component = va_arg(va,const char*);
49 exception_caught = va_arg(va,const exception*); 50 exception_caught = va_arg(va,const exception*);
50 break; 51 break;
51 default: 52 default:
52 break; 53 break;
53 } 54 }
54</%code> 55</%code>
55<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 56<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
56<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> 57<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
57 <head> 58 <head>
58 <title><% message %></title> 59 <title><% message %></title>
59 <style type="text/css"> 60 <style type="text/css">
60 <!-- 61 <!--
61 body { 62 body {
62 font-family: sans-serif; 63 font-family: sans-serif;
63 font-size: 11pt; 64 font-size: 11pt;
64 } 65 }
65 66
66 h1 { 67 h1 {
67 font-family: serif; 68 font-family: serif;
68 font-size: 130%; 69 font-size: 130%;
69 font-weight: bold; 70 font-weight: bold;
70 text-align: center; 71 text-align: center;
71 } 72 }
72 p { 73 p {
73 text-indent: 2em; 74 text-indent: 2em;
74 text-align: justify; 75 text-align: justify;
75 } 76 }
76 77
77 dl.exception-props { 78 dl.exception-props {
78 margin: 1ex 1em; 79 margin: 1ex 1em;
79 padding: 0.5ex; 80 padding: 0.5ex;
80 border: solid 1px gray; 81 border: solid 1px gray;
81 background-color: #e0e0e0; 82 background-color: #e0e0e0;
82 } 83 }
83 dl.exception-props dt { 84 dl.exception-props dt {
84 font-weight: bold; 85 font-weight: bold;
85 color: blue; 86 color: blue;
86 } 87 }
87 dl.exception-props dd { 88 dl.exception-props dd {
88 color: gray; 89 color: gray;
89 } 90 }
90 91
91 div.exception-codepoint-report { 92 div.exception-codepoint-report {
92 border: solid 1px black; 93 border: solid 1px black;
93 margin: 0.5ex 1em 0.ex 3em; 94 margin: 0.5ex 1em 0.ex 3em;
94 } 95 }
95 div.exception-codepoint-report h3 { 96 div.exception-codepoint-report h3 {
96 display: block; 97 display: block;
97 color: blue; 98 color: blue;
98 border-bottom: 3px double black; 99 border-bottom: 3px double black;
99 padding: 0.3ex; margin: 0px; 100 padding: 0.3ex; margin: 0px;
100 background: #e0e0e0; 101 background: #e0e0e0;
101 } 102 }
102 div.exception-codepoint-report ul { 103 div.exception-codepoint-report ul {
103 padding: 0px; 104 padding: 0px;
104 margin: 0px; 105 margin: 0px;
105 background: #87fdff; 106 background: #87fdff;
106 font-size: 70%; 107 font-size: 70%;
107 } 108 }
108 div.exception-codepoint-report li { 109 div.exception-codepoint-report li {
109 font-family: monospace; 110 font-family: monospace;
110 list-style-type: none; 111 list-style-type: none;
111 white-space: nowrap; 112 white-space: nowrap;
112 overflow: hidden; 113 overflow: hidden;
113 } 114 }
114 div.exception-codepoint-report li.focused { 115 div.exception-codepoint-report li.focused {
115 color: red; 116 color: red;
116 border-top: solid 1px red; border-bottom: solid 1px red; 117 border-top: solid 1px red; border-bottom: solid 1px red;
117 } 118 }
118 div.exception-codepoint-report li .lineno { 119 div.exception-codepoint-report li .lineno {
119 padding-right: 0.5ex; 120 padding-right: 0.5ex;
120 border-right: dotted black 1px; 121 border-right: dotted black 1px;
121 } 122 }
122 div.exception-codepoint-report div.what { 123 div.exception-codepoint-report div.what {
123 border-top: double 3px black; 124 border-top: double 3px black;
124 padding: 0.5ex 2em; 125 padding: 0.5ex 2em;
125 font-weight: bold; color: #4040c0; 126 font-weight: bold; color: #4040c0;
126 overflow: auto; 127 overflow: auto;
127 } 128 }
128 div.backtrace div.exception-codepoint-report div.what { 129 div.backtrace div.exception-codepoint-report div.what {
129 color: gray; 130 color: gray;
130 } 131 }
131 132
132 div.exception-compile div.what { 133 div.exception-compile div.what {
133 font-weight: normal; 134 font-weight: normal;
134 color: red; 135 color: red;
135 } 136 }
136 137
137 div.powered { 138 div.powered {
138 margin: 2em 0px 0px 50%; 139 margin: 2em 0px 0px 50%;
139 padding: 1ex 2ex; 140 padding: 1ex 2ex;
140 text-align: right; 141 text-align: right;
141 font-family: serif; 142 font-family: serif;
142 font-size: 140%; 143 font-size: 140%;
143 font-weight: bold; 144 font-weight: bold;
144 border-top: solid 2px black; 145 border-top: solid 2px black;
145 border-left: solid 1px gray; border-right: solid 1px gray; border-bottom: solid 1px gray; 146 border-left: solid 1px gray; border-right: solid 1px gray; border-bottom: solid 1px gray;
146 background: #c0c0f0; 147 background: #c0c0f0;
147 } 148 }
148 --> 149 -->
149 </style> 150 </style>
150% __SCIF->headers["Content-Type"]="text/html; charset=utf-8"; 151% __SCIF->headers["Content-Type"]="text/html; charset=utf-8";
151% __SCIF->headers["Pragma"]="no-cache"; 152% __SCIF->headers["Pragma"]="no-cache";
152 </head> 153 </head>
153 <body> 154 <body>
154 <%code> 155 <%code>
155 switch(magic) { 156 switch(magic) {
156 case sitecing::__magic_compile_error: 157 case sitecing::__magic_compile_error:
157 handle_compile_error(); 158 handle_compile_error();
158 break; 159 break;
159 case sitecing::__magic_preprocess_error: 160 case sitecing::__magic_preprocess_error:
160 handle_preprocess_error(); 161 handle_preprocess_error();
161 break; 162 break;
162 case sitecing::__magic_generic_exception: 163 case sitecing::__magic_generic_exception:
163 handle_generic_exception(); 164 handle_generic_exception();
164 break; 165 break;
165 default: 166 default:
166 handle_unknown_error(); 167 handle_unknown_error();
167 break; 168 break;
168 } 169 }
169 </%code> 170 </%code>
170 <div class="powered">Powered by <a href="http://kin.klever.net/sitecing/" title="site-C-ing">site-C-ing</a>.</div> 171 <div class="powered">Powered by <a href="http://kin.klever.net/sitecing/" title="site-C-ing">site-C-ing</a>.</div>
171 </body> 172 </body>
172</html> 173</html>
173<%method void handle_generic_exception() %> 174<%method void handle_generic_exception() %>
174 <div class="exception-generic"> 175 <div class="exception-generic">
175 <h1>exception caught while running component '<code><% component %></code>'</h1> 176 <h1>exception caught while running component '<code><% component %></code>'</h1>
176 <dl class="exception-props"> 177 <dl class="exception-props">
177 <dt><code>typeid(<em>e</em>).name()</code></dt> 178 <dt><code>typeid(<em>e</em>).name()</code></dt>
178% int destat; 179% int destat;
179% char *demangled = abi::__cxa_demangle(typeid(*exception_caught).name(),NULL,NULL,&destat); 180% char *demangled = abi::__cxa_demangle(typeid(*exception_caught).name(),NULL,NULL,&destat);
180 <dd><code><% destat?typeid(*exception_caught).name():demangled %></code></dd> 181 <dd><code><% destat?typeid(*exception_caught).name():demangled %></code></dd>
181% if(!destat) free(demangled); 182% if(!destat) free(demangled);
182 <dt><code><em>e</em>.what()</code></dt> 183 <dt><code><em>e</em>.what()</code></dt>
183 <dd><% message %></dd> 184 <dd><% message %></dd>
184% if(typeid(*exception_caught)==typeid(konforka::exception&)) { 185% if(typeid(*exception_caught)==typeid(konforka::exception&)) {
185% konforka::exception* ke = (konforka::exception*)exception_caught; 186% konforka::exception* ke = (konforka::exception*)exception_caught;
186 <dt><code><em>e</em>.where()</code></dt> 187 <dt><code><em>e</em>.where()</code></dt>
187 <dd><code> 188 <dd><code>
188% if(ke->_where.line<0) { 189% if(ke->_where.line<0) {
189 <% ke->where() %> 190 <% ke->where() %>
190% }else{ 191% }else{
191 <% strip_roots(ke->_where.file) %>:<% ke->_where.line %> [<% ke->_where.function %>] 192 <% strip_roots(ke->_where.file) %>:<% ke->_where.line %> [<% ke->_where.function %>]
192% } 193% }
193 </code></dd> 194 </code></dd>
194% } 195% }
195 </dl> 196 </dl>
196% if(typeid(*exception_caught)==typeid(konforka::exception&)) { 197% if(typeid(*exception_caught)==typeid(konforka::exception&)) {
197% konforka::exception* ke = (konforka::exception*)exception_caught; 198% konforka::exception* ke = (konforka::exception*)exception_caught;
198% if(ke->_where.line>=0) { 199% if(ke->_where.line>=0) {
199% report_error(ke->_where.file,ke->_where.line,ke->what()); 200% report_error(ke->_where.file,ke->_where.line,ke->what());
200% } 201% }
201% if(!ke->_seen.empty()) { 202% if(!ke->_seen.empty()) {
202 <h2>seen at:</h2> 203 <h2>seen at:</h2>
203 <div class="backtrace"> 204 <div class="backtrace">
204% for(list<konforka::code_point>::const_iterator i=ke->_seen.begin();i!=ke->_seen.end();++i) { 205% for(list<konforka::code_point>::const_iterator i=ke->_seen.begin();i!=ke->_seen.end();++i) {
205% if(i->line>=0) { 206% if(i->line>=0) {
206% report_error(i->file,i->line,i->function); 207% report_error(i->file,i->line,i->function);
207% } 208% }
208% } 209% }
209 </div> 210 </div>
210% } 211% }
211% } 212% }
212 </div> 213 </div>
213</%method> 214</%method>
214<%method void handle_preprocess_error() %> 215<%method void handle_preprocess_error() %>
215 <div class="exception-preprocess"> 216 <div class="exception-preprocess">
216 <h1>error preprocessing component '<code><% component %></code>'</h1> 217 <h1>error preprocessing component '<code><% component %></code>'</h1>
217% report_error(root_source+component,line_number,message); 218% report_error(root_source+component,line_number,message);
218 </div> 219 </div>
219</%method> 220</%method>
220<%method void handle_compile_error() %> 221<%method void handle_compile_error() %>
221 <div class="exception-compile"> 222 <div class="exception-compile">
222 <h1>error compiling component '<code><% component %></code>'</h1> 223 <h1>error compiling component '<code><% component %></code>'</h1>
223 <%code> 224 <%code>
224 ifstream err((root_intermediate+component+".stderr").c_str(),ios::in); 225 ifstream err((root_intermediate+component+".stderr").c_str(),ios::in);
225 if(err.bad()) { 226 if(err.bad()) {
226 <%output> 227 <%output>
227 Failed to access compiler output 228 Failed to access compiler output
228 </%output> 229 </%output>
229 }else{ 230 }else{
230 string cumulative; 231 string cumulative;
231 string error_file; 232 string error_file;
232 long error_line = -1; 233 long error_line = -1;
233 while(!err.eof()) { 234 while(!err.eof()) {
234 string oef = error_file; 235 string oef = error_file;
235 long oel = error_line; 236 long oel = error_line;
236 string line; 237 string line;
237 getline(err,line); 238 getline(err,line);
238 if(line[0]!=' ') { 239 if(line[0]!=' ') {
239 string::size_type c = line.find(':'); 240 string::size_type c = line.find(':');
240 if(c!=string::npos) { 241 if(c!=string::npos) {
241 string fn = line.substr(0,c); 242 string fn = line.substr(0,c);
242 string::size_type c1 = line.find(':',c+1); 243 string::size_type c1 = line.find(':',c+1);
243 if(c1!=string::npos) { 244 if(c1!=string::npos) {
244 string ln = line.substr(c+1,c1-c-1); 245 string ln = line.substr(c+1,c1-c-1);
245 string::size_type nd = ln.find_first_not_of("0123456789"); 246 string::size_type nd = ln.find_first_not_of("0123456789");
246 if(nd==string::npos) { 247 if(nd==string::npos) {
247 try { 248 try {
248 error_file = sitecing::strip_prefix(fn,"In file included from "); 249 error_file = sitecing::strip_prefix(fn,"In file included from ");
249 }catch(sitecing::utility_no_prefix& unp) { 250 }catch(sitecing::utility_no_prefix& unp) {
250 error_file = fn; 251 error_file = fn;
251 } 252 }
252 error_line = strtol(ln.c_str(),0,10); 253 error_line = strtol(ln.c_str(),0,10);
253 } 254 }
254 } 255 }
255 } 256 }
256 if((oel>0 && !oef.empty()) && (oel!=error_line || oef!=error_file)) { 257 if((oel>0 && !oef.empty()) && (oel!=error_line || oef!=error_file)) {
257 string ef = "/"+sitecing::combine_path(root_source+component,oef); 258 string ef = "/"+konforka::combine_path(root_source+component,oef);
258 report_error(ef,oel,remove_roots(cumulative)); 259 report_error(ef,oel,remove_roots(cumulative));
259 cumulative.clear(); 260 cumulative.clear();
260 } 261 }
261 } 262 }
262 if(!cumulative.empty()) 263 if(!cumulative.empty())
263 cumulative += '\n'; 264 cumulative += '\n';
264 cumulative += line; 265 cumulative += line;
265 } 266 }
266 if(!(cumulative.empty() || error_file.empty() || error_line<0)) { 267 if(!(cumulative.empty() || error_file.empty() || error_line<0)) {
267 error_file = "/"+sitecing::combine_path(root_source+component,error_file); 268 error_file = "/"+konforka::combine_path(root_source+component,error_file);
268 report_error(error_file,error_line,remove_roots(cumulative)); 269 report_error(error_file,error_line,remove_roots(cumulative));
269 } 270 }
270 } 271 }
271 </%code> 272 </%code>
272 </div> 273 </div>
273</%method> 274</%method>
274<%method void handle_unknown_error() %> 275<%method void handle_unknown_error() %>
275 <div class="exception-unknown"> 276 <div class="exception-unknown">
276 <h1>unknown error</h1> 277 <h1>unknown error</h1>
277 </div> 278 </div>
278</%method> 279</%method>
279<%method void report_error(const string& file,long line,const string& message) %> 280<%method void report_error(const string& file,long line,const string& message) %>
280 <div class="exception-codepoint-report"> 281 <div class="exception-codepoint-report">
281 <h3><% sitecing::html_escape(strip_roots(file)) %></h3> 282 <h3><% sitecing::html_escape(strip_roots(file)) %></h3>
282 <%code> 283 <%code>
283 if(line>=0) { 284 if(line>=0) {
284 int firstline = line-5, lastline = line+5; 285 int firstline = line-5, lastline = line+5;
285 if(firstline<1) 286 if(firstline<1)
286 firstline = 1; 287 firstline = 1;
287 ifstream ifs(file.c_str(),ios::in); 288 ifstream ifs(file.c_str(),ios::in);
288 if(ifs.bad()) { 289 if(ifs.bad()) {
289 // TODO: 290 // TODO:
290 }else{ 291 }else{
291 for(int l=1;l<firstline && !ifs.eof();l++) { 292 for(int l=1;l<firstline && !ifs.eof();l++) {
292 ifs.ignore(65536,'\n'); 293 ifs.ignore(65536,'\n');
293 } 294 }
294 if(ifs.eof()) { 295 if(ifs.eof()) {
295 // TODO: no such line in file 296 // TODO: no such line in file
296 }else{ 297 }else{
297 <%output><ul></%output> 298 <%output><ul></%output>
298 for(int l=firstline;l<=lastline && !ifs.eof();l++) { 299 for(int l=firstline;l<=lastline && !ifs.eof();l++) {
299 string str; 300 string str;
300 getline(ifs,str); 301 getline(ifs,str);
301 for(string::size_type t=str.find('\t');t!=string::npos;t=str.find('\t')) { 302 for(string::size_type t=str.find('\t');t!=string::npos;t=str.find('\t')) {
302 str.replace(t,1,8-(t%8),' '); 303 str.replace(t,1,8-(t%8),' ');
303 } 304 }
304 char tln[16]; 305 char tln[16];
305 snprintf(tln,sizeof(tln),"%5d",l); 306 snprintf(tln,sizeof(tln),"%5d",l);
306 <%output> 307 <%output>
307 <li class="<% l==line?"focused":"unfocused" %>"><span class="lineno"><% sitecing::html_escape(tln,sitecing::html_escape_nbsp) %></span>&nbsp;<span class="line"><% sitecing::html_escape(str,sitecing::html_escape_nbsp) %></span></li> 308 <li class="<% l==line?"focused":"unfocused" %>"><span class="lineno"><% sitecing::html_escape(tln,sitecing::html_escape_nbsp) %></span>&nbsp;<span class="line"><% sitecing::html_escape(str,sitecing::html_escape_nbsp) %></span></li>
308 </%output> 309 </%output>
309 } 310 }
310 <%output></ul></%output> 311 <%output></ul></%output>
311 } 312 }
312 } 313 }
313 } 314 }
314 </%code> 315 </%code>
315 <div class="what"> 316 <div class="what">
316 <% sitecing::html_escape(message,sitecing::html_escape_br) %> 317 <% sitecing::html_escape(message,sitecing::html_escape_br) %>
317 </div> 318 </div>
318 </div> 319 </div>
319</%method> 320</%method>
320<%codemethod string strip_roots(const string& filename) %> 321<%codemethod string strip_roots(const string& filename) %>
321 string np = sitecing::normalize_path(filename); 322 string np = konforka::normalize_path(filename);
322 try{ 323 try{
323 return sitecing::strip_prefix(np,root_source); 324 return sitecing::strip_prefix(np,root_source);
324 }catch(sitecing::utility_no_prefix& e){ } 325 }catch(sitecing::utility_no_prefix& e){ }
325 try{ 326 try{
326 return sitecing::strip_prefix(np,root_intermediate); 327 return sitecing::strip_prefix(np,root_intermediate);
327 }catch(sitecing::utility_no_prefix& e){ } 328 }catch(sitecing::utility_no_prefix& e){ }
328</%codemethod> 329</%codemethod>
329<%codemethod string remove_roots(const string& str) %> 330<%codemethod string remove_roots(const string& str) %>
330 string rv = str; 331 string rv = str;
331 string::size_type rp; 332 string::size_type rp;
332 string::size_type rl = root_source.length(); 333 string::size_type rl = root_source.length();
333 while((rp=rv.find(root_source))!=string::npos) { 334 while((rp=rv.find(root_source))!=string::npos) {
334 rv.erase(rp,rl); 335 rv.erase(rp,rl);
335 } 336 }
336 rl = root_intermediate.length(); 337 rl = root_intermediate.length();
337 while((rp=rv.find(root_intermediate))!=string::npos) { 338 while((rp=rv.find(root_intermediate))!=string::npos) {
338 rv.erase(rp,rl); 339 rv.erase(rp,rl);
339 } 340 }
340 rl = root_so.length(); 341 rl = root_so.length();
341 while((rp=rv.find(root_so))!=string::npos) { 342 while((rp=rv.find(root_so))!=string::npos) {
342 rv.erase(rp,rl); 343 rv.erase(rp,rl);
343 } 344 }
344 return rv; 345 return rv;
345</%codemethod> 346</%codemethod>
346% /* vim:set ft=sitecing: */ 347% /* vim:set ft=sitecing: */
diff --git a/configure.ac b/configure.ac
index a8aa142..fde326b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,89 +1,93 @@
1AC_INIT([sitecing], [0.0.1], [sitecing-bugs@klever.net]) 1AC_INIT([sitecing], [0.0.1], [sitecing-bugs@klever.net])
2AC_CONFIG_SRCDIR([include/sitecing/sitecing_parser.h]) 2AC_CONFIG_SRCDIR([include/sitecing/sitecing_parser.h])
3AC_CONFIG_HEADER([config.h]) 3AC_CONFIG_HEADER([config.h])
4AM_INIT_AUTOMAKE([dist-bzip2]) 4AM_INIT_AUTOMAKE([dist-bzip2])
5 5
6AC_PROG_INSTALL 6AC_PROG_INSTALL
7AC_PROG_AWK 7AC_PROG_AWK
8AC_PROG_CXX 8AC_PROG_CXX
9AC_PROG_CC 9AC_PROG_CC
10AM_PROG_LEX 10AM_PROG_LEX
11AC_PROG_LIBTOOL 11AC_PROG_LIBTOOL
12 12
13AC_HEADER_STDC 13AC_HEADER_STDC
14AC_CHECK_HEADERS([stdlib.h unistd.h]) 14AC_CHECK_HEADERS([stdlib.h unistd.h])
15 15
16AC_C_CONST 16AC_C_CONST
17 17
18AC_FUNC_MALLOC 18AC_FUNC_MALLOC
19AC_FUNC_REALLOC 19AC_FUNC_REALLOC
20 20
21AC_WITH_PKGCONFIG 21AC_WITH_PKGCONFIG
22 22
23PKG_CHECK_MODULES([KONFORKA],[konforka >= 0.0.1],,[
24 AC_MSG_ERROR([no proper version of konforka library found, get it at http://kin.klever.net/konforka/])
25])
26
23PKG_CHECK_MODULES([KINGATE],[kingate >= 0.0.1],,[ 27PKG_CHECK_MODULES([KINGATE],[kingate >= 0.0.1],,[
24 AC_MSG_ERROR([no kingate library found, get it at http://kin.klever.net/kingate/]) 28 AC_MSG_ERROR([no kingate library found, get it at http://kin.klever.net/kingate/])
25]) 29])
26HAVE_FCGI=false 30HAVE_FCGI=false
27HAVE_PLAINCGI=false 31HAVE_PLAINCGI=false
28PKG_CHECK_MODULES([KINGATE_FCGI],[kingate-fcgi >= 0.0.1],[ 32PKG_CHECK_MODULES([KINGATE_FCGI],[kingate-fcgi >= 0.0.1],[
29 HAVE_FCGI=true 33 HAVE_FCGI=true
30],[ 34],[
31 AC_MSG_NOTICE([no fastcgi support in kingate library]) 35 AC_MSG_NOTICE([no fastcgi support in kingate library])
32]) 36])
33PKG_CHECK_MODULES([KINGATE_PLAINCGI],[kingate-plaincgi >= 0.0.1],[ 37PKG_CHECK_MODULES([KINGATE_PLAINCGI],[kingate-plaincgi >= 0.0.1],[
34 HAVE_PLAINCGI=true 38 HAVE_PLAINCGI=true
35],[ 39],[
36 AC_MSG_NOTICE([no plaincgi support in kingate library]) 40 AC_MSG_NOTICE([no plaincgi support in kingate library])
37]) 41])
38if ! (${HAVE_FCGI} || ${HAVE_PLAINCGI}) ; then 42if ! (${HAVE_FCGI} || ${HAVE_PLAINCGI}) ; then
39 AC_MSG_ERROR([not a single CGI interface supported in kingate]) 43 AC_MSG_ERROR([not a single CGI interface supported in kingate])
40fi 44fi
41AM_CONDITIONAL([HAVE_FCGI],[${HAVE_FCGI}]) 45AM_CONDITIONAL([HAVE_FCGI],[${HAVE_FCGI}])
42AM_CONDITIONAL([HAVE_PLAINCGI],[${HAVE_PLAINCGI}]) 46AM_CONDITIONAL([HAVE_PLAINCGI],[${HAVE_PLAINCGI}])
43 47
44PKG_CHECK_MODULES([DOTCONF],[dotconf],,[ 48PKG_CHECK_MODULES([DOTCONF],[dotconf],,[
45 AC_MSG_ERROR([no dotconf library found]) 49 AC_MSG_ERROR([no dotconf library found])
46]) 50])
47 51
48AC_WITH_PCRE([ 52AC_WITH_PCRE([
49 AC_WITH_PCREPP(,[ 53 AC_WITH_PCREPP(,[
50 AC_MSG_ERROR([no pcre++ library found]) 54 AC_MSG_ERROR([no pcre++ library found])
51 ]) 55 ])
52],[ 56],[
53 AC_MSG_ERROR([no pcre library found]) 57 AC_MSG_ERROR([no pcre library found])
54]) 58])
55 59
56AC_CHECK_FUNC([dlopen],,[ 60AC_CHECK_FUNC([dlopen],,[
57 AC_CHECK_LIB([dl],[dlopen],,[ 61 AC_CHECK_LIB([dl],[dlopen],,[
58 AC_MSG_ERROR([no dlopen library found]) 62 AC_MSG_ERROR([no dlopen library found])
59 ]) 63 ])
60]) 64])
61 65
62AC_PATH_PROG([XSLTPROC],[xsltproc],[true]) 66AC_PATH_PROG([XSLTPROC],[xsltproc],[true])
63 67
64WANT_DOXYGEN="yes" 68WANT_DOXYGEN="yes"
65AC_ARG_ENABLE([doxygen], 69AC_ARG_ENABLE([doxygen],
66 AC_HELP_STRING([--disable-doxygen],[do not generate documentation]), 70 AC_HELP_STRING([--disable-doxygen],[do not generate documentation]),
67 [ 71 [
68 test "${enableval}" = "no" && WANT_DOXYGEN="no" 72 test "${enableval}" = "no" && WANT_DOXYGEN="no"
69 ] 73 ]
70) 74)
71if test "${WANT_DOXYGEN}" = "yes" ; then 75if test "${WANT_DOXYGEN}" = "yes" ; then
72 AC_WITH_DOXYGEN 76 AC_WITH_DOXYGEN
73 AC_WITH_DOT 77 AC_WITH_DOT
74else 78else
75 AM_CONDITIONAL([HAVE_DOXYGEN],[false]) 79 AM_CONDITIONAL([HAVE_DOXYGEN],[false])
76 AM_CONDITIONAL([HAVE_DOT],[false]) 80 AM_CONDITIONAL([HAVE_DOT],[false])
77fi 81fi
78 82
79AC_CONFIG_FILES([ 83AC_CONFIG_FILES([
80 Makefile 84 Makefile
81 Doxyfile 85 Doxyfile
82 sitecing.pc 86 sitecing.pc
83 include/Makefile 87 include/Makefile
84 lib/Makefile 88 lib/Makefile
85 share/Makefile 89 share/Makefile
86 src/Makefile 90 src/Makefile
87 components/Makefile 91 components/Makefile
88]) 92])
89AC_OUTPUT 93AC_OUTPUT
diff --git a/include/sitecing/sitecing_util.h b/include/sitecing/sitecing_util.h
index d1a6c4a..f642c74 100644
--- a/include/sitecing/sitecing_util.h
+++ b/include/sitecing/sitecing_util.h
@@ -1,341 +1,260 @@
1#ifndef __SITECING_SITECING_UTIL_H 1#ifndef __SITECING_SITECING_UTIL_H
2#define __SITECING_SITECING_UTIL_H 2#define __SITECING_SITECING_UTIL_H
3 3
4#include <sys/types.h> 4#include <sys/types.h>
5#include <string> 5#include <string>
6#include <konforka/exception.h> 6#include <konforka/exception.h>
7#include <konforka/util.h>
7 8
8/** 9/**
9 * @file 10 * @file
10 * @brief utility classes and functions. 11 * @brief utility classes and functions.
11 */ 12 */
12 13
13namespace sitecing { 14namespace sitecing {
14 using namespace std; 15 using namespace std;
15 16
16 /** 17 /**
17 * Base class for utility exceptions. 18 * Base class for utility exceptions.
18 */ 19 */
19 class utility_error : public konforka::exception { 20 class utility_error : public konforka::exception {
20 public: 21 public:
21 utility_error(const string& fi,const string& fu,int l,const string& w) 22 utility_error(const string& fi,const string& fu,int l,const string& w)
22 : konforka::exception(fi,fu,l,w) { } 23 : konforka::exception(fi,fu,l,w) { }
23 }; 24 };
24 /** 25
25 * Restricted sequence encountered.
26 */
27 class utility_restricted_sequence : public utility_error {
28 public:
29 utility_restricted_sequence(const string& fi,const string& fu,int l,const string& w)
30 : utility_error(fi,fu,l,w) { }
31 };
32 /** 26 /**
33 * No prefix or suffix found to strip out. 27 * No prefix or suffix found to strip out.
34 */ 28 */
35 class utility_no_affix : public utility_error { 29 class utility_no_affix : public utility_error {
36 public: 30 public:
37 utility_no_affix(const string& fi,const string& fu,int l,const string& w) 31 utility_no_affix(const string& fi,const string& fu,int l,const string& w)
38 : utility_error(fi,fu,l,w) { } 32 : utility_error(fi,fu,l,w) { }
39 }; 33 };
40 /** 34 /**
41 * No prefix to strip found. 35 * No prefix to strip found.
42 */ 36 */
43 class utility_no_prefix : public utility_no_affix { 37 class utility_no_prefix : public utility_no_affix {
44 public: 38 public:
45 utility_no_prefix(const string& fi,const string& fu,int l,const string& w) 39 utility_no_prefix(const string& fi,const string& fu,int l,const string& w)
46 : utility_no_affix(fi,fu,l,w) { } 40 : utility_no_affix(fi,fu,l,w) { }
47 }; 41 };
48 /** 42 /**
49 * No suffix to strip found. 43 * No suffix to strip found.
50 */ 44 */
51 class utility_no_suffix : public utility_no_affix { 45 class utility_no_suffix : public utility_no_affix {
52 public: 46 public:
53 utility_no_suffix(const string& fi,const string& fu,int l,const string& w) 47 utility_no_suffix(const string& fi,const string& fu,int l,const string& w)
54 : utility_no_affix(fi,fu,l,w) { } 48 : utility_no_affix(fi,fu,l,w) { }
55 }; 49 };
56 50
57 /** 51 /**
58 * Went up beyond root.
59 * @todo TODO: wish I could remember the details -- document me.
60 */
61 class utility_beyond_root : public utility_error {
62 public:
63 utility_beyond_root(const string& fi,const string& fu,int l,const string& w)
64 : utility_error(fi,fu,l,w) { }
65 };
66
67 /**
68 * The file lock object. Released at the object destruction. 52 * The file lock object. Released at the object destruction.
69 */ 53 */
70 class file_lock { 54 class file_lock {
71 public: 55 public:
72 /** 56 /**
73 * The file descriptor. 57 * The file descriptor.
74 */ 58 */
75 int fd; 59 int fd;
76 60
77 file_lock() 61 file_lock()
78 : fd(-1) { } 62 : fd(-1) { }
79 /** 63 /**
80 * @param f file name. 64 * @param f file name.
81 */ 65 */
82 file_lock(const string& f) 66 file_lock(const string& f)
83 : fd(-1) { lock(f); } 67 : fd(-1) { lock(f); }
84 ~file_lock() { unlock(); } 68 ~file_lock() { unlock(); }
85 69
86 /** 70 /**
87 * Do lock. 71 * Do lock.
88 * @param f file name. 72 * @param f file name.
89 */ 73 */
90 void lock(const string& f); 74 void lock(const string& f);
91 /** 75 /**
92 * @todo TODO: wish I could remember the details -- document me. 76 * @todo TODO: wish I could remember the details -- document me.
93 */ 77 */
94 void lock(); 78 void lock();
95 /** 79 /**
96 * Release the lock obtained. 80 * Release the lock obtained.
97 */ 81 */
98 void unlock(); 82 void unlock();
99 }; 83 };
100 84
101 /** 85 /**
102 * The pid file. Removed at object destruction. 86 * The pid file. Removed at object destruction.
103 */ 87 */
104 class pid_file { 88 class pid_file {
105 public: 89 public:
106 /** 90 /**
107 * The file name. 91 * The file name.
108 */ 92 */
109 string file_name; 93 string file_name;
110 /** 94 /**
111 * Do we unlink the file after we're done? 95 * Do we unlink the file after we're done?
112 */ 96 */
113 bool unlink_pid; 97 bool unlink_pid;
114 98
115 pid_file() 99 pid_file()
116 : unlink_pid(false) { } 100 : unlink_pid(false) { }
117 ~pid_file() { unlink(); } 101 ~pid_file() { unlink(); }
118 102
119 /** 103 /**
120 * @param f file name. 104 * @param f file name.
121 * @param u whether we want to unlink the file. 105 * @param u whether we want to unlink the file.
122 */ 106 */
123 void set(const string& f,bool u=true); 107 void set(const string& f,bool u=true);
124 /** 108 /**
125 * Unlink the file if we wanted to in the first place. 109 * Unlink the file if we wanted to in the first place.
126 */ 110 */
127 void unlink(); 111 void unlink();
128 }; 112 };
129 113
130 /** 114 /**
131 * The semaphore object. 115 * The semaphore object.
132 */ 116 */
133 class semaphore { 117 class semaphore {
134 public: 118 public:
135 /** 119 /**
136 * The semaphore id. 120 * The semaphore id.
137 */ 121 */
138 int semid; 122 int semid;
139 123
140 semaphore() 124 semaphore()
141 : semid(-1) { } 125 : semid(-1) { }
142 /** 126 /**
143 * @param sid semaphore id. 127 * @param sid semaphore id.
144 */ 128 */
145 semaphore(int sid) 129 semaphore(int sid)
146 : semid(sid) { } 130 : semid(sid) { }
147 ~semaphore() { 131 ~semaphore() {
148 deinit(); 132 deinit();
149 } 133 }
150 134
151 /** 135 /**
152 * Init semaphore. 136 * Init semaphore.
153 */ 137 */
154 void init(); 138 void init();
155 /** 139 /**
156 * Undo the init. 140 * Undo the init.
157 */ 141 */
158 void deinit(); 142 void deinit();
159 143
160 /** 144 /**
161 * Semaphore on. 145 * Semaphore on.
162 */ 146 */
163 void on(); 147 void on();
164 /** 148 /**
165 * Semaphore off. 149 * Semaphore off.
166 */ 150 */
167 void off(); 151 void off();
168 }; 152 };
169 153
170 /** 154 /**
171 * The semaphor lock object, released at object destruction. 155 * The semaphor lock object, released at object destruction.
172 */ 156 */
173 class semaphore_lock { 157 class semaphore_lock {
174 public: 158 public:
175 /** 159 /**
176 * Pointer to the semaphore we're operating on. 160 * Pointer to the semaphore we're operating on.
177 */ 161 */
178 semaphore* sem; 162 semaphore* sem;
179 /** 163 /**
180 * Whether it is locked. 164 * Whether it is locked.
181 */ 165 */
182 bool locked; 166 bool locked;
183 167
184 semaphore_lock() 168 semaphore_lock()
185 : sem(NULL), locked(false) {} 169 : sem(NULL), locked(false) {}
186 /** 170 /**
187 * @param s pointer to the semaphore. 171 * @param s pointer to the semaphore.
188 * @param l lock at creation? 172 * @param l lock at creation?
189 */ 173 */
190 semaphore_lock(semaphore* s,bool l=true) 174 semaphore_lock(semaphore* s,bool l=true)
191 : sem(s), locked(false) { 175 : sem(s), locked(false) {
192 if(l) lock(); 176 if(l) lock();
193 } 177 }
194 /** 178 /**
195 * @param s reference to the semaphore. 179 * @param s reference to the semaphore.
196 * @param l lock at creation? 180 * @param l lock at creation?
197 */ 181 */
198 semaphore_lock(semaphore& s,bool l=true) 182 semaphore_lock(semaphore& s,bool l=true)
199 : sem(&s), locked(false) { 183 : sem(&s), locked(false) {
200 if(l) lock(); 184 if(l) lock();
201 } 185 }
202 186
203 ~semaphore_lock() { 187 ~semaphore_lock() {
204 unlock(); 188 unlock();
205 } 189 }
206 190
207 /** 191 /**
208 * Lock it. 192 * Lock it.
209 */ 193 */
210 void lock(); 194 void lock();
211 /** 195 /**
212 * Unlock it. 196 * Unlock it.
213 */ 197 */
214 void unlock(); 198 void unlock();
215 }; 199 };
216 200
217 /** 201 /**
218 * normalize_path options enumeration.
219 * @see normalize_path()
220 */
221 enum normalize_path_options {
222 /**
223 * Restrict the /../ sequence.
224 */
225 restrict_dotdot = 1,
226 /**
227 * Strip out the leading slash.
228 */
229 strip_leading_slash = 2,
230 /**
231 * Strip out the trailing slash.
232 */
233 strip_trailing_slash = 4
234 };
235 /**
236 * combine_path options enumeration.
237 * @see combine_path()
238 */
239 enum combine_path_options {
240 /**
241 * The origin is file. Otherwise it is directory.
242 */
243 origin_is_file = 1,
244 /**
245 * Fail if we've gone up beyond root.
246 */
247 fail_beyond_root = 2
248 };
249
250 /**
251 * Normalize pathname by stripping duplicate slashes, etc.
252 * @param path the path name.
253 * @param opts options.
254 * @return the normalized path.
255 * @see normalize_path_options
256 * @todo TODO: document exceptions.
257 */
258 string normalize_path(const string& path,int opts=(restrict_dotdot|strip_trailing_slash));
259 /**
260 * Strip prefix from the string. 202 * Strip prefix from the string.
261 * @param str the string. 203 * @param str the string.
262 * @param prefix prefix to strip. 204 * @param prefix prefix to strip.
263 * @return the string without prefix. 205 * @return the string without prefix.
264 * @todo TODO: document exceptions. 206 * @todo TODO: document exceptions.
265 */ 207 */
266 string strip_prefix(const string& str,const string& prefix); 208 string strip_prefix(const string& str,const string& prefix);
267 /** 209 /**
268 * Strip suffix from the string. 210 * Strip suffix from the string.
269 * @param str the string. 211 * @param str the string.
270 * @param suffix suffix to strip. 212 * @param suffix suffix to strip.
271 * @return the string without suffix. 213 * @return the string without suffix.
272 * @todo TODO: document exceptions. 214 * @todo TODO: document exceptions.
273 */ 215 */
274 string strip_suffix(const string& str,const string& suffix); 216 string strip_suffix(const string& str,const string& suffix);
275 /** 217
276 * Get the directory part of the filename.
277 * @param filename the full file name.
278 * @return the directory part.
279 */
280 string dir_name(const string& filename);
281 /**
282 * Combine path with the relative path.
283 * @param origin the origin.
284 * @param relative relative path to combine origin with.
285 * @param opts options.
286 * @return the pathc combined.
287 * @see combine_path_options
288 * @todo TODO: document exceptions.
289 */
290 string combine_path(const string& origin,const string& relative,int opts=origin_is_file);
291
292 /**
293 * Create directory and parent directories if needed.
294 * @param path the pathname.
295 * @param mode the mode for newly created directories.
296 */
297 void make_path(const string& path,mode_t mode);
298
299 /** 218 /**
300 * Change to the directory and pop back at object's destruction (e.g. when 219 * Change to the directory and pop back at object's destruction (e.g. when
301 * the object goes out of scope). 220 * the object goes out of scope).
302 */ 221 */
303 class auto_chdir { 222 class auto_chdir {
304 public: 223 public:
305 /** 224 /**
306 * Saved working directory. 225 * Saved working directory.
307 */ 226 */
308 string saved_pwd; 227 string saved_pwd;
309 /** 228 /**
310 * Whether we want to change back automatically. 229 * Whether we want to change back automatically.
311 */ 230 */
312 bool autopop; 231 bool autopop;
313 232
314 auto_chdir() 233 auto_chdir()
315 : autopop(false) { } 234 : autopop(false) { }
316 /** 235 /**
317 * @param td destination path. 236 * @param td destination path.
318 * @param ap automatically come back? 237 * @param ap automatically come back?
319 */ 238 */
320 auto_chdir(const string& td,bool ap=true) 239 auto_chdir(const string& td,bool ap=true)
321 : autopop(false) { pushdir(td,ap); } 240 : autopop(false) { pushdir(td,ap); }
322 ~auto_chdir() { 241 ~auto_chdir() {
323 if(autopop) 242 if(autopop)
324 popdir(); 243 popdir();
325 } 244 }
326 245
327 /** 246 /**
328 * Change into directory. 247 * Change into directory.
329 * @param td the directory. 248 * @param td the directory.
330 * @param ap automaticall pop back? 249 * @param ap automaticall pop back?
331 */ 250 */
332 void pushdir(const string& td,bool ap=true); 251 void pushdir(const string& td,bool ap=true);
333 /** 252 /**
334 * Change to the saved directory. 253 * Change to the saved directory.
335 */ 254 */
336 void popdir(); 255 void popdir();
337 }; 256 };
338 257
339} 258}
340 259
341#endif /* __SITECING_SITECING_UTIL_H */ 260#endif /* __SITECING_SITECING_UTIL_H */
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}
diff --git a/src/sitecing-build.cc b/src/sitecing-build.cc
index 4cad0a3..887ef83 100644
--- a/src/sitecing-build.cc
+++ b/src/sitecing-build.cc
@@ -1,231 +1,232 @@
1#include <sys/types.h> 1#include <sys/types.h>
2#include <dirent.h> 2#include <dirent.h>
3#include <getopt.h> 3#include <getopt.h>
4#include <iostream> 4#include <iostream>
5#include <memory> 5#include <memory>
6#include <fstream> 6#include <fstream>
7#include <cassert> 7#include <cassert>
8#include <set> 8#include <set>
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/util.h" 12#include "sitecing/util.h"
12#include "sitecing/sitespace.h" 13#include "sitecing/sitespace.h"
13#include "sitecing/sitecing_interface_cgi.h" 14#include "sitecing/sitecing_interface_cgi.h"
14#include "sitecing/cgi_component.h" 15#include "sitecing/cgi_component.h"
15#include "sitecing/configuration.h" 16#include "sitecing/configuration.h"
16#include "sitecing/magic.h" 17#include "sitecing/magic.h"
17#include "sitecing/sitecing_exception.h" 18#include "sitecing/sitecing_exception.h"
18#include "sitecing/exception.h" 19#include "sitecing/exception.h"
19using namespace sitecing; 20using namespace sitecing;
20 21
21#include "config.h" 22#include "config.h"
22#define PHEADER PACKAGE "-build Version " VERSION 23#define PHEADER PACKAGE "-build Version " VERSION
23#define PCOPY "Copyright (c) 2004 Klever Group" 24#define PCOPY "Copyright (c) 2004 Klever Group"
24 25
25static sitespace* site_space = NULL; 26static sitespace* site_space = NULL;
26typedef pair<dev_t,ino_t> the_inode_t; 27typedef pair<dev_t,ino_t> the_inode_t;
27set<the_inode_t> built_inodes; 28set<the_inode_t> built_inodes;
28 29
29void build_component(const string& component) { 30void build_component(const string& component) {
30 assert(site_space); 31 assert(site_space);
31 cerr << "Building " << component << endl; 32 cerr << "Building " << component << endl;
32 try { 33 try {
33 site_space->factory.make(site_space->config.root_so+component+".so"); 34 site_space->factory.make(site_space->config.root_so+component+".so");
34 }catch(compile_error& ce) { 35 }catch(compile_error& ce) {
35 ce.see(CODEPOINT); 36 ce.see(CODEPOINT);
36 ifstream err((site_space->config.root_intermediate+ce.component_path+".stderr").c_str(),ios::in); 37 ifstream err((site_space->config.root_intermediate+ce.component_path+".stderr").c_str(),ios::in);
37 if(err) { 38 if(err) {
38 cerr << err.rdbuf(); 39 cerr << err.rdbuf();
39 } 40 }
40 throw; 41 throw;
41 }catch(preprocessor_error& pe) { 42 }catch(preprocessor_error& pe) {
42 pe.see(CODEPOINT); 43 pe.see(CODEPOINT);
43 cerr << site_space->config.root_source << pe.component_name << ":" << pe.line_number << ":" << pe.what() << endl; 44 cerr << site_space->config.root_source << pe.component_name << ":" << pe.line_number << ":" << pe.what() << endl;
44 throw; 45 throw;
45 } 46 }
46} 47}
47 48
48void build_imports(const string& component); 49void build_imports(const string& component);
49 50
50void build_with_imports(const string& component) { 51void build_with_imports(const string& component) {
51 assert(site_space); 52 assert(site_space);
52 struct stat st; 53 struct stat st;
53 string cp = site_space->config.root_source+component; 54 string cp = site_space->config.root_source+component;
54 if(!lstat(cp.c_str(),&st)) { 55 if(!lstat(cp.c_str(),&st)) {
55 if(built_inodes.find(the_inode_t(st.st_dev,st.st_ino))!=built_inodes.end()) 56 if(built_inodes.find(the_inode_t(st.st_dev,st.st_ino))!=built_inodes.end())
56 return; 57 return;
57 built_inodes.insert(the_inode_t(st.st_dev,st.st_ino)); 58 built_inodes.insert(the_inode_t(st.st_dev,st.st_ino));
58 } 59 }
59 build_component(component); 60 build_component(component);
60 build_imports(component); 61 build_imports(component);
61} 62}
62 63
63void build_imports(const string& component) { 64void build_imports(const string& component) {
64 assert(site_space); 65 assert(site_space);
65 ifstream ifs((site_space->config.root_intermediate+component+".imports").c_str(),ios::in); 66 ifstream ifs((site_space->config.root_intermediate+component+".imports").c_str(),ios::in);
66 cerr << "Building components imported by " << component << endl; 67 cerr << "Building components imported by " << component << endl;
67 if(ifs) { 68 if(ifs) {
68 string import; 69 string import;
69 while(!ifs.eof()) { 70 while(!ifs.eof()) {
70 ifs >> import; 71 ifs >> import;
71 if(!import.empty()) 72 if(!import.empty())
72 build_with_imports(import); 73 build_with_imports(import);
73 } 74 }
74 } 75 }
75} 76}
76 77
77void build_http_status_handlers(const string& target) { 78void build_http_status_handlers(const string& target) {
78 assert(site_space); 79 assert(site_space);
79 set<string> stop_list; 80 set<string> stop_list;
80 string t = "/"; 81 string t = "/";
81 t += normalize_path(target,strip_leading_slash); 82 t += konforka::normalize_path(target,konforka::strip_leading_slash);
82 for(;;) { 83 for(;;) {
83 if(t[t.length()-1]=='/') { 84 if(t[t.length()-1]=='/') {
84 loaded_options* lo = site_space->config.lookup_loaded_options(t); 85 loaded_options* lo = site_space->config.lookup_loaded_options(t);
85 if( lo && (lo->flags&config_options::flag_http_status_handlers) ) { 86 if( lo && (lo->flags&config_options::flag_http_status_handlers) ) {
86 for(config_options::http_status_handlers_t::const_iterator i=lo->http_status_handlers.begin();i!=lo->http_status_handlers.end();++i) { 87 for(config_options::http_status_handlers_t::const_iterator i=lo->http_status_handlers.begin();i!=lo->http_status_handlers.end();++i) {
87 if(stop_list.find(i->first)==stop_list.end()) { 88 if(stop_list.find(i->first)==stop_list.end()) {
88 build_with_imports(i->second); 89 build_with_imports(i->second);
89 stop_list.insert(i->first); 90 stop_list.insert(i->first);
90 } 91 }
91 } 92 }
92 } 93 }
93 } 94 }
94 configuration::specs_t::iterator i=site_space->config.specs.find(t); 95 configuration::specs_t::iterator i=site_space->config.specs.find(t);
95 if( i!=site_space->config.specs.end() && (i->second.flags&config_options::flag_http_status_handlers) ) { 96 if( i!=site_space->config.specs.end() && (i->second.flags&config_options::flag_http_status_handlers) ) {
96 for(config_options::http_status_handlers_t::const_iterator ii=i->second.http_status_handlers.begin();ii!=i->second.http_status_handlers.end();++i) { 97 for(config_options::http_status_handlers_t::const_iterator ii=i->second.http_status_handlers.begin();ii!=i->second.http_status_handlers.end();++i) {
97 if(stop_list.find(ii->first)==stop_list.end()) { 98 if(stop_list.find(ii->first)==stop_list.end()) {
98 build_with_imports(ii->second); 99 build_with_imports(ii->second);
99 stop_list.insert(ii->first); 100 stop_list.insert(ii->first);
100 } 101 }
101 } 102 }
102 } 103 }
103 if(t.empty()) 104 if(t.empty())
104 return; 105 return;
105 string::size_type sl=t.rfind('/'); 106 string::size_type sl=t.rfind('/');
106 if(sl==string::npos) { 107 if(sl==string::npos) {
107 t.erase(); 108 t.erase();
108 }else{ 109 }else{
109 if(sl==(t.length()-1)) 110 if(sl==(t.length()-1))
110 t.erase(sl); 111 t.erase(sl);
111 else 112 else
112 t.erase(sl+1); 113 t.erase(sl+1);
113 } 114 }
114 } 115 }
115} 116}
116 117
117void build_target(const string& target) { 118void build_target(const string& target) {
118 assert(site_space); 119 assert(site_space);
119 string action = target; 120 string action = target;
120 config_options::action_handler_t *ah = site_space->config.lookup_action_handler(target); 121 config_options::action_handler_t *ah = site_space->config.lookup_action_handler(target);
121 if(ah) 122 if(ah)
122 action = ah->action; 123 action = ah->action;
123 build_with_imports(action); 124 build_with_imports(action);
124} 125}
125 126
126void build(const string& target) { 127void build(const string& target) {
127 assert(site_space); 128 assert(site_space);
128 build_http_status_handlers(target); 129 build_http_status_handlers(target);
129 config_options *co_exception_handler = site_space->config.lookup_config(target,config_options::flag_exception_handler); 130 config_options *co_exception_handler = site_space->config.lookup_config(target,config_options::flag_exception_handler);
130 if(co_exception_handler) { 131 if(co_exception_handler) {
131 string handler = co_exception_handler->exception_handler; 132 string handler = co_exception_handler->exception_handler;
132 build_with_imports(handler); 133 build_with_imports(handler);
133 } 134 }
134 string target_source = site_space->config.root_source+target; 135 string target_source = site_space->config.root_source+target;
135 struct stat st; 136 struct stat st;
136 if(stat(target_source.c_str(),&st)) 137 if(stat(target_source.c_str(),&st))
137 throw konforka::exception(CODEPOINT,"failed to stat() target"); 138 throw konforka::exception(CODEPOINT,"failed to stat() target");
138 if(S_ISREG(st.st_mode)) { 139 if(S_ISREG(st.st_mode)) {
139 build_target(target); 140 build_target(target);
140 }else if(S_ISDIR(st.st_mode)) { 141 }else if(S_ISDIR(st.st_mode)) {
141 build_http_status_handlers(target); 142 build_http_status_handlers(target);
142 DIR *d=opendir(target_source.c_str()); 143 DIR *d=opendir(target_source.c_str());
143 if(!d) 144 if(!d)
144 throw konforka::exception(CODEPOINT,"failed to opendir()"); 145 throw konforka::exception(CODEPOINT,"failed to opendir()");
145 for(struct dirent *de=readdir(d);de;de=readdir(d)) { 146 for(struct dirent *de=readdir(d);de;de=readdir(d)) {
146 if(!strcmp(de->d_name,".")) 147 if(!strcmp(de->d_name,"."))
147 continue; 148 continue;
148 if(!strcmp(de->d_name,"..")) 149 if(!strcmp(de->d_name,".."))
149 continue; 150 continue;
150 string subtarget = normalize_path(target+"/"+de->d_name); 151 string subtarget = konforka::normalize_path(target+"/"+de->d_name);
151 struct stat sts; 152 struct stat sts;
152 if(stat((site_space->config.root_source+subtarget).c_str(),&sts)) 153 if(stat((site_space->config.root_source+subtarget).c_str(),&sts))
153 throw konforka::exception(CODEPOINT,"failed to stat() subtarget"); 154 throw konforka::exception(CODEPOINT,"failed to stat() subtarget");
154 if(S_ISDIR(sts.st_mode)) { 155 if(S_ISDIR(sts.st_mode)) {
155 build(subtarget); 156 build(subtarget);
156 }else{ 157 }else{
157 if(site_space->config.match_autobuild_files(target,de->d_name)){ 158 if(site_space->config.match_autobuild_files(target,de->d_name)){
158 build_target(subtarget); 159 build_target(subtarget);
159 } 160 }
160 } 161 }
161 } 162 }
162 closedir(d); 163 closedir(d);
163 } 164 }
164} 165}
165 166
166int main(int argc,char **argv) { 167int main(int argc,char **argv) {
167 try { 168 try {
168 string config_file = "sitecing.conf"; 169 string config_file = "sitecing.conf";
169 while(true) { 170 while(true) {
170 static struct option opts[] = { 171 static struct option opts[] = {
171 { "help", no_argument, 0, 'h' }, 172 { "help", no_argument, 0, 'h' },
172 { "usage", no_argument, 0, 'h' }, 173 { "usage", no_argument, 0, 'h' },
173 { "version", no_argument, 0, 'V' }, 174 { "version", no_argument, 0, 'V' },
174 { "license", no_argument, 0, 'L' }, 175 { "license", no_argument, 0, 'L' },
175 { "config", required_argument, 0, 'f' }, 176 { "config", required_argument, 0, 'f' },
176 { NULL, 0, 0, 0 } 177 { NULL, 0, 0, 0 }
177 }; 178 };
178 int c = getopt_long(argc,argv,"f:hVL",opts,NULL); 179 int c = getopt_long(argc,argv,"f:hVL",opts,NULL);
179 if(c==-1) 180 if(c==-1)
180 break; 181 break;
181 switch(c) { 182 switch(c) {
182 case 'h': 183 case 'h':
183 cerr << PHEADER << endl 184 cerr << PHEADER << endl
184 << PCOPY << endl << endl 185 << PCOPY << endl << endl
185 << " -h, --help" << endl 186 << " -h, --help" << endl
186 << " --usage display this text" << endl 187 << " --usage display this text" << endl
187 << " -V, --version display version number" << endl 188 << " -V, --version display version number" << endl
188 << " -L, --license show license" << endl 189 << " -L, --license show license" << endl
189 << " -f filename, --config=filename" << endl 190 << " -f filename, --config=filename" << endl
190 << " specify configuration file to use" << endl; 191 << " specify configuration file to use" << endl;
191 exit(0); 192 exit(0);
192 break; 193 break;
193 case 'V': 194 case 'V':
194 cerr << VERSION << endl; 195 cerr << VERSION << endl;
195 exit(0); 196 exit(0);
196 break; 197 break;
197 case 'L': 198 case 'L':
198 extern const char *COPYING; 199 extern const char *COPYING;
199 cerr << COPYING << endl; 200 cerr << COPYING << endl;
200 exit(0); 201 exit(0);
201 break; 202 break;
202 case 'f': 203 case 'f':
203 config_file = optarg; 204 config_file = optarg;
204 break; 205 break;
205 default: 206 default:
206 cerr << "Huh??" << endl; 207 cerr << "Huh??" << endl;
207 break; 208 break;
208 } 209 }
209 } 210 }
210 configuration config(config_file,true); 211 configuration config(config_file,true);
211 if(!(config.flags&configuration::flag_root_source)) 212 if(!(config.flags&configuration::flag_root_source))
212 throw konforka::exception(CODEPOINT,"Unspecified root for sources"); 213 throw konforka::exception(CODEPOINT,"Unspecified root for sources");
213 if(!(config.flags&configuration::flag_root_intermediate)) 214 if(!(config.flags&configuration::flag_root_intermediate))
214 throw konforka::exception(CODEPOINT,"Unspecified root for intermediate files"); 215 throw konforka::exception(CODEPOINT,"Unspecified root for intermediate files");
215 if(!(config.flags&configuration::flag_root_so)) 216 if(!(config.flags&configuration::flag_root_so))
216 throw konforka::exception(CODEPOINT,"Unspecified root for shared objects"); 217 throw konforka::exception(CODEPOINT,"Unspecified root for shared objects");
217 sitespace ss(config); 218 sitespace ss(config);
218 site_space = &ss; 219 site_space = &ss;
219 if(optind<argc) { 220 if(optind<argc) {
220 for(int narg=optind;narg<argc;narg++) { 221 for(int narg=optind;narg<argc;narg++) {
221 const char *arg = argv[narg]; 222 const char *arg = argv[narg];
222 build(arg); 223 build(arg);
223 } 224 }
224 }else 225 }else
225 build("/"); 226 build("/");
226 return 0; 227 return 0;
227 }catch(exception& e) { 228 }catch(exception& e) {
228 cerr << "Oops: " << e.what() << endl; 229 cerr << "Oops: " << e.what() << endl;
229 return 1; 230 return 1;
230 } 231 }
231} 232}
diff --git a/src/sitecing-fastcgi.cc b/src/sitecing-fastcgi.cc
index 756dcee..03587aa 100644
--- a/src/sitecing-fastcgi.cc
+++ b/src/sitecing-fastcgi.cc
@@ -1,328 +1,328 @@
1#include <sys/types.h> 1#include <sys/types.h>
2#include <unistd.h> 2#include <unistd.h>
3#include <signal.h> 3#include <signal.h>
4#include <getopt.h> 4#include <getopt.h>
5#include <pwd.h> 5#include <pwd.h>
6#include <grp.h> 6#include <grp.h>
7#include <errno.h> 7#include <errno.h>
8#include <syslog.h> 8#include <syslog.h>
9#include <iostream> 9#include <iostream>
10#include <memory> 10#include <memory>
11#include <typeinfo> 11#include <typeinfo>
12using namespace std; 12using namespace std;
13#include "kingate/fastcgi.h" 13#include "kingate/fastcgi.h"
14#include "kingate/cgi_gateway.h" 14#include "kingate/cgi_gateway.h"
15using namespace kingate; 15using namespace kingate;
16#include "sitecing/sitecing_util.h" 16#include "sitecing/sitecing_util.h"
17#include "sitecing/util.h" 17#include "sitecing/util.h"
18#include "sitecing/sitespace.h" 18#include "sitecing/sitespace.h"
19#include "sitecing/sitecing_interface_cgi.h" 19#include "sitecing/sitecing_interface_cgi.h"
20#include "sitecing/cgi_component.h" 20#include "sitecing/cgi_component.h"
21#include "sitecing/configuration.h" 21#include "sitecing/configuration.h"
22#include "sitecing/magic.h" 22#include "sitecing/magic.h"
23#include "sitecing/sitecing_exception.h" 23#include "sitecing/sitecing_exception.h"
24#include "sitecing/exception.h" 24#include "sitecing/exception.h"
25#include "sitecing/process_manager.h" 25#include "sitecing/process_manager.h"
26using namespace sitecing; 26using namespace sitecing;
27 27
28#include "config.h" 28#include "config.h"
29#define PHEADER PACKAGE " Version " VERSION 29#define PHEADER PACKAGE " Version " VERSION
30#define PCOPY "Copyright (c) 2004 Klever Group" 30#define PCOPY "Copyright (c) 2004 Klever Group"
31 31
32class cdummyClass : public acomponent { 32class cdummyClass : public acomponent {
33 public: 33 public:
34 void main(int _magic,va_list _args) {} 34 void main(int _magic,va_list _args) {}
35 void *__the_most_derived_this() { return NULL; } 35 void *__the_most_derived_this() { return NULL; }
36} cdummyInstance; 36} cdummyInstance;
37class adummyClass : public cgi_component { 37class adummyClass : public cgi_component {
38 public: 38 public:
39 void main(int _magic,va_list _args) {} 39 void main(int _magic,va_list _args) {}
40 void *__the_most_derived_this() { return NULL; } 40 void *__the_most_derived_this() { return NULL; }
41} adummyInstance; 41} adummyInstance;
42 42
43class sitecing_fastcgi_pm : public process_manager { 43class sitecing_fastcgi_pm : public process_manager {
44 public: 44 public:
45 configuration config; 45 configuration config;
46 fcgi_socket *fss; 46 fcgi_socket *fss;
47 semaphore sem; 47 semaphore sem;
48 bool multi; 48 bool multi;
49 uid_t uid; 49 uid_t uid;
50 gid_t gid; 50 gid_t gid;
51 pid_file pidfile; 51 pid_file pidfile;
52 52
53 sitecing_fastcgi_pm(const string& config_file); 53 sitecing_fastcgi_pm(const string& config_file);
54 ~sitecing_fastcgi_pm(); 54 ~sitecing_fastcgi_pm();
55 55
56 void process(int slot); 56 void process(int slot);
57 57
58 void run(); 58 void run();
59 void give_up_privs(); 59 void give_up_privs();
60}; 60};
61 61
62sitecing_fastcgi_pm::sitecing_fastcgi_pm(const string& config_file) 62sitecing_fastcgi_pm::sitecing_fastcgi_pm(const string& config_file)
63 : config(config_file), multi(false) { 63 : config(config_file), multi(false) {
64 if(( (config.flags&configuration::flag_user) || (config.flags&configuration::flag_group) || (config.flags&configuration::flag_chroot) ) && geteuid() ) 64 if(( (config.flags&configuration::flag_user) || (config.flags&configuration::flag_group) || (config.flags&configuration::flag_chroot) ) && geteuid() )
65 throw konforka::exception(CODEPOINT,"can't use User, Group or Chroot when started without root privileges"); 65 throw konforka::exception(CODEPOINT,"can't use User, Group or Chroot when started without root privileges");
66 if(config.flags&configuration::flag_user) { 66 if(config.flags&configuration::flag_user) {
67 struct passwd *ptmp = getpwnam(config.user.c_str()); 67 struct passwd *ptmp = getpwnam(config.user.c_str());
68 if(ptmp) { 68 if(ptmp) {
69 uid = ptmp->pw_uid; 69 uid = ptmp->pw_uid;
70 }else{ 70 }else{
71 errno=0; 71 errno=0;
72 uid = strtol(config.user.c_str(),NULL,0); 72 uid = strtol(config.user.c_str(),NULL,0);
73 if(errno) 73 if(errno)
74 throw konforka::exception(CODEPOINT,"failed to resolve User value to uid"); 74 throw konforka::exception(CODEPOINT,"failed to resolve User value to uid");
75 } 75 }
76 } 76 }
77 if(config.flags&configuration::flag_group) { 77 if(config.flags&configuration::flag_group) {
78 struct group *gtmp = getgrnam(config.group.c_str()); 78 struct group *gtmp = getgrnam(config.group.c_str());
79 if(gtmp) { 79 if(gtmp) {
80 gid = gtmp->gr_gid; 80 gid = gtmp->gr_gid;
81 }else{ 81 }else{
82 errno=0; 82 errno=0;
83 gid = strtol(config.group.c_str(),NULL,0); 83 gid = strtol(config.group.c_str(),NULL,0);
84 if(errno) 84 if(errno)
85 throw konforka::exception(CODEPOINT,"failed to resolve Group value to gid"); 85 throw konforka::exception(CODEPOINT,"failed to resolve Group value to gid");
86 } 86 }
87 } 87 }
88 if(!(config.flags&configuration::flag_root_source)) 88 if(!(config.flags&configuration::flag_root_source))
89 throw konforka::exception(CODEPOINT,"unspecified root for sources"); 89 throw konforka::exception(CODEPOINT,"unspecified root for sources");
90 if(!(config.flags&configuration::flag_root_intermediate)) 90 if(!(config.flags&configuration::flag_root_intermediate))
91 throw konforka::exception(CODEPOINT,"unspecified root for intermediate files"); 91 throw konforka::exception(CODEPOINT,"unspecified root for intermediate files");
92 if(!(config.flags&configuration::flag_root_so)) 92 if(!(config.flags&configuration::flag_root_so))
93 throw konforka::exception(CODEPOINT,"unspecified root for shared objects"); 93 throw konforka::exception(CODEPOINT,"unspecified root for shared objects");
94 if(config.flags&configuration::flag_min_children) 94 if(config.flags&configuration::flag_min_children)
95 min_children = config.min_children; 95 min_children = config.min_children;
96 if(config.flags&configuration::flag_max_children) 96 if(config.flags&configuration::flag_max_children)
97 max_children = config.max_children; 97 max_children = config.max_children;
98 if(config.flags&configuration::flag_min_spare_children) 98 if(config.flags&configuration::flag_min_spare_children)
99 min_spare_children = config.min_spare_children; 99 min_spare_children = config.min_spare_children;
100 if(config.flags&configuration::flag_max_spare_children) 100 if(config.flags&configuration::flag_max_spare_children)
101 max_spare_children = config.max_spare_children; 101 max_spare_children = config.max_spare_children;
102 if(max_children<min_spare_children) 102 if(max_children<min_spare_children)
103 throw konforka::exception(CODEPOINT,"inconsistent numbers of MaxChildren and MinSpareChildren"); 103 throw konforka::exception(CODEPOINT,"inconsistent numbers of MaxChildren and MinSpareChildren");
104 if(min_children>max_spare_children && max_spare_children>=0) 104 if(min_children>max_spare_children && max_spare_children>=0)
105 throw konforka::exception(CODEPOINT,"inconsistent numbers of MinChildren and MaxSpareChildren"); 105 throw konforka::exception(CODEPOINT,"inconsistent numbers of MinChildren and MaxSpareChildren");
106 if(config.flags&configuration::flag_multi_process) { 106 if(config.flags&configuration::flag_multi_process) {
107 multi = config.multi_process; 107 multi = config.multi_process;
108 }else{ 108 }else{
109 if(config.flags&configuration::flag_listen_socket) 109 if(config.flags&configuration::flag_listen_socket)
110 multi = true; 110 multi = true;
111 else 111 else
112 multi = false; 112 multi = false;
113 } 113 }
114 fss = (config.flags&configuration::flag_listen_socket)?new fcgi_socket(config.listen_socket.c_str(),5):new fcgi_socket(0); 114 fss = (config.flags&configuration::flag_listen_socket)?new fcgi_socket(config.listen_socket.c_str(),5):new fcgi_socket(0);
115 if(!fss) 115 if(!fss)
116 throw konforka::exception(CODEPOINT,"failed to establish listening socket"); 116 throw konforka::exception(CODEPOINT,"failed to establish listening socket");
117 if(config.flags&configuration::flag_daemonize && config.daemonize) { 117 if(config.flags&configuration::flag_daemonize && config.daemonize) {
118 pid_t pf = fork(); 118 pid_t pf = fork();
119 if(pf<0) 119 if(pf<0)
120 throw konforka::exception(CODEPOINT,"failed to fork()"); 120 throw konforka::exception(CODEPOINT,"failed to fork()");
121 if(pf) { 121 if(pf) {
122 die_humbly=true; 122 die_humbly=true;
123 _exit(0); 123 _exit(0);
124 } 124 }
125 } 125 }
126 if(config.flags&configuration::flag_pid_file) { 126 if(config.flags&configuration::flag_pid_file) {
127 pidfile.set(config.pid_file); 127 pidfile.set(config.pid_file);
128 } 128 }
129 if(multi) 129 if(multi)
130 sem.init(); 130 sem.init();
131 } 131 }
132sitecing_fastcgi_pm::~sitecing_fastcgi_pm() { 132sitecing_fastcgi_pm::~sitecing_fastcgi_pm() {
133 if(fss) 133 if(fss)
134 delete fss; 134 delete fss;
135} 135}
136 136
137void sitecing_fastcgi_pm::process(int slot) { 137void sitecing_fastcgi_pm::process(int slot) {
138 signal(SIGINT,SIG_DFL); 138 signal(SIGINT,SIG_DFL);
139 signal(SIGABRT,SIG_DFL); 139 signal(SIGABRT,SIG_DFL);
140 signal(SIGTERM,SIG_DFL); 140 signal(SIGTERM,SIG_DFL);
141 give_up_privs(); 141 give_up_privs();
142 scoreboard_slot *sslot = sboard.get_slot(slot); 142 scoreboard_slot *sslot = sboard.get_slot(slot);
143 try { 143 try {
144 sitespace ss(config); 144 sitespace ss(config);
145 fcgi_socket& fs = *fss; 145 fcgi_socket& fs = *fss;
146 sitecing_interface_cgi scif(&ss); 146 sitecing_interface_cgi scif(&ss);
147 string component_path; 147 string component_path;
148 string action; 148 string action;
149 config_options::action_handler_t *action_handler; 149 config_options::action_handler_t *action_handler;
150 int rpc = 0; 150 int rpc = 0;
151 if(config.flags&configuration::flag_requests_per_child) 151 if(config.flags&configuration::flag_requests_per_child)
152 rpc = config.requests_per_child; 152 rpc = config.requests_per_child;
153 for(int req=0;(rpc<=0) || (req<rpc);rpc++) { 153 for(int req=0;(rpc<=0) || (req<rpc);rpc++) {
154 semaphore_lock sl; 154 semaphore_lock sl;
155 if(multi) { 155 if(multi) {
156 sslot->state = scoreboard_slot::state_idle; 156 sslot->state = scoreboard_slot::state_idle;
157 sl.sem = &sem; 157 sl.sem = &sem;
158 sl.lock(); 158 sl.lock();
159 } 159 }
160 sslot->state = scoreboard_slot::state_accept; 160 sslot->state = scoreboard_slot::state_accept;
161 fcgi_interface fi(fs); 161 fcgi_interface fi(fs);
162 sslot->state = scoreboard_slot::state_processing; 162 sslot->state = scoreboard_slot::state_processing;
163 if(multi) 163 if(multi)
164 sl.unlock(); 164 sl.unlock();
165 cgi_gateway gw(fi); 165 cgi_gateway gw(fi);
166 scif.prepare(&gw); 166 scif.prepare(&gw);
167 try { 167 try {
168 component_path = normalize_path(gw.path_info(),strip_leading_slash|strip_trailing_slash); 168 component_path = konforka::normalize_path(gw.path_info(),konforka::strip_leading_slash|konforka::strip_trailing_slash);
169 string full_component_path; 169 string full_component_path;
170 string sitecing_path_info; 170 string sitecing_path_info;
171 while(true) { 171 while(true) {
172 full_component_path = config.root_source+'/'+component_path; 172 full_component_path = config.root_source+'/'+component_path;
173 if(!access(full_component_path.c_str(),F_OK)) 173 if(!access(full_component_path.c_str(),F_OK))
174 break; 174 break;
175 string::size_type sl = component_path.rfind('/'); 175 string::size_type sl = component_path.rfind('/');
176 if(sl==string::npos) 176 if(sl==string::npos)
177 throw konforka::exception(CODEPOINT,"can't find the target component"); 177 throw konforka::exception(CODEPOINT,"can't find the target component");
178 sitecing_path_info.insert(0,component_path,sl,string::npos); 178 sitecing_path_info.insert(0,component_path,sl,string::npos);
179 component_path.erase(sl); 179 component_path.erase(sl);
180 } 180 }
181 fi.metavars["SITECING_PATH_INFO"]=sitecing_path_info; 181 fi.metavars["SITECING_PATH_INFO"]=sitecing_path_info;
182 action = component_path; 182 action = component_path;
183 action_handler = config.lookup_action_handler(component_path); 183 action_handler = config.lookup_action_handler(component_path);
184 if(action_handler) { 184 if(action_handler) {
185 action = action_handler->action; 185 action = action_handler->action;
186 } 186 }
187 string pwd = dir_name(full_component_path); 187 string pwd = konforka::dir_name(full_component_path);
188 if(chdir(pwd.c_str())) 188 if(chdir(pwd.c_str()))
189 throw konforka::exception(CODEPOINT,"failed to chdir() into document's directory"); 189 throw konforka::exception(CODEPOINT,"failed to chdir() into document's directory");
190 so_component soc = ss.fetch(action,&scif); 190 so_component soc = ss.fetch(action,&scif);
191 if(action_handler) { 191 if(action_handler) {
192 soc.ac->run(__magic_action, 192 soc.ac->run(__magic_action,
193 config.root_source.c_str(), config.root_intermediate.c_str(), config.root_so.c_str(), 193 config.root_source.c_str(), config.root_intermediate.c_str(), config.root_so.c_str(),
194 &(action_handler->args) 194 &(action_handler->args)
195 ); 195 );
196 }else{ 196 }else{
197 soc.ac->main(0,NULL); 197 soc.ac->main(0,NULL);
198 } 198 }
199 }catch(http_status& hs) { 199 }catch(http_status& hs) {
200 scif.headers["Status"] = hs.status+" "+hs.message; 200 scif.headers["Status"] = hs.status+" "+hs.message;
201 string hshp = config.lookup_http_status_handler(component_path,hs.status); 201 string hshp = config.lookup_http_status_handler(component_path,hs.status);
202 if(!hshp.empty()) { 202 if(!hshp.empty()) {
203 so_component hsh = ss.fetch(hshp,&scif); // TODO: handle error trying to handle status 203 so_component hsh = ss.fetch(hshp,&scif); // TODO: handle error trying to handle status
204 hsh.ac->run(__magic_http_status,config.root_source.c_str(),config.root_intermediate.c_str(), 204 hsh.ac->run(__magic_http_status,config.root_source.c_str(),config.root_intermediate.c_str(),
205 config.root_so.c_str(),action.c_str(),&hs); 205 config.root_so.c_str(),action.c_str(),&hs);
206 } 206 }
207 }catch(compile_error& ce) { 207 }catch(compile_error& ce) {
208 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); 208 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler);
209 if(co_exception_handler) { 209 if(co_exception_handler) {
210 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. 210 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error.
211 eh.ac->run(__magic_compile_error,ce.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),ce.component_path.c_str()); 211 eh.ac->run(__magic_compile_error,ce.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),ce.component_path.c_str());
212 }else{ 212 }else{
213 ce.see(CODEPOINT); 213 ce.see(CODEPOINT);
214 throw; 214 throw;
215 } 215 }
216 }catch(preprocessor_error& pe) { 216 }catch(preprocessor_error& pe) {
217 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); 217 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler);
218 if(co_exception_handler) { 218 if(co_exception_handler) {
219 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. 219 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error.
220 eh.ac->run(__magic_preprocess_error,pe.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),pe.component_name.c_str(),pe.line_number); 220 eh.ac->run(__magic_preprocess_error,pe.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),pe.component_name.c_str(),pe.line_number);
221 }else{ 221 }else{
222 pe.see(CODEPOINT); 222 pe.see(CODEPOINT);
223 throw; 223 throw;
224 } 224 }
225 }catch(exception& e) { 225 }catch(exception& e) {
226 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); 226 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler);
227 if(co_exception_handler) { 227 if(co_exception_handler) {
228 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. 228 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error.
229 eh.ac->run(__magic_generic_exception,e.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),component_path.c_str(),&e); 229 eh.ac->run(__magic_generic_exception,e.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),component_path.c_str(),&e);
230 } 230 }
231 } 231 }
232 scif.flush(); 232 scif.flush();
233 } 233 }
234 }catch(exception& e) { 234 }catch(exception& e) {
235 cerr << "->Oops: " << e.what() << endl; 235 cerr << "->Oops: " << e.what() << endl;
236 } 236 }
237} 237}
238 238
239void sitecing_fastcgi_pm::run() { 239void sitecing_fastcgi_pm::run() {
240 if(multi) 240 if(multi)
241 manage(); 241 manage();
242 else 242 else
243 process(0); 243 process(0);
244} 244}
245 245
246void sitecing_fastcgi_pm::give_up_privs() { 246void sitecing_fastcgi_pm::give_up_privs() {
247 if(config.flags&configuration::flag_chroot) { 247 if(config.flags&configuration::flag_chroot) {
248 if(chroot(config.chroot.c_str())) 248 if(chroot(config.chroot.c_str()))
249 throw konforka::exception(CODEPOINT,"failed to chroot()"); 249 throw konforka::exception(CODEPOINT,"failed to chroot()");
250 } 250 }
251 if(config.flags&configuration::flag_group) { 251 if(config.flags&configuration::flag_group) {
252 if((getgid()!=gid) && setgid(gid)) 252 if((getgid()!=gid) && setgid(gid))
253 throw konforka::exception(CODEPOINT,"failed to setgid()"); 253 throw konforka::exception(CODEPOINT,"failed to setgid()");
254 } 254 }
255 if(config.flags&configuration::flag_user) { 255 if(config.flags&configuration::flag_user) {
256 if((getuid()!=uid) && setuid(uid)) 256 if((getuid()!=uid) && setuid(uid))
257 throw konforka::exception(CODEPOINT,"failed to setuid()"); 257 throw konforka::exception(CODEPOINT,"failed to setuid()");
258 } 258 }
259} 259}
260 260
261static sitecing_fastcgi_pm* _process_manager = NULL; 261static sitecing_fastcgi_pm* _process_manager = NULL;
262 262
263static void lethal_signal_handler(int signum) { 263static void lethal_signal_handler(int signum) {
264 _process_manager->finishing=true; 264 _process_manager->finishing=true;
265} 265}
266 266
267int main(int argc,char **argv) { 267int main(int argc,char **argv) {
268 const char* id = *argv; 268 const char* id = *argv;
269 const char* t; 269 const char* t;
270 while(t = index(id,'/')) { 270 while(t = index(id,'/')) {
271 id=t; id++; 271 id=t; id++;
272 } 272 }
273 openlog(id,LOG_PERROR|LOG_PID,LOG_USER); 273 openlog(id,LOG_PERROR|LOG_PID,LOG_USER);
274 try { 274 try {
275 string config_file = "sitecing.conf"; 275 string config_file = "sitecing.conf";
276 while(true) { 276 while(true) {
277 static struct option opts[] = { 277 static struct option opts[] = {
278 { "help", no_argument, 0, 'h' }, 278 { "help", no_argument, 0, 'h' },
279 { "usage", no_argument, 0, 'h' }, 279 { "usage", no_argument, 0, 'h' },
280 { "version", no_argument, 0, 'V' }, 280 { "version", no_argument, 0, 'V' },
281 { "license", no_argument, 0, 'L' }, 281 { "license", no_argument, 0, 'L' },
282 { "config", required_argument, 0, 'f' }, 282 { "config", required_argument, 0, 'f' },
283 { NULL, 0, 0, 0 } 283 { NULL, 0, 0, 0 }
284 }; 284 };
285 int c = getopt_long(argc,argv,"f:hVL",opts,NULL); 285 int c = getopt_long(argc,argv,"f:hVL",opts,NULL);
286 if(c==-1) 286 if(c==-1)
287 break; 287 break;
288 switch(c) { 288 switch(c) {
289 case 'h': 289 case 'h':
290 cerr << PHEADER << endl 290 cerr << PHEADER << endl
291 << PCOPY << endl << endl 291 << PCOPY << endl << endl
292 << " -h, --help" << endl 292 << " -h, --help" << endl
293 << " --usage display this text" << endl 293 << " --usage display this text" << endl
294 << " -V, --version display version number" << endl 294 << " -V, --version display version number" << endl
295 << " -L, --license show license" << endl 295 << " -L, --license show license" << endl
296 << " -f filename, --config=filename" << endl 296 << " -f filename, --config=filename" << endl
297 << " specify configuration file to use" << endl; 297 << " specify configuration file to use" << endl;
298 exit(0); 298 exit(0);
299 break; 299 break;
300 case 'V': 300 case 'V':
301 cerr << VERSION << endl; 301 cerr << VERSION << endl;
302 exit(0); 302 exit(0);
303 break; 303 break;
304 case 'L': 304 case 'L':
305 extern const char *COPYING; 305 extern const char *COPYING;
306 cerr << COPYING << endl; 306 cerr << COPYING << endl;
307 exit(0); 307 exit(0);
308 break; 308 break;
309 case 'f': 309 case 'f':
310 config_file = optarg; 310 config_file = optarg;
311 break; 311 break;
312 default: 312 default:
313 cerr << "Huh??" << endl; 313 cerr << "Huh??" << endl;
314 break; 314 break;
315 } 315 }
316 } 316 }
317 sitecing_fastcgi_pm sfpm(config_file); 317 sitecing_fastcgi_pm sfpm(config_file);
318 _process_manager = &sfpm; 318 _process_manager = &sfpm;
319 signal(SIGINT,lethal_signal_handler); 319 signal(SIGINT,lethal_signal_handler);
320 signal(SIGABRT,lethal_signal_handler); 320 signal(SIGABRT,lethal_signal_handler);
321 signal(SIGTERM,lethal_signal_handler); 321 signal(SIGTERM,lethal_signal_handler);
322 sfpm.run(); 322 sfpm.run();
323 }catch(exception& e) { 323 }catch(exception& e) {
324 /* cerr << "Oops: " << e.what() << endl; */ 324 /* cerr << "Oops: " << e.what() << endl; */
325 syslog(LOG_ERR,"uncaught exception: %s",e.what()); 325 syslog(LOG_ERR,"uncaught exception: %s",e.what());
326 } 326 }
327 closelog(); 327 closelog();
328} 328}
diff --git a/src/sitecing-plaincgi.cc b/src/sitecing-plaincgi.cc
index 3bd291a..2f93cc5 100644
--- a/src/sitecing-plaincgi.cc
+++ b/src/sitecing-plaincgi.cc
@@ -1,181 +1,181 @@
1#include <sys/types.h> 1#include <sys/types.h>
2#include <unistd.h> 2#include <unistd.h>
3#include <signal.h> 3#include <signal.h>
4#include <getopt.h> 4#include <getopt.h>
5#include <pwd.h> 5#include <pwd.h>
6#include <grp.h> 6#include <grp.h>
7#include <errno.h> 7#include <errno.h>
8#include <syslog.h> 8#include <syslog.h>
9#include <iostream> 9#include <iostream>
10#include <memory> 10#include <memory>
11#include <typeinfo> 11#include <typeinfo>
12using namespace std; 12using namespace std;
13#include "kingate/plaincgi.h" 13#include "kingate/plaincgi.h"
14#include "kingate/cgi_gateway.h" 14#include "kingate/cgi_gateway.h"
15using namespace kingate; 15using namespace kingate;
16#include "sitecing/sitecing_util.h" 16#include "sitecing/sitecing_util.h"
17#include "sitecing/util.h" 17#include "sitecing/util.h"
18#include "sitecing/sitespace.h" 18#include "sitecing/sitespace.h"
19#include "sitecing/sitecing_interface_cgi.h" 19#include "sitecing/sitecing_interface_cgi.h"
20#include "sitecing/cgi_component.h" 20#include "sitecing/cgi_component.h"
21#include "sitecing/configuration.h" 21#include "sitecing/configuration.h"
22#include "sitecing/magic.h" 22#include "sitecing/magic.h"
23#include "sitecing/sitecing_exception.h" 23#include "sitecing/sitecing_exception.h"
24#include "sitecing/exception.h" 24#include "sitecing/exception.h"
25using namespace sitecing; 25using namespace sitecing;
26 26
27#include "config.h" 27#include "config.h"
28#define PHEADER PACKAGE " Version " VERSION 28#define PHEADER PACKAGE " Version " VERSION
29#define PCOPY "Copyright (c) 2005 Klever Group" 29#define PCOPY "Copyright (c) 2005 Klever Group"
30 30
31class cdummyClass : public acomponent { 31class cdummyClass : public acomponent {
32 public: 32 public:
33 void main(int _magic,va_list _args) {} 33 void main(int _magic,va_list _args) {}
34 void *__the_most_derived_this() { return NULL; } 34 void *__the_most_derived_this() { return NULL; }
35} cdummyInstance; 35} cdummyInstance;
36class adummyClass : public cgi_component { 36class adummyClass : public cgi_component {
37 public: 37 public:
38 void main(int _magic,va_list _args) {} 38 void main(int _magic,va_list _args) {}
39 void *__the_most_derived_this() { return NULL; } 39 void *__the_most_derived_this() { return NULL; }
40} adummyInstance; 40} adummyInstance;
41 41
42void process_request(configuration& config) { 42void process_request(configuration& config) {
43 try { 43 try {
44 sitespace ss(config); 44 sitespace ss(config);
45 sitecing_interface_cgi scif(&ss); 45 sitecing_interface_cgi scif(&ss);
46 string component_path; 46 string component_path;
47 string action; 47 string action;
48 config_options::action_handler_t *action_handler; 48 config_options::action_handler_t *action_handler;
49 plaincgi_interface ci; 49 plaincgi_interface ci;
50 cgi_gateway gw(ci); 50 cgi_gateway gw(ci);
51 scif.prepare(&gw); 51 scif.prepare(&gw);
52 try { 52 try {
53 component_path = normalize_path(gw.path_info(),strip_leading_slash|strip_trailing_slash); 53 component_path = konforka::normalize_path(gw.path_info(),konforka::strip_leading_slash|konforka::strip_trailing_slash);
54 string full_component_path; 54 string full_component_path;
55 string sitecing_path_info; 55 string sitecing_path_info;
56 while(true) { 56 while(true) {
57 full_component_path = config.root_source+'/'+component_path; 57 full_component_path = config.root_source+'/'+component_path;
58 if(!access(full_component_path.c_str(),F_OK)) 58 if(!access(full_component_path.c_str(),F_OK))
59 break; 59 break;
60 string::size_type sl = component_path.rfind('/'); 60 string::size_type sl = component_path.rfind('/');
61 if(sl==string::npos) 61 if(sl==string::npos)
62 throw konforka::exception(CODEPOINT,"can't find the target component"); 62 throw konforka::exception(CODEPOINT,"can't find the target component");
63 sitecing_path_info.insert(0,component_path,sl,string::npos); 63 sitecing_path_info.insert(0,component_path,sl,string::npos);
64 component_path.erase(sl); 64 component_path.erase(sl);
65 } 65 }
66 ci.metavars["SITECING_PATH_INFO"]=sitecing_path_info; 66 ci.metavars["SITECING_PATH_INFO"]=sitecing_path_info;
67 action = component_path; 67 action = component_path;
68 action_handler = config.lookup_action_handler(component_path); 68 action_handler = config.lookup_action_handler(component_path);
69 if(action_handler) { 69 if(action_handler) {
70 action = action_handler->action; 70 action = action_handler->action;
71 } 71 }
72 string pwd = dir_name(full_component_path); 72 string pwd = konforka::dir_name(full_component_path);
73 if(chdir(pwd.c_str())) 73 if(chdir(pwd.c_str()))
74 throw konforka::exception(CODEPOINT,"failed to chdir() into document's directory"); 74 throw konforka::exception(CODEPOINT,"failed to chdir() into document's directory");
75 so_component soc = ss.fetch(action,&scif); 75 so_component soc = ss.fetch(action,&scif);
76 if(action_handler) { 76 if(action_handler) {
77 soc.ac->run(__magic_action, 77 soc.ac->run(__magic_action,
78 config.root_source.c_str(), config.root_intermediate.c_str(), config.root_so.c_str(), 78 config.root_source.c_str(), config.root_intermediate.c_str(), config.root_so.c_str(),
79 &(action_handler->args) 79 &(action_handler->args)
80 ); 80 );
81 }else{ 81 }else{
82 soc.ac->main(0,NULL); 82 soc.ac->main(0,NULL);
83 } 83 }
84 }catch(http_status& hs) { 84 }catch(http_status& hs) {
85 scif.headers["Status"] = hs.status+" "+hs.message; 85 scif.headers["Status"] = hs.status+" "+hs.message;
86 string hshp = config.lookup_http_status_handler(component_path,hs.status); 86 string hshp = config.lookup_http_status_handler(component_path,hs.status);
87 if(!hshp.empty()) { 87 if(!hshp.empty()) {
88 so_component hsh = ss.fetch(hshp,&scif); // TODO: handle error trying to handle status 88 so_component hsh = ss.fetch(hshp,&scif); // TODO: handle error trying to handle status
89 hsh.ac->run(__magic_http_status,config.root_source.c_str(),config.root_intermediate.c_str(), 89 hsh.ac->run(__magic_http_status,config.root_source.c_str(),config.root_intermediate.c_str(),
90 config.root_so.c_str(),action.c_str(),&hs); 90 config.root_so.c_str(),action.c_str(),&hs);
91 } 91 }
92 }catch(compile_error& ce) { 92 }catch(compile_error& ce) {
93 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); 93 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler);
94 if(co_exception_handler) { 94 if(co_exception_handler) {
95 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. 95 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error.
96 eh.ac->run(__magic_compile_error,ce.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),ce.component_path.c_str()); 96 eh.ac->run(__magic_compile_error,ce.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),ce.component_path.c_str());
97 }else{ 97 }else{
98 ce.see(CODEPOINT); 98 ce.see(CODEPOINT);
99 throw; 99 throw;
100 } 100 }
101 }catch(preprocessor_error& pe) { 101 }catch(preprocessor_error& pe) {
102 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); 102 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler);
103 if(co_exception_handler) { 103 if(co_exception_handler) {
104 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. 104 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error.
105 eh.ac->run(__magic_preprocess_error,pe.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),pe.component_name.c_str(),pe.line_number); 105 eh.ac->run(__magic_preprocess_error,pe.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),pe.component_name.c_str(),pe.line_number);
106 }else{ 106 }else{
107 pe.see(CODEPOINT); 107 pe.see(CODEPOINT);
108 throw; 108 throw;
109 } 109 }
110 }catch(exception& e) { 110 }catch(exception& e) {
111 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler); 111 config_options *co_exception_handler = config.lookup_config(component_path,config_options::flag_exception_handler);
112 if(co_exception_handler) { 112 if(co_exception_handler) {
113 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error. 113 so_component eh = ss.fetch(co_exception_handler->exception_handler,&scif); // TODO: handle error trying to handle error.
114 eh.ac->run(__magic_generic_exception,e.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),component_path.c_str(),&e); 114 eh.ac->run(__magic_generic_exception,e.what(),config.root_source.c_str(),config.root_intermediate.c_str(),config.root_so.c_str(),component_path.c_str(),&e);
115 } 115 }
116 } 116 }
117 scif.flush(); 117 scif.flush();
118 }catch(exception& e) { 118 }catch(exception& e) {
119 cerr << "->Oops: " << e.what() << endl; 119 cerr << "->Oops: " << e.what() << endl;
120 } 120 }
121} 121}
122 122
123int main(int argc,char **argv) { 123int main(int argc,char **argv) {
124 const char* id = *argv; 124 const char* id = *argv;
125 const char* t; 125 const char* t;
126 while(t = index(id,'/')) { 126 while(t = index(id,'/')) {
127 id=t; id++; 127 id=t; id++;
128 } 128 }
129 openlog(id,LOG_PERROR|LOG_PID,LOG_USER); 129 openlog(id,LOG_PERROR|LOG_PID,LOG_USER);
130 try { 130 try {
131 const char *esccf = getenv("SITECING_CONF"); 131 const char *esccf = getenv("SITECING_CONF");
132 string config_file = esccf ? esccf : "sitecing.conf"; 132 string config_file = esccf ? esccf : "sitecing.conf";
133 while(true) { 133 while(true) {
134 static struct option opts[] = { 134 static struct option opts[] = {
135 { "help", no_argument, 0, 'h' }, 135 { "help", no_argument, 0, 'h' },
136 { "usage", no_argument, 0, 'h' }, 136 { "usage", no_argument, 0, 'h' },
137 { "version", no_argument, 0, 'V' }, 137 { "version", no_argument, 0, 'V' },
138 { "license", no_argument, 0, 'L' }, 138 { "license", no_argument, 0, 'L' },
139 { "config", required_argument, 0, 'f' }, 139 { "config", required_argument, 0, 'f' },
140 { NULL, 0, 0, 0 } 140 { NULL, 0, 0, 0 }
141 }; 141 };
142 int c = getopt_long(argc,argv,"f:hVL",opts,NULL); 142 int c = getopt_long(argc,argv,"f:hVL",opts,NULL);
143 if(c==-1) 143 if(c==-1)
144 break; 144 break;
145 switch(c) { 145 switch(c) {
146 case 'h': 146 case 'h':
147 cerr << PHEADER << endl 147 cerr << PHEADER << endl
148 << PCOPY << endl << endl 148 << PCOPY << endl << endl
149 << " -h, --help" << endl 149 << " -h, --help" << endl
150 << " --usage display this text" << endl 150 << " --usage display this text" << endl
151 << " -V, --version display version number" << endl 151 << " -V, --version display version number" << endl
152 << " -L, --license show license" << endl 152 << " -L, --license show license" << endl
153 << " -f filename, --config=filename" << endl 153 << " -f filename, --config=filename" << endl
154 << " specify configuration file to use" << endl; 154 << " specify configuration file to use" << endl;
155 exit(0); 155 exit(0);
156 break; 156 break;
157 case 'V': 157 case 'V':
158 cerr << VERSION << endl; 158 cerr << VERSION << endl;
159 exit(0); 159 exit(0);
160 break; 160 break;
161 case 'L': 161 case 'L':
162 extern const char *COPYING; 162 extern const char *COPYING;
163 cerr << COPYING << endl; 163 cerr << COPYING << endl;
164 exit(0); 164 exit(0);
165 break; 165 break;
166 case 'f': 166 case 'f':
167 config_file = optarg; 167 config_file = optarg;
168 break; 168 break;
169 default: 169 default:
170 cerr << "Huh??" << endl; 170 cerr << "Huh??" << endl;
171 break; 171 break;
172 } 172 }
173 } 173 }
174 configuration config(config_file); 174 configuration config(config_file);
175 process_request(config); 175 process_request(config);
176 }catch(exception& e) { 176 }catch(exception& e) {
177 /* cerr << "Oops: " << e.what() << endl; */ 177 /* cerr << "Oops: " << e.what() << endl; */
178 syslog(LOG_ERR,"uncaught exception: %s",e.what()); 178 syslog(LOG_ERR,"uncaught exception: %s",e.what());
179 } 179 }
180 closelog(); 180 closelog();
181} 181}