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