Annotation of parser3/src/classes/root.C, revision 1.29
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.29 ! paf 6: $Id: root.C,v 1.28 2001/03/12 18:19:36 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(
! 138: Request& r,
! 139: const String& method_name, Array *params,
! 140: math_one_double_op_func_ptr func) {
! 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: