Annotation of parser3/src/classes/root.C, revision 1.33
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.33 ! paf 6: $Id: root.C,v 1.32 2001/03/12 21:54:18 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:
1.33 ! paf 168: static void _eval(Request& r, const String& method_name, Array *params) {
! 169: Value& expr=*static_cast<Value *>(params->get(0));
! 170: r.fail_if_junction_(false, expr,
! 171: method_name, "need expression");
! 172: // evaluate expresion
! 173: Value *result=r.process(expr,
! 174: 0/*no name*/,
! 175: true/*don't intercept string*/).get_expr_result();
! 176: if(params->size()==2) {
! 177: Value& fmt=*static_cast<Value *>(params->get(1));
! 178: // forcing ^format[this param type]
! 179: r.fail_if_junction_(true, fmt,
! 180: method_name, "fmt must not be junction");
! 181:
! 182: Pool& pool=r.pool();
! 183: String *string=new(pool) String(pool);
! 184: string->APPEND_CONST(format(pool, result->get_double(), fmt.as_string().cstr()));
! 185: result=new(pool) VString(*string);
! 186: }
! 187: r.wcontext->write(*result, String::Untaint_lang::NO /*always object, not string*/);
! 188: }
1.31 paf 189:
190:
1.29 paf 191: typedef double (*math_one_double_op_func_ptr)(double);
192: static double round(double op) { return floor(op+0.5); }
193: static double sign(double op) { return op > 0 ? 1 : ( op < 0 ? -1 : 0 ); }
194:
195: static void _math_one_double_op(
1.30 paf 196: Request& r,
197: const String& method_name, Array *params,
198: math_one_double_op_func_ptr func) {
1.29 paf 199: Pool& pool=r.pool();
200: Value& param=*static_cast<Value *>(params->get(0));
201:
202: // forcing ^round(this param type)
203: r.fail_if_junction_(false, param,
204: method_name, "parameter must be expression");
205:
206: Value& result=*new(pool) VDouble(pool, (*func)(r.process(param).get_double()));
207: r.wcontext->write(result, String::Untaint_lang::NO /*always object, not string*/);
208: }
209:
210: static void _round(Request& r, const String& method_name, Array *params) {
211: _math_one_double_op(r, method_name, params, &round);
212: }
213:
214: static void _floor(Request& r, const String& method_name, Array *params) {
215: _math_one_double_op(r, method_name, params, &floor);
216: }
217:
218: static void _ceiling(Request& r, const String& method_name, Array *params) {
219: _math_one_double_op(r, method_name, params, &ceil);
220: }
221:
222: static void _abs(Request& r, const String& method_name, Array *params) {
223: _math_one_double_op(r, method_name, params, &fabs);
224: }
225:
226: static void _sign(Request& r, const String& method_name, Array *params) {
227: _math_one_double_op(r, method_name, params, &sign);
228: }
229:
1.7 paf 230: void initialize_root_class(Pool& pool, VClass& vclass) {
1.15 paf 231: // ^if(condition){code-when-true}
232: // ^if(condition){code-when-true}{code-when-false}
233: vclass.add_native_method("if", _if, 2, 3);
234:
235: // ^untaint[as-is|sql|js|html|html-typo]{code}
236: vclass.add_native_method("untaint", _untaint, 2, 2);
1.18 paf 237:
238: // ^process[code]
239: vclass.add_native_method("process", _process, 1, 1);
1.26 paf 240:
241: // ^rem{code}
242: vclass.add_native_method("rem", _rem, 1, 1);
1.27 paf 243:
244: // ^while(condition){code}
245: vclass.add_native_method("while", _while, 2, 2);
1.28 paf 246:
247: // ^use[file]
248: vclass.add_native_method("use", _use, 1, 1);
1.29 paf 249:
1.31 paf 250: // ^for[i;from-number;to-number-inclusive]{code}[delim]
251: vclass.add_native_method("for", _for, 3+1, 3+1+1);
1.33 ! paf 252:
! 253: // ^eval(expr)
! 254: // ^eval(expr)[format]
! 255: vclass.add_native_method("eval", _eval, 1, 2);
1.31 paf 256:
1.29 paf 257:
258: // math functions
259:
260: // ^round(expr)
261: vclass.add_native_method("round", _round, 1, 1);
262:
263: // ^floor(expr)
264: vclass.add_native_method("floor", _floor, 1, 1);
265:
266: // ^ceiling(expr)
267: vclass.add_native_method("ceiling", _ceiling, 1, 1);
268:
269: // ^abs(expr)
270: vclass.add_native_method("abs", _abs, 1, 1);
271:
272: // ^sign(expr)
273: vclass.add_native_method("sign", _sign, 1, 1);
1.1 paf 274: }
E-mail: