Annotation of parser3/src/classes/root.C, revision 1.32
1.1 paf 1: /*
1.10 paf 2: Parser
3: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.12 paf 4: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
1.10 paf 5:
1.32 ! paf 6: $Id: root.C,v 1.31 2001/03/12 21:18:00 paf Exp $
1.1 paf 7: */
8:
1.18 paf 9: #include <string.h>
1.29 paf 10: #include <math.h>
1.18 paf 11:
1.1 paf 12: #include "pa_request.h"
1.8 paf 13: #include "_root.h"
1.31 paf 14: #include "pa_vint.h"
1.32 ! paf 15: #include "pa_common.h"
1.1 paf 16:
1.18 paf 17: static void _if(Request& r, const String&, Array *params) {
1.2 paf 18: bool condition=
1.18 paf 19: r.process(
1.6 paf 20: *static_cast<Value *>(params->get(0)),
1.11 paf 21: 0/*no name*/,
1.14 paf 22: false/*don't intercept string*/).get_bool();
1.6 paf 23: if(condition) {
1.18 paf 24: Value& value=r.process(*static_cast<Value *>(params->get(1)));
1.22 paf 25: r.write_pass_lang(value);
1.6 paf 26: } else if(params->size()==3) {
1.18 paf 27: Value& value=r.process(*static_cast<Value *>(params->get(2)));
1.22 paf 28: r.write_pass_lang(value);
1.6 paf 29: }
1.1 paf 30: }
31:
1.22 paf 32: static void _untaint(Request& r, const String& method_name, Array *params) {
1.18 paf 33: const String& lang_name=r.process(*static_cast<Value *>(params->get(0))).as_string();
1.15 paf 34: String::Untaint_lang lang=static_cast<String::Untaint_lang>(
1.23 paf 35: untaint_lang_name2enum->get_int(lang_name));
1.15 paf 36: if(!lang)
37: R_THROW(0, 0,
38: &lang_name,
1.18 paf 39: "invalid untaint language");
1.15 paf 40:
1.24 paf 41: {
42: Temp_lang temp_lang(r, lang);
43: Value *vbody=static_cast<Value *>(params->get(1));
44: // forcing ^untaint[]{this param type}
1.26 paf 45: r.fail_if_junction_(false, *vbody,
46: method_name, "body must be junction");
1.24 paf 47:
48: r.write_pass_lang(r.process(*vbody));
49: }
1.15 paf 50: }
51:
52:
1.22 paf 53: static void _process(Request& r, const String& method_name, Array *params) {
1.20 paf 54: // calculate pseudo file name of processed chars
55: // would be something like "/some/file(4) process"
1.18 paf 56: char place[MAX_STRING];
57: #ifndef NO_STRING_ORIGIN
1.25 paf 58: const Origin& origin=method_name.origin();
1.18 paf 59: snprintf(place, MAX_STRING, "%s(%d) %s",
60: origin.file, 1+origin.line,
1.22 paf 61: method_name.cstr());
1.18 paf 62: #else
1.22 paf 63: strncpy(place, MAX_STRING, method_name.cstr());
1.18 paf 64: #endif
65:
1.20 paf 66: VClass& self_class=*r.self->get_class();
1.22 paf 67: {
68: // temporary zero @main so to maybe-replace it in processed code
69: Temp_method temp_method(self_class, *main_method_name, 0);
70:
1.25 paf 71: // evaluate source to process
72: const String& source=
73: r.process(*static_cast<Value *>(params->get(0))).as_string();
74:
1.22 paf 75: // process source code, append processed methods to 'self' class
76: // maybe-define new @main
77: r.use_buf(source.cstr(), place, &self_class);
78:
79: // maybe-execute @main[]
80: if(const Method *method=self_class.get_method(*main_method_name)) {
81: // execute!
82: r.execute(*method->parser_code);
83: }
1.18 paf 84: }
85: }
86:
1.26 paf 87: static void _rem(Request& r, const String& method_name, Array *params) {
1.27 paf 88: // forcing ^rem{this param type}
1.26 paf 89: r.fail_if_junction_(false, *static_cast<Value *>(params->get(0)),
90: method_name, "body must be junction");
91: }
1.18 paf 92:
1.27 paf 93: static void _while(Request& r, const String& method_name, Array *params) {
94: Value& vcondition=*static_cast<Value *>(params->get(0));
95: // forcing ^while(this param type){}
96: r.fail_if_junction_(false, vcondition,
97: method_name, "condition must be junction");
98:
99: Value& body=*static_cast<Value *>(params->get(1));
100: // forcing ^while(){this param type}
101: r.fail_if_junction_(false, body,
102: method_name, "body must be junction");
103:
104: // while...
105: int endless_loop_count=0;
106: while(true) {
107: if(++endless_loop_count>=1973) // endless loop?
108: R_THROW(0, 0,
109: &method_name,
110: "endless loop detected");
111:
112: bool condition=
113: r.process(
114: vcondition,
115: 0/*no name*/,
116: false/*don't intercept string*/).get_bool();
117: if(!condition) // ...condition is true
118: break;
119:
120: // write processed body
121: r.write_pass_lang(r.process(body));
122: }
123: }
124:
1.28 paf 125: static void _use(Request& r, const String& method_name, Array *params) {
126: Value& vfile=*static_cast<Value *>(params->get(0));
127: // forcing ^rem{this param type}
128: r.fail_if_junction_(true, vfile,
129: method_name, "file name must not be junction");
130:
131: char *file=vfile.as_string().cstr();
132: r.use_file(r.absolute(file));
133: }
134:
1.31 paf 135: static void _for(Request& r, const String& method_name, Array *params) {
136: // ^for[i;from-number;to-number-inclusive]{code}[delim]
137:
138: Pool& pool=r.pool();
139: const String& var_name=r.process(*static_cast<Value *>(params->get(0))).as_string();
140: int from=(int)r.process(*static_cast<Value *>(params->get(1))).get_double();
141: int to=(int)r.process(*static_cast<Value *>(params->get(2))).get_double();
142: Value& body_code=*static_cast<Value *>(params->get(3));
143: // forcing ^menu{this param type}
144: r.fail_if_junction_(false, body_code,
145: method_name, "body must be junction");
146: Value *delim_code=params->size()==3+1+1?static_cast<Value *>(params->get(3+1)):0;
147:
148: bool need_delim=false;
149: int endless_loop_count=0;
150: for(VInt *vint=new(pool) VInt(pool, from); vint->get_int()<=to; vint->inc()) {
151: if(++endless_loop_count>=2001) // endless loop?
152: R_THROW(0, 0,
153: &method_name,
154: "endless loop detected");
155: r.wcontext->put_element(var_name, vint);
156:
157: Value& processed_body=r.process(body_code);
158: if(delim_code) { // delimiter set?
159: const String *string=processed_body.get_string();
160: if(need_delim && string && string->size()) // need delim & iteration produced string?
161: r.write_pass_lang(r.process(*delim_code));
162: need_delim=true;
163: }
164: r.write_pass_lang(processed_body);
165: }
166: }
167:
168:
169:
1.29 paf 170: typedef double (*math_one_double_op_func_ptr)(double);
171: static double round(double op) { return floor(op+0.5); }
172: static double sign(double op) { return op > 0 ? 1 : ( op < 0 ? -1 : 0 ); }
173:
174: static void _math_one_double_op(
1.30 paf 175: Request& r,
176: const String& method_name, Array *params,
177: math_one_double_op_func_ptr func) {
1.29 paf 178: Pool& pool=r.pool();
179: Value& param=*static_cast<Value *>(params->get(0));
180:
181: // forcing ^round(this param type)
182: r.fail_if_junction_(false, param,
183: method_name, "parameter must be expression");
184:
185: Value& result=*new(pool) VDouble(pool, (*func)(r.process(param).get_double()));
186: r.wcontext->write(result, String::Untaint_lang::NO /*always object, not string*/);
187: }
188:
189: static void _round(Request& r, const String& method_name, Array *params) {
190: _math_one_double_op(r, method_name, params, &round);
191: }
192:
193: static void _floor(Request& r, const String& method_name, Array *params) {
194: _math_one_double_op(r, method_name, params, &floor);
195: }
196:
197: static void _ceiling(Request& r, const String& method_name, Array *params) {
198: _math_one_double_op(r, method_name, params, &ceil);
199: }
200:
201: static void _abs(Request& r, const String& method_name, Array *params) {
202: _math_one_double_op(r, method_name, params, &fabs);
203: }
204:
205: static void _sign(Request& r, const String& method_name, Array *params) {
206: _math_one_double_op(r, method_name, params, &sign);
207: }
208:
1.7 paf 209: void initialize_root_class(Pool& pool, VClass& vclass) {
1.15 paf 210: // ^if(condition){code-when-true}
211: // ^if(condition){code-when-true}{code-when-false}
212: vclass.add_native_method("if", _if, 2, 3);
213:
214: // ^untaint[as-is|sql|js|html|html-typo]{code}
215: vclass.add_native_method("untaint", _untaint, 2, 2);
1.18 paf 216:
217: // ^process[code]
218: vclass.add_native_method("process", _process, 1, 1);
1.26 paf 219:
220: // ^rem{code}
221: vclass.add_native_method("rem", _rem, 1, 1);
1.27 paf 222:
223: // ^while(condition){code}
224: vclass.add_native_method("while", _while, 2, 2);
1.28 paf 225:
226: // ^use[file]
227: vclass.add_native_method("use", _use, 1, 1);
1.29 paf 228:
1.31 paf 229: // ^for[i;from-number;to-number-inclusive]{code}[delim]
230: vclass.add_native_method("for", _for, 3+1, 3+1+1);
231:
1.29 paf 232:
233: // math functions
234:
235: // ^round(expr)
236: vclass.add_native_method("round", _round, 1, 1);
237:
238: // ^floor(expr)
239: vclass.add_native_method("floor", _floor, 1, 1);
240:
241: // ^ceiling(expr)
242: vclass.add_native_method("ceiling", _ceiling, 1, 1);
243:
244: // ^abs(expr)
245: vclass.add_native_method("abs", _abs, 1, 1);
246:
247: // ^sign(expr)
248: vclass.add_native_method("sign", _sign, 1, 1);
1.1 paf 249: }
E-mail: