|
|
1.1 paf 1: /*
1.9 paf 2: Parser
3: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.14 paf 4: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
1.9 paf 5:
1.29 paf 6: $Id: pa_request.C,v 1.28 2001/03/13 17:54:14 paf Exp $
1.1 paf 7: */
8:
1.19 paf 9: #include <string.h>
10:
1.1 paf 11: #include "pa_request.h"
1.3 paf 12: #include "pa_wwrapper.h"
13: #include "pa_common.h"
14: #include "pa_vclass.h"
1.11 paf 15: #include "_root.h"
16: #include "_env.h"
1.17 paf 17: #include "_table.h"
1.6 paf 18: #include "core.h"
1.30 ! paf 19: #include "pa_vint.h"
! 20: #include "pa_vmframe.h"
1.3 paf 21:
1.30 ! paf 22: #define NEW_STRING(name, value) name=NEW String(pool()); name->APPEND_CONST(value)
! 23: #define LOCAL_STRING(name, value) String name(pool()); name.APPEND_CONST(value)
1.3 paf 24:
1.28 paf 25: Request::Request(Pool& apool,
26: String::Untaint_lang alang,
1.30 ! paf 27: const char *adocument_root,
! 28: const char *apage_filespec) : Pooled(apool),
1.3 paf 29: stack(apool),
30: root_class(apool),
31: env_class(apool),
1.27 paf 32: form_class(apool),
1.3 paf 33: fclasses(apool),
1.28 paf 34: flang(alang),
35: fdocument_root(adocument_root),
36: fpage_filespec(apage_filespec)
1.3 paf 37: {
1.27 paf 38: // root superclass,
1.3 paf 39: // parent of all classes,
40: // operators holder
1.27 paf 41: initialize_root_class(pool(), root_class);
1.6 paf 42: classes().put(*root_class_name, &root_class);
1.27 paf 43: // table class
44: classes().put(*table_class_name, table_class);
45: // table_class->set_name(*table_class_name);
1.3 paf 46:
47: // env class
1.6 paf 48: classes().put(*env_class_name, &env_class);
1.27 paf 49: // form class
50: classes().put(*form_class_name, &form_class);
1.3 paf 51: }
1.1 paf 52:
1.29 paf 53: char *Request::core(const char *sys_auto_path1,
54: const char *sys_auto_path2) {
1.28 paf 55: char *result;
1.29 paf 56: VStateless_class *main_class=0;
1.3 paf 57: TRY {
1.29 paf 58: char *auto_filespec=(char *)malloc(MAX_STRING);
59:
60: // load MAIN class,
61: // it consists of all the auto.p files we'd manage to find
62: // plus
63: // the file user requested us to process
64: // all located classes become children of one another,
65: // composing class we name 'MAIN'
66:
67: // loading system auto.p 1
68: if(sys_auto_path1) {
1.30 ! paf 69: strncpy(auto_filespec, sys_auto_path1, MAX_STRING-strlen(AUTO_FILE_NAME));
1.29 paf 70: strcat(auto_filespec, AUTO_FILE_NAME);
71: main_class=use_file(
72: auto_filespec, false/*ignore possible read problem*/,
73: main_class_name);
74: }
75:
76: // loading system auto.p 2
77: if(sys_auto_path2) {
1.30 ! paf 78: strncpy(auto_filespec, sys_auto_path2, MAX_STRING-strlen(AUTO_FILE_NAME));
1.29 paf 79: strcat(auto_filespec, AUTO_FILE_NAME);
80: VStateless_class *main_class=use_file(
81: auto_filespec, false/*ignore possible read problem*/,
82: main_class_name);
83: }
1.8 paf 84:
1.13 paf 85: // TODO: использовать $MAIN:limits здесь, пока их не сломали враги
1.7 paf 86:
87: // TODO: load site auto.p files, all assigned bases from upper dir
88: char *site_auto_file="Y:\\parser3\\src\\auto.p";
1.16 paf 89: main_class=use_file(
90: site_auto_file, false/*ignore possible read problem*/,
1.25 paf 91: main_class_name, main_class);
1.7 paf 92:
93: // there must be some auto.p
1.12 paf 94: if(!main_class)
1.7 paf 95: THROW(0,0,
96: 0,
1.24 paf 97: "no 'auto.p' found (nither system nor any site's)");
1.5 paf 98:
1.7 paf 99: // compiling requested file
1.28 paf 100: main_class=use_file(fpage_filespec, true/*don't ignore read problem*/,
1.25 paf 101: main_class_name, main_class);
102:
103: // execute @main[]
1.30 ! paf 104: result=execute_method(*main_class, *main_method_name);
1.25 paf 105: if(!result)
106: THROW(0,0,
107: 0,
108: "'"MAIN_METHOD_NAME"' method not found");
1.3 paf 109: }
110: CATCH(e) {
1.30 ! paf 111: TRY {
! 112: // we're returning not result, but error explanation
! 113: result=0;
! 114:
! 115: if(main_class) { // we've managed to end up with some main_class
! 116: // maybe we'd be lucky enough as to report an error
! 117: // in a gracefull way...
! 118: if(Value *value=main_class->get_element(*exception_method_name))
! 119: if(Junction *junction=value->get_junction())
! 120: if(const Method *method=junction->method) {
! 121: // preparing to pass parameters to
! 122: // @exception[origin;source;comment;type;code]
! 123: VMethodFrame *frame=NEW VMethodFrame(pool(), *junction);
! 124:
! 125: const String *problem_source=e.problem_source();
! 126: // origin
! 127: LOCAL_STRING(origin_name, "origin");
! 128: VString *origin_value=0;
! 129: #ifndef NO_STRING_ORIGIN
! 130: const Origin& origin=problem_source->origin();
! 131: if(origin.file) {
! 132: char *buf=(char *)malloc(MAX_STRING);
! 133: snprintf(buf, MAX_STRING, "%s(%d): ",
! 134: origin.file, 1+origin.line);
! 135: String *NEW_STRING(origin_file_line, buf);
! 136: origin_value=NEW VString(*origin_file_line);
! 137: }
! 138: #endif
! 139: frame->store_param(origin_name, origin_value);
1.28 paf 140:
1.30 ! paf 141: // source
! 142: LOCAL_STRING(source_name, "source");
! 143: frame->store_param(source_name,
! 144: NEW VString(*problem_source));
! 145:
! 146: // comment
! 147: LOCAL_STRING(comment_name, "comment");
! 148: String *NEW_STRING(comment_value, e.comment());
! 149: frame->store_param(comment_name,
! 150: NEW VString(*comment_value));
! 151:
! 152: // type
! 153: LOCAL_STRING(type_name, "type");
! 154: Value *type_value;
! 155: if(e.type())
! 156: type_value=NEW VString(*e.type());
! 157: else
! 158: type_value=NEW VUnknown(pool());
! 159: frame->store_param(type_name, type_value);
! 160:
! 161: // code
! 162: LOCAL_STRING(code_name, "code");
! 163: Value *code_value;
! 164: if(e.code())
! 165: code_value=NEW VString(*e.code());
! 166: else
! 167: code_value=NEW VUnknown(pool());
! 168: frame->store_param(code_name, code_value);
! 169:
! 170: result=execute_method(*frame, *method);
! 171: }
! 172: }
! 173:
! 174: // couldn't report an error beautifully, doing that ugly
! 175: if(!result) {
! 176: result=(char *)malloc(MAX_STRING);
! 177: result[0]=0;
! 178: size_t printed=0;
! 179: const String *problem_source=e.problem_source();
! 180: if(problem_source) {
1.16 paf 181: #ifndef NO_STRING_ORIGIN
1.30 ! paf 182: const Origin& origin=problem_source->origin();
! 183: if(origin.file)
! 184: printed+=snprintf(result+printed, MAX_STRING-printed, "%s(%d): ",
! 185: origin.file, 1+origin.line);
1.28 paf 186: #endif
1.30 ! paf 187: printed+=snprintf(result+printed, MAX_STRING-printed, "'%s' ",
! 188: problem_source->cstr());
! 189: }
! 190: printed+=snprintf(result+printed, MAX_STRING-printed, "%s",
! 191: e.comment());
! 192: const String *type=e.type();
! 193: if(type) {
! 194: printed+=snprintf(result+printed, MAX_STRING-printed, " type: %s",
! 195: type->cstr());
! 196: const String *code=e.code();
! 197: if(code)
! 198: printed+=snprintf(result+printed, MAX_STRING-printed, ", code: %s",
! 199: code->cstr());
! 200: }
! 201: }
1.3 paf 202: }
1.30 ! paf 203: CATCH(e) {
! 204: // exception in exception handler occured
! 205: // probably totally out of memory
! 206: // can't say anything about such sad story
! 207: // would just return 0
! 208: result=0;
1.1 paf 209: }
1.30 ! paf 210: END_CATCH
1.1 paf 211: }
1.3 paf 212: END_CATCH
1.28 paf 213:
214: return result;
1.1 paf 215: }
216:
1.26 paf 217: VStateless_class *Request::use_file(
218: const char *file, bool fail_on_read_problem,
219: const String *name,
220: VStateless_class *base_class) {
1.3 paf 221: // TODO: обнаружить|решить cyclic dependences
1.5 paf 222: char *source=file_read(pool(), file, fail_on_read_problem);
1.3 paf 223: if(!source)
1.12 paf 224: return base_class;
1.3 paf 225:
1.25 paf 226: return use_buf(source, file, 0/*new class*/, name, base_class);
1.16 paf 227: }
228:
1.26 paf 229: VStateless_class *Request::use_buf(
230: const char *source, const char *file,
231: VStateless_class *aclass, const String *name,
232: VStateless_class *base_class) {
1.5 paf 233: // compile loaded class
1.26 paf 234: VStateless_class& cclass=COMPILE(source, aclass, name, base_class, file);
1.1 paf 235:
1.4 paf 236: // locate and execute possible @auto[] static method
1.25 paf 237: execute_method(cclass, *auto_method_name, false /*no result needed*/);
1.16 paf 238: return &cclass;
1.20 paf 239: }
240:
241: void Request::fail_if_junction_(bool is,
1.26 paf 242: Value& value, const String& method_name, char *msg) {
1.20 paf 243:
244: // fail_if_junction(true, junction = fail
245: // fail_if_junction(false, not junction = fail
246: if((value.get_junction()!=0) ^ !is)
247: THROW(0, 0,
248: &method_name,
249: msg);
1.19 paf 250: }
251:
252: char *Request::relative(const char *path, const char *file) {
1.21 paf 253: char *result=(char *)malloc(strlen(path)+strlen(file)+1);
1.19 paf 254: strcpy(result, path);
255: rsplit(result,'/');
256: strcat(result, "/");
257: strcat(result, file);
258: return result;
259: }
260:
261: char *Request::absolute(const char *name) {
262: if(name[0]=='/') {
1.28 paf 263: char *result=(char *)malloc(strlen(fdocument_root)+strlen(name)+1);
264: strcpy(result, fdocument_root);
1.19 paf 265: strcat(result, name);
266: return result;
267: } else
1.28 paf 268: return relative(fpage_filespec, name);
1.1 paf 269: }