Back to index

im-sdk  12.3.91
PCE.c
Go to the documentation of this file.
00001 /*
00002   PCE.c
00003     Primary Composition Engine
00004 */
00005 #ifdef HAVE_CONFIG_H
00006 #include <config.h>
00007 #endif
00008 #include <stdio.h>
00009 #include <setjmp.h>
00010 #include <EIMIL.h>
00011 #include <EIMILint.h>
00012 
00013 #ifdef HAVE_STRING_H
00014 #include <string.h>
00015 #endif
00016 #ifdef HAVE_MALLOC_H
00017 #include <malloc.h>
00018 #endif
00019 #ifdef HAVE_STDLIB_H
00020 #include <stdlib.h>
00021 #endif
00022 
00023 /********************************************************************************
00024                              Declarations
00025 *********************************************************************************/
00026 
00027 #define PCE_MAX_NUMBER ((1 << 23) - 1)
00028 #define PCE_DICTIONARY_DEFAULT_SIZE 17
00029 
00030 #define PCE_CALL_MAX_DEPTH 16
00031 
00032 typedef struct PCE_code PCE_code;
00033 typedef struct PCE_data PCE_data;
00034 typedef struct PCE_context PCE_context;
00035 typedef struct PCE_funcproto PCE_funcproto;
00036 typedef struct PCE_function PCE_function;
00037 typedef struct PCE_inst_template PCE_inst_template;
00038 typedef struct PCE_parse_context PCE_parse_context;
00039 typedef struct PCE_label PCE_label;
00040 typedef struct PCE_labelset PCE_labelset;
00041 
00042 typedef EIMIL_value* (*PCE_EXEC_HANDLER)(PCE_context *pctx);
00043 
00044 struct PCE_data {
00045     PCE_code *pcode;
00046 };
00047 
00048 typedef enum PCE_ERROR_CODE (*PCE_SEH_TRY_FUNCTION)(PCE_context *pctx,
00049                                               void *arg);
00050 typedef enum PCE_ERROR_CODE (*PCE_SEH_CATCH_FUNCTION)(PCE_context *pctx,
00051                                                 int ecode,
00052                                                 void *throwarg,
00053                                                 void *catcharg);
00054 typedef struct PCE_SEH_catchblock PCE_SEH_catchblock;
00055 typedef struct PCE_SEH_block PCE_SEH_block;
00056 struct PCE_SEH_catchblock {
00057     int type;
00058     PCE_SEH_CATCH_FUNCTION pcfs;
00059     void *catcharg;
00060     PCE_SEH_catchblock *pnext;
00061 };
00062 
00063 struct PCE_SEH_block {
00064     jmp_buf jmp;
00065     void *arg;
00066     PCE_SEH_catchblock *pcatchers;
00067     PCE_SEH_block *pnext;
00068 };
00069 
00070 struct PCE_context {
00071     int depth;
00072     PCE_code *pcur;
00073     EIMIL_data *ped;
00074     EIMIL_dictionary *pdic;
00075     EIMIL_dictionary *pdic_f;
00076     EIMIL_symbol *psym_cev;
00077     PCE_data *ppce_data;
00078     EIMIL_dictionary *pfuncdic[PCE_CALL_MAX_DEPTH];
00079     PCE_SEH_block *pseh;
00080 };
00081 
00082 struct PCE_funcproto {
00083     EIMIL_symbol *psym;
00084     enum EIMIL_TYPE type;
00085 };
00086 
00087 struct PCE_function {
00088     int nargs;
00089     PCE_funcproto *pfp;
00090     EIMIL_dictionary *pdic;
00091     int rettype;
00092     PCE_code *pc;
00093 };
00094 
00095 enum PCE_CODE_TYPE {
00096        PCE_CODE_INST,
00097        PCE_CODE_VALUE,
00098 
00099        PCE_CODE_MAIN,
00100        PCE_CODE_DEFUN,
00101 
00102        PCE_CODE_JMP,
00103        PCE_CODE_UNRESOLVED_JMP,
00104        PCE_CODE_COND_JMP,
00105        PCE_CODE_UNRESOLVED_COND_JMP,
00106        PCE_CODE_COND_NOT_JMP,
00107        PCE_CODE_UNRESOLVED_COND_NOT_JMP,
00108 
00109        PCE_CODE_SYMBOL = (1 << 16),
00110        PCE_CODE_FUNCTION
00111 };
00112 
00113 #define PCE_ARG_MAX 5
00114 struct PCE_inst_template {
00115     enum PCE_CODE_TYPE code_type;
00116     PCE_EXEC_HANDLER handler;
00117     enum EIMIL_TYPE result;
00118     int newmode;
00119     int required_type[PCE_ARG_MAX];
00120 };
00121 
00122 #define PCE_SET_REQUIRED_TYPES(PCX, PIT) \
00123   (memcpy((PCX)->required_type, (PIT)->required_type, sizeof((PCX)->required_type)))
00124 
00125 struct PCE_label {
00126     int id;
00127     PCE_code *pc;
00128     EIMIL_symbol *psym;
00129     /* If this flag is set, the label will be 
00130        set to the next code.  */
00131     int nextp;
00132 };
00133 
00134 struct PCE_labelset {
00135     int labelnum;
00136     int allocednum;
00137     EIMIL_dictionary *pdic;
00138     PCE_label *pl;
00139 };
00140 
00141 struct PCE_parse_context {
00142     PCE_context *pctx;
00143     int idx;
00144     unsigned int mode;
00145     int required_type[PCE_ARG_MAX];
00146     enum EIMIL_TYPE result;
00147     EIMIL_dictionary *pdic;
00148     EIMIL_symbol *psym;
00149     PCE_function *pf;
00150     PCE_code *pc;
00151     PCE_code *pc_head;
00152     PCE_labelset *plabels;
00153     int labelid;
00154     int labelid2;
00155 
00156     PCE_parse_context *pnext;
00157 };
00158 
00159 struct PCE_code {
00160     enum PCE_CODE_TYPE type;
00161     union {
00162        PCE_EXEC_HANDLER h;
00163        EIMIL_value *pv;
00164        EIMIL_SYMID symid;
00165        PCE_function *pf;
00166        PCE_code *pc_to;
00167        int to_labelid;
00168     } val;
00169     void *poption;
00170     PCE_code *parg;
00171     PCE_code *pnext;
00172 };
00173 
00174 enum PCE_CONTEXT_MODE {
00175        PCE_IN_MAIN = (1 << 0),
00176        PCE_IN_TRY = (1 << 1),
00177        PCE_IN_CATCH = (1 << 2),
00178        PCE_IN_DEFVAR = (1 << 3),
00179        PCE_DEFVAR_NIL = (1 << 4),
00180        PCE_DEFVAR_DONE = (1 << 5),
00181        PCE_IN_DEFUN = (1 << 6),
00182        PCE_IN_DEFTABLE = (1 << 7),
00183        PCE_IN_DEFPATTERN = (1 << 8),
00184 
00185        PCE_CONTEXT_MODE_PERSISTENT_MASK = (1 << 16) - 1,
00186 
00187        PCE_IN_IF = (1 << 16),
00188        PCE_IN_ELSE = (1 << 17),
00189        PCE_IN_E = (1 << 18),
00190        PCE_IN_SELECT = (1 << 19),
00191        PCE_SELECT_HAS_DEFAULT = (1 << 20),
00192        PCE_ONLY_IN_MAIN_STATEMENT = (1 << 21)
00193 };
00194 #define PCE_NEW_PARSER_CONTEXT_MODE(pcx, m) \
00195 (((pcx)->mode & PCE_CONTEXT_MODE_PERSISTENT_MASK) | (m))
00196 
00197 #define PCE_SET_PARSER_CONTEXT_MODE(pcx, m) \
00198 ((pcx)->mode | (m))
00199 
00200 #define PCE_RESET_PARSER_CONTEXT_MODE(pcx, m) \
00201 ((pcx)->mode & (~(m)))
00202 
00203 #define PCE_ADD_CODE(PCX, PCODE) \
00204 (((PCODE)->pnext = (PCX)->pc), ((PCX)->pc = (PCODE)), ((PCX)->idx++))
00205 
00206 
00207 /********************************************************************************
00208                          PCE error handling.
00209 *********************************************************************************/
00210 
00211 enum PCE_ERROR_CODE {
00212        PCE_ANY_ERROR = -1,
00213        PCE_SUCCESS = 0,
00214        PCE_UNKNOWN_ERROR,
00215        PCE_MEMORY_ERROR,
00216        PCE_LITERAL_OVERFLOW,
00217        PCE_DEC_NUMBER_ERROR,
00218        PCE_HEX_NUMBER_ERROR,
00219        PCE_CHAR_LITERAL_ERROR,
00220        PCE_MTEXT_LITERAL_ERROR,
00221        PCE_NOT_VARIABLE_ERROR,
00222        PCE_NOT_FUNCTION_ERROR,
00223        PCE_NOT_EXCEPTION_ERROR,
00224        PCE_LABEL_NOT_DEFINED_ERROR,
00225 
00226        PCE_PARSE_NOT_LITERAL,
00227        PCE_PARSE_SYNTAX_ERROR,
00228        PCE_PARSE_UNKNOWN_SYMBOL_ERROR,
00229        PCE_PARSE_INVALID_SYMBOL_ERROR,
00230        PCE_PARSE_RETURN_IN_DEFUN_ERROR,
00231 
00232        PCE_TOO_FEW_ARGUMENTS_ERROR,
00233        PCE_WRONG_TYPE_ARGUMENT_ERROR,
00234        PCE_VARIABLE_CONSTANT_ERROR,
00235        PCE_OUT_OF_RANGE_ERROR,
00236        PCE_OVER_EVAL_DEPTH_ERROR,
00237 
00238        PCE_DEFVAR_DONE_ERROR,
00239        PCE_DEFVAR_NIL_ERROR,
00240 
00241        PCE_RETURN_JMP_ERROR,
00242        PCE_WAIT_NEXT_EVENT_ERROR,
00243 
00244        PCE_NO_MORE_ARG_ERROR
00245 };
00246 static void
00247 PCE_set_error(
00248     EIMIL_data *ped,
00249     enum PCE_ERROR_CODE code
00250 )
00251 {
00252     switch (code) {
00253       case PCE_LITERAL_OVERFLOW:
00254        EIMIL_set_error_pt(ped, NULL, "Overflow in the literal.");
00255        return;
00256       case PCE_DEC_NUMBER_ERROR:
00257        EIMIL_set_error_pt(ped, NULL, "Syntax error in the decimal number.");
00258        break;
00259       case PCE_HEX_NUMBER_ERROR:
00260        EIMIL_set_error_pt(ped, NULL, "Syntax error in the hexadecimal number.");
00261        break;
00262       case PCE_CHAR_LITERAL_ERROR:
00263        EIMIL_set_error_pt(ped, NULL, "Syntax error in the char literal.");
00264        break;
00265       case PCE_MTEXT_LITERAL_ERROR:
00266        EIMIL_set_error_pt(ped, NULL, "Syntax error in the mtext literal.");
00267        break;
00268       case PCE_TOO_FEW_ARGUMENTS_ERROR:
00269        EIMIL_set_error_pt(ped, NULL, "Too few arguments.");
00270        return;
00271       case PCE_DEFVAR_DONE_ERROR:
00272        EIMIL_set_error_pt(ped, NULL, "Initiali value must be only one in defvar.");
00273        return;
00274       case PCE_DEFVAR_NIL_ERROR:
00275        EIMIL_set_error_pt(ped, NULL, "The variable in defvar must be initialized to nil.");
00276        return;
00277       case PCE_PARSE_UNKNOWN_SYMBOL_ERROR:
00278        EIMIL_set_error_pt(ped, NULL, "Unknown symbol.");
00279        return;
00280       case PCE_PARSE_RETURN_IN_DEFUN_ERROR:
00281        EIMIL_set_error_pt(ped, NULL, "`return' must be in `defun'.");
00282        return;
00283       case PCE_NOT_VARIABLE_ERROR:
00284        EIMIL_set_error_pt(ped, NULL, "It is not a variable.");
00285        return;
00286       case PCE_NOT_FUNCTION_ERROR:
00287        EIMIL_set_error_pt(ped, NULL, "It is not a function.");
00288        return;
00289       case PCE_NOT_EXCEPTION_ERROR:
00290        EIMIL_set_error_pt(ped, NULL, "It is not an exception.");
00291        return;
00292       default:
00293        EIMIL_set_error_pt(ped, NULL, "PCE internal error (parser).");
00294     }
00295 
00296     return;
00297 }
00298 
00299 /********************************************************************************
00300                          PCE document template
00301 *********************************************************************************/
00302 
00303 static const UTF8* PCE_classname = "com.sun.iiim.pce1.s1";
00304 static const UTF8* PCE_xmlns_uri = "http://www.OpenI18N.org/EIMIL/NS/PCE/1.0";
00305 
00306 #define DECLARE_PARSER_METHOD(name) \
00307 static int PCE_##name##_parser( \
00308     EIMIL_data *ped, \
00309     EIMIL_attrs *patr, \
00310     enum EIMIL_TAG_TYPE type, \
00311     UTF8 *pchars, \
00312     void **pprivate \
00313 )
00314 #define DEFINE_PARSER_METHOD(name) DECLARE_PARSER_METHOD(name)
00315 
00316 static int
00317 PCE_generic_inst_parser(
00318     EIMIL_data *ped,
00319     EIMIL_attrs *patr,
00320     enum EIMIL_TAG_TYPE type,
00321     UTF8 *pchars,
00322     void **pprivate
00323 );
00324 
00325 /*
00326   instrunction element template.
00327  */
00328 
00329 #define PCE_noarg_option (EIMIL_element_EMPTY | EIMIL_element_multiple)
00330 #define PCE_arg_option (EIMIL_element_multiple | EIMIL_allow_PCDATA | EIMIL_PCDATA_QUOTED_TOKEN)
00331 
00332 
00333 #define DEFINE_SINST_TEMPLATE_1(name, kind, type, mode, arg1) \
00334 static PCE_inst_template \
00335 PCE_##name##_inst_template = {kind, NULL, type, mode, {arg1}}
00336 
00337 #define DEFINE_SINST_TEMPLATE_0(name, kind, type, mode) \
00338   DEFINE_SINST_TEMPLATE_1(name, kind, type, mode, 0)
00339 
00340 #define DEFINE_INST_TEMPLATE_5(name, type, mode, arg1, arg2, arg3, arg4, arg5) \
00341 static PCE_inst_template \
00342 PCE_##name##_inst_template = {PCE_CODE_INST, PCE_##name##_exec, type, mode, \
00343                               {arg1, arg2, arg3, arg4, arg5}}
00344 #define DEFINE_INST_TEMPLATE_4(name, type, mode, arg1, arg2, arg3, arg4) \
00345   DEFINE_INST_TEMPLATE_5(name, type, mode, arg1, arg2, arg3, arg4, 0)
00346 #define DEFINE_INST_TEMPLATE_3(name, type, mode, arg1, arg2, arg3) \
00347   DEFINE_INST_TEMPLATE_5(name, type, mode, arg1, arg2, arg3, 0, 0)
00348 #define DEFINE_INST_TEMPLATE_2(name, type, mode, arg1, arg2) \
00349   DEFINE_INST_TEMPLATE_5(name, type, mode, arg1, arg2, 0, 0, 0)
00350 #define DEFINE_INST_TEMPLATE_1(name, type, mode, arg1) \
00351   DEFINE_INST_TEMPLATE_5(name, type, mode, arg1, 0, 0, 0, 0)
00352 #define DEFINE_INST_TEMPLATE_0(name, type, mode) \
00353   DEFINE_INST_TEMPLATE_5(name, type, mode, 0, 0, 0, 0, 0)
00354 
00355 #define INST_ELEMENT_TEMPLATE(name, strname) \
00356 {(strname), PCE_generic_inst_parser, NULL, \
00357  PCE_arg_option, PCE_statement_template, \
00358  &PCE_##name##_inst_template}
00359 
00360 #define INST_ELEMENT_TEMPLATE_NOARG(name, strname) \
00361 {(strname), PCE_generic_inst_parser, NULL, \
00362  PCE_noarg_option, NULL, \
00363  &PCE_##name##_inst_template}
00364 
00365 #define INST_ELEMENT_TEMPLATE_OPTION(name, strname, option) \
00366 {(strname), PCE_generic_inst_parser, NULL, \
00367  (option), PCE_statement_template, \
00368  &PCE_##name##_inst_template}
00369 
00370 #define DECLARE_EXEC_METHOD(name) \
00371 static EIMIL_value* PCE_##name##_exec( \
00372     PCE_context *pctx \
00373 )
00374 #define DEFINE_EXEC_METHOD(name) DECLARE_EXEC_METHOD(name)
00375 
00376 DECLARE_PARSER_METHOD(PCE);
00377 
00378 DECLARE_PARSER_METHOD(mnemonic);
00379 DECLARE_PARSER_METHOD(pattern);
00380 DECLARE_PARSER_METHOD(key);
00381 DECLARE_PARSER_METHOD(defvar);
00382 DECLARE_PARSER_METHOD(defun);
00383 DEFINE_SINST_TEMPLATE_1(defun, PCE_CODE_DEFUN, EIMIL_TYPE_NONE, 0,
00384                      EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1);
00385 DECLARE_PARSER_METHOD(deftable);
00386 DECLARE_PARSER_METHOD(defkeymap);
00387 DECLARE_PARSER_METHOD(defpattern);
00388 DECLARE_PARSER_METHOD(main);
00389 DEFINE_SINST_TEMPLATE_1(main, PCE_CODE_MAIN, EIMIL_TYPE_NONE, 0,
00390                      EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1);
00391 
00392 DECLARE_PARSER_METHOD(while);
00393 DECLARE_PARSER_METHOD(go);
00394 DECLARE_PARSER_METHOD(label);
00395 DECLARE_PARSER_METHOD(undo);
00396 DECLARE_EXEC_METHOD(undo);
00397 DEFINE_INST_TEMPLATE_0(undo, EIMIL_TYPE_NONE, 0);
00398 DECLARE_PARSER_METHOD(mark_undo);
00399 DECLARE_EXEC_METHOD(mark_undo);
00400 DEFINE_INST_TEMPLATE_0(mark_undo, EIMIL_TYPE_NONE, 0);
00401 DECLARE_PARSER_METHOD(try);
00402 DECLARE_EXEC_METHOD(try);
00403 DEFINE_INST_TEMPLATE_1(try, EIMIL_TYPE_NONE, 0,
00404                      EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1);
00405 DECLARE_PARSER_METHOD(catch);
00406 DECLARE_EXEC_METHOD(catch);
00407 DEFINE_INST_TEMPLATE_1(catch, EIMIL_TYPE_NONE, 0,
00408                      EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1);
00409 DECLARE_PARSER_METHOD(throw);
00410 DECLARE_EXEC_METHOD(throw);
00411 DEFINE_INST_TEMPLATE_0(throw, EIMIL_TYPE_NONE, 0);
00412 DECLARE_PARSER_METHOD(if);
00413 DECLARE_PARSER_METHOD(else);
00414 
00415 DECLARE_PARSER_METHOD(keycase);
00416 DECLARE_EXEC_METHOD(keycase);
00417 DEFINE_INST_TEMPLATE_1(keycase, EIMIL_TYPE_NONE, 0,
00418                      EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1);
00419 DECLARE_PARSER_METHOD(keymap);
00420 DECLARE_EXEC_METHOD(keymap);
00421 DEFINE_INST_TEMPLATE_1(keymap, EIMIL_TYPE_NONE, 0,
00422                      EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1);
00423 
00424 DECLARE_PARSER_METHOD(case);
00425 DECLARE_PARSER_METHOD(default);
00426 DECLARE_PARSER_METHOD(select);
00427 
00428 DECLARE_EXEC_METHOD(toggle_preedit);
00429 DEFINE_INST_TEMPLATE_1(toggle_preedit, EIMIL_TYPE_BOOL, 0, EIMIL_TYPE_BOOL);
00430 DECLARE_EXEC_METHOD(toggle_lookup_choice);
00431 DEFINE_INST_TEMPLATE_1(toggle_lookup_choice, EIMIL_TYPE_BOOL, 0, EIMIL_TYPE_BOOL);
00432 DECLARE_EXEC_METHOD(keyeventp);
00433 DEFINE_INST_TEMPLATE_1(keyeventp, EIMIL_TYPE_BOOL, 0, EIMIL_TYPE_EVENT);
00434 
00435 DECLARE_EXEC_METHOD(or);
00436 DEFINE_INST_TEMPLATE_1(or, EIMIL_TYPE_BOOL, 0,
00437                      EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1);
00438 DECLARE_EXEC_METHOD(and);
00439 DEFINE_INST_TEMPLATE_1(and, EIMIL_TYPE_BOOL, 0,
00440                      EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1);
00441 DECLARE_EXEC_METHOD(not);
00442 DEFINE_INST_TEMPLATE_1(not, EIMIL_TYPE_BOOL, 0, EIMIL_TYPE_ANY);
00443 DECLARE_EXEC_METHOD(gt);
00444 DEFINE_INST_TEMPLATE_2(gt, EIMIL_TYPE_BOOL, 0,
00445                      EIMIL_TYPE_NUMBER, EIMIL_TYPE_NUMBER);
00446 DECLARE_EXEC_METHOD(lt);
00447 DEFINE_INST_TEMPLATE_2(lt, EIMIL_TYPE_BOOL, 0,
00448                      EIMIL_TYPE_NUMBER, EIMIL_TYPE_NUMBER);
00449 DECLARE_EXEC_METHOD(le);
00450 DEFINE_INST_TEMPLATE_2(le, EIMIL_TYPE_BOOL, 0,
00451                      EIMIL_TYPE_NUMBER, EIMIL_TYPE_NUMBER);
00452 DECLARE_EXEC_METHOD(ge);
00453 DEFINE_INST_TEMPLATE_2(ge, EIMIL_TYPE_BOOL, 0,
00454                      EIMIL_TYPE_NUMBER, EIMIL_TYPE_NUMBER);
00455 DECLARE_EXEC_METHOD(eql);
00456 DEFINE_INST_TEMPLATE_2(eql, EIMIL_TYPE_BOOL, 0,
00457                      EIMIL_TYPE_NUMBER, EIMIL_TYPE_NUMBER);
00458 
00459 DECLARE_EXEC_METHOD(propval);
00460 DEFINE_INST_TEMPLATE_2(propval, EIMIL_TYPE_ANY, 0,
00461                      EIMIL_TYPE_PROP, EIMIL_TYPE_NUMBER);
00462 
00463 DECLARE_EXEC_METHOD(propsize);
00464 DEFINE_INST_TEMPLATE_1(propsize, EIMIL_TYPE_NUMBER, 0, EIMIL_TYPE_PROP);
00465 DECLARE_EXEC_METHOD(propmbeg);
00466 DEFINE_INST_TEMPLATE_1(propmbeg, EIMIL_TYPE_NUMBER, 0, EIMIL_TYPE_PROP);
00467 DECLARE_EXEC_METHOD(propmend);
00468 DEFINE_INST_TEMPLATE_1(propmend, EIMIL_TYPE_NUMBER, 0, EIMIL_TYPE_PROP);
00469 DECLARE_EXEC_METHOD(evval);
00470 DEFINE_INST_TEMPLATE_1(evval, EIMIL_TYPE_NUMBER, 0, EIMIL_TYPE_EVENT);
00471 DECLARE_EXEC_METHOD(evmod);
00472 DEFINE_INST_TEMPLATE_1(evmod, EIMIL_TYPE_NUMBER, 0, EIMIL_TYPE_EVENT);
00473 DECLARE_EXEC_METHOD(strlen);
00474 DEFINE_INST_TEMPLATE_1(strlen, EIMIL_TYPE_NUMBER, 0, EIMIL_TYPE_MTEXT);
00475 DECLARE_EXEC_METHOD(strcmp);
00476 DEFINE_INST_TEMPLATE_2(strcmp, EIMIL_TYPE_NUMBER, 0,
00477                      EIMIL_TYPE_MTEXT, EIMIL_TYPE_MTEXT);
00478 DECLARE_EXEC_METHOD(add);
00479 DEFINE_INST_TEMPLATE_1(add, EIMIL_TYPE_NUMBER, 0,
00480                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION1);
00481 DECLARE_EXEC_METHOD(sub);
00482 DEFINE_INST_TEMPLATE_1(sub, EIMIL_TYPE_NUMBER, 0,
00483                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION1);
00484 DECLARE_EXEC_METHOD(mul);
00485 DEFINE_INST_TEMPLATE_1(mul, EIMIL_TYPE_NUMBER, 0,
00486                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION1);
00487 DECLARE_EXEC_METHOD(div);
00488 DEFINE_INST_TEMPLATE_1(div, EIMIL_TYPE_NUMBER, 0,
00489                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION1);
00490 DECLARE_EXEC_METHOD(mod);
00491 DEFINE_INST_TEMPLATE_1(mod, EIMIL_TYPE_NUMBER, 0,
00492                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION1);
00493 DECLARE_EXEC_METHOD(bor);
00494 DEFINE_INST_TEMPLATE_1(bor, EIMIL_TYPE_NUMBER, 0,
00495                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION1);
00496 DECLARE_EXEC_METHOD(band);
00497 DEFINE_INST_TEMPLATE_1(band, EIMIL_TYPE_NUMBER, 0,
00498                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION1);
00499 DECLARE_EXEC_METHOD(bxor);
00500 DEFINE_INST_TEMPLATE_1(bxor, EIMIL_TYPE_NUMBER, 0,
00501                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION1);
00502 DECLARE_EXEC_METHOD(UCSval);
00503 DEFINE_INST_TEMPLATE_1(UCSval, EIMIL_TYPE_NUMBER, 0, EIMIL_TYPE_CHAR);
00504 
00505 DECLARE_EXEC_METHOD(propadd);
00506 DEFINE_INST_TEMPLATE_2(propadd, EIMIL_TYPE_PROP, 0,
00507                      EIMIL_TYPE_PROP, EIMIL_TYPE_ANY);
00508 DECLARE_EXEC_METHOD(propcopy);
00509 DEFINE_INST_TEMPLATE_1(propcopy, EIMIL_TYPE_PROP, 0, EIMIL_TYPE_PROP);
00510 DECLARE_EXEC_METHOD(evchar);
00511 DEFINE_INST_TEMPLATE_1(evchar, EIMIL_TYPE_CHAR, 0, EIMIL_TYPE_EVENT);
00512 DECLARE_EXEC_METHOD(strref);
00513 DEFINE_INST_TEMPLATE_2(strref, EIMIL_TYPE_CHAR, 0,
00514                      EIMIL_TYPE_MTEXT, EIMIL_TYPE_NUMBER);
00515 DECLARE_EXEC_METHOD(makechar);
00516 DEFINE_INST_TEMPLATE_1(makechar, EIMIL_TYPE_CHAR, 0, EIMIL_TYPE_NUMBER);
00517 DECLARE_EXEC_METHOD(evtype);
00518 DEFINE_INST_TEMPLATE_1(evtype, EIMIL_TYPE_MTEXT, 0, EIMIL_TYPE_EVENT);
00519 DECLARE_EXEC_METHOD(evmtext);
00520 DEFINE_INST_TEMPLATE_1(evmtext, EIMIL_TYPE_MTEXT, 0, EIMIL_TYPE_EVENT);
00521 DECLARE_EXEC_METHOD(concat);
00522 DEFINE_INST_TEMPLATE_1(concat, EIMIL_TYPE_MTEXT, 0,
00523                      EIMIL_TYPE_CHAR | EIMIL_TYPE_MTEXT | EIMIL_TYPE_OPTION1);
00524 DECLARE_EXEC_METHOD(substr);
00525 DEFINE_INST_TEMPLATE_3(substr, EIMIL_TYPE_MTEXT, 0,
00526                      EIMIL_TYPE_MTEXT, EIMIL_TYPE_NUMBER,
00527                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_OPTION2);
00528 DECLARE_EXEC_METHOD(next);
00529 DEFINE_INST_TEMPLATE_2(next, EIMIL_TYPE_NONE, PCE_ONLY_IN_MAIN_STATEMENT,
00530                      EIMIL_TYPE_EVENT, EIMIL_TYPE_EVENT | EIMIL_TYPE_OPTION2);
00531 DECLARE_EXEC_METHOD(makeev);
00532 DEFINE_INST_TEMPLATE_5(makeev, EIMIL_TYPE_EVENT, 0,
00533                      EIMIL_TYPE_MTEXT,
00534                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_NIL,
00535                      EIMIL_TYPE_NUMBER | EIMIL_TYPE_NIL,
00536                      EIMIL_TYPE_CHAR | EIMIL_TYPE_NIL,
00537                      EIMIL_TYPE_MTEXT | EIMIL_TYPE_NIL);
00538 DECLARE_EXEC_METHOD(commit);
00539 DEFINE_INST_TEMPLATE_1(commit, EIMIL_TYPE_NONE, 0, EIMIL_TYPE_MTEXT);
00540 DECLARE_EXEC_METHOD(unroll);
00541 DEFINE_INST_TEMPLATE_1(unroll, EIMIL_TYPE_NONE, 0, EIMIL_TYPE_EVENT);
00542 DECLARE_EXEC_METHOD(propdel);
00543 DEFINE_INST_TEMPLATE_2(propdel, EIMIL_TYPE_NONE, 0,
00544                      EIMIL_TYPE_PROP, EIMIL_TYPE_NUMBER);
00545 DECLARE_EXEC_METHOD(addmprop);
00546 DEFINE_INST_TEMPLATE_4(addmprop, EIMIL_TYPE_NONE, 0,
00547                      EIMIL_TYPE_MTEXT, EIMIL_TYPE_PROP,
00548                      EIMIL_TYPE_NUMBER, EIMIL_TYPE_NUMBER);
00549 DECLARE_EXEC_METHOD(delmprop);
00550 DEFINE_INST_TEMPLATE_1(delmprop, EIMIL_TYPE_NONE, 0, EIMIL_TYPE_PROP);
00551 DECLARE_EXEC_METHOD(setmprop);
00552 DEFINE_INST_TEMPLATE_4(setmprop, EIMIL_TYPE_NONE, 0,
00553                      EIMIL_TYPE_MTEXT, EIMIL_TYPE_PROP,
00554                      EIMIL_TYPE_NUMBER, EIMIL_TYPE_NUMBER);
00555 
00556 DECLARE_PARSER_METHOD(return);
00557 DECLARE_EXEC_METHOD(return);
00558 DEFINE_INST_TEMPLATE_1(return, EIMIL_TYPE_NONE, 0, EIMIL_TYPE_ANY);
00559 
00560 DECLARE_PARSER_METHOD(tblkeymaxsize);
00561 DECLARE_EXEC_METHOD(tblkeymaxsize);
00562 DECLARE_PARSER_METHOD(tblvalmaxsize);
00563 DECLARE_EXEC_METHOD(tblvalmaxsize);
00564 DECLARE_PARSER_METHOD(tblref);
00565 DECLARE_EXEC_METHOD(tblref);
00566 
00567 DECLARE_PARSER_METHOD(makeprop);
00568 DECLARE_EXEC_METHOD(makeprop);
00569 DECLARE_PARSER_METHOD(getmprop);
00570 DECLARE_EXEC_METHOD(getmprop);
00571 DECLARE_PARSER_METHOD(findmprop);
00572 DECLARE_EXEC_METHOD(findmprop);
00573 DECLARE_PARSER_METHOD(interact);
00574 DECLARE_EXEC_METHOD(interact);
00575 
00576 DECLARE_PARSER_METHOD(match);
00577 DECLARE_EXEC_METHOD(match);
00578 
00579 DECLARE_PARSER_METHOD(forward);
00580 DECLARE_EXEC_METHOD(forward);
00581 DECLARE_PARSER_METHOD(send);
00582 DECLARE_EXEC_METHOD(send);
00583 
00584 DECLARE_PARSER_METHOD(set);
00585 DECLARE_EXEC_METHOD(set);
00586 
00587 DECLARE_PARSER_METHOD(e);
00588 DECLARE_EXEC_METHOD(e);
00589 
00590 #define EIMIL_TEMPLATE_NUM(e) (sizeof(e) / sizeof(EIMIL_element_template))
00591 
00592 static EIMIL_element_template
00593 PCE_statement_template[];
00594 
00595 /* */
00596 static EIMIL_element_template
00597 PCE_if_else_template[] = {
00598        {"else", PCE_else_parser, NULL, 
00599         EIMIL_element_0or1 | EIMIL_element_lock_template
00600         | EIMIL_allow_PCDATA | EIMIL_PCDATA_QUOTED_TOKEN,
00601         PCE_statement_template, NULL},
00602        {NULL, NULL, NULL, 0, NULL, NULL}
00603 };
00604 static EIMIL_element_template
00605 PCE_if_full_template[];
00606 
00607 static EIMIL_attr_template
00608 PCE_attr_keycase[] = {{"code", EIMIL_attr_IMPLIED, NULL},
00609                     {"char", EIMIL_attr_IMPLIED, NULL},
00610                     {"mod", EIMIL_attr_IMPLIED, ""},
00611                     {NULL, 0, NULL}};
00612 
00613 static EIMIL_attr_template
00614 PCE_attr_keymap[] = {{"k", EIMIL_attr_REQUIRED, NULL},
00615                    {NULL, 0, NULL}};
00616 
00617 /* */
00618 static EIMIL_element_template
00619 PCE_select_template[] = {
00620        {"case", PCE_case_parser, NULL, 
00621         PCE_arg_option, PCE_statement_template, NULL},
00622        {"default", PCE_default_parser, NULL, 
00623         EIMIL_element_0or1 | EIMIL_element_lock_template
00624         | EIMIL_allow_PCDATA | EIMIL_PCDATA_QUOTED_TOKEN,
00625         PCE_statement_template, NULL},
00626        {NULL, NULL, NULL, 0, NULL}
00627 };
00628 
00629 /* */
00630 static EIMIL_element_template
00631 PCE_try_catch_template[] = {
00632        INST_ELEMENT_TEMPLATE_OPTION(catch, "catch",
00633                                  PCE_arg_option
00634                                  | EIMIL_element_lock_template),
00635        {NULL, NULL, NULL, 0, NULL}
00636 };
00637 
00638 static EIMIL_element_template
00639 PCE_try_full_template[];
00640 
00641 static EIMIL_attr_template
00642 PCE_attr_go[] = {{"to", EIMIL_attr_REQUIRED, NULL},
00643                {NULL, 0, NULL}};
00644 
00645 static EIMIL_attr_template
00646 PCE_attr_label[] = {{"name", EIMIL_attr_REQUIRED, NULL},
00647                   {NULL, 0, NULL}};
00648 
00649 static EIMIL_attr_template
00650 PCE_attr_catch[] = {{"exc", EIMIL_attr_REQUIRED, NULL},
00651                   {NULL, 0, NULL}};
00652 
00653 static EIMIL_attr_template
00654 PCE_attr_throw[] = {{"exc", EIMIL_attr_REQUIRED, NULL},
00655                   {NULL, 0, NULL}};
00656 
00657 static EIMIL_attr_template
00658 PCE_attr_interact[] = {{"op", EIMIL_attr_REQUIRED, NULL},
00659                      {NULL, 0, NULL}};
00660 
00661 static EIMIL_attr_template
00662 PCE_attr_next[] = {{"remove", EIMIL_attr_NORMAL, "true"},
00663                  {NULL, 0, NULL}};
00664 
00665 static EIMIL_attr_template
00666 PCE_attr_forward[] = {{"to", EIMIL_attr_IMPLIED, NULL},
00667                     {NULL, 0, NULL}};
00668 
00669 static EIMIL_attr_template
00670 PCE_attr_send[] = {{"to", EIMIL_attr_IMPLIED, NULL},
00671                  {NULL, 0, NULL}};
00672 
00673 static EIMIL_attr_template
00674 PCE_attr_e[] = {{"f", EIMIL_attr_REQUIRED, NULL},
00675               {NULL, 0, NULL}};
00676 
00677 static EIMIL_attr_template
00678 PCE_attr_set[] = {{"v", EIMIL_attr_REQUIRED, NULL},
00679                 {NULL, 0, NULL}};
00680 
00681 static EIMIL_attr_template
00682 PCE_attr_match[] = {{"p", EIMIL_attr_REQUIRED, NULL},
00683                   {NULL, 0, NULL}};
00684 
00685 static EIMIL_attr_template
00686 PCE_attr_tblref[] = {{"t", EIMIL_attr_REQUIRED, NULL},
00687                    {NULL, 0, NULL}};
00688 
00689 static EIMIL_attr_template
00690 PCE_attr_tblkeymaxsize[] = {{"t", EIMIL_attr_REQUIRED, NULL},
00691                          {NULL, 0, NULL}};
00692 
00693 static EIMIL_attr_template
00694 PCE_attr_tblvalmaxsize[] = {{"t", EIMIL_attr_REQUIRED, NULL},
00695                          {NULL, 0, NULL}};
00696 
00697 static EIMIL_attr_template
00698 PCE_attr_makeprop[] = {{"p", EIMIL_attr_REQUIRED, NULL},
00699                      {NULL, 0, NULL}};
00700 
00701 static EIMIL_attr_template
00702 PCE_attr_propval[] = {{"p", EIMIL_attr_REQUIRED, NULL},
00703                     {NULL, 0, NULL}};
00704 
00705 static EIMIL_attr_template
00706 PCE_attr_getmprop[] = {{"p", EIMIL_attr_REQUIRED, NULL},
00707                      {NULL, 0, NULL}};
00708 
00709 static EIMIL_attr_template
00710 PCE_attr_findmprop[] = {{"p", EIMIL_attr_REQUIRED, NULL},
00711                      {NULL, 0, NULL}};
00712 
00713 static EIMIL_element_template
00714 PCE_statement_template[] = {
00715        /* Flow control */
00716        {"while", PCE_while_parser, NULL,
00717         PCE_arg_option, PCE_statement_template, NULL},
00718        /* undo */
00719        INST_ELEMENT_TEMPLATE_NOARG(undo, "undo"),
00720        INST_ELEMENT_TEMPLATE_NOARG(mark_undo, "mark-undo"),
00721        /* STH */
00722        {"try", PCE_try_parser, NULL,
00723         PCE_arg_option, PCE_try_full_template,
00724         &PCE_try_inst_template},
00725        /* flow */
00726        {"if", PCE_if_parser, NULL,
00727         PCE_arg_option, PCE_if_full_template, NULL},
00728        {"select", PCE_select_parser, NULL,
00729         EIMIL_element_multiple, PCE_select_template, NULL},
00730 
00731        /* BOOL */
00732        INST_ELEMENT_TEMPLATE(toggle_preedit, "toggle-preedit"),
00733        INST_ELEMENT_TEMPLATE(toggle_lookup_choice, "toggle-lookup-choice"),
00734        INST_ELEMENT_TEMPLATE(keyeventp, "keyeventp"),
00735        INST_ELEMENT_TEMPLATE(or, "or"),
00736        INST_ELEMENT_TEMPLATE(and, "and"),
00737        INST_ELEMENT_TEMPLATE(not, "not"),
00738        INST_ELEMENT_TEMPLATE(gt, "gt"),
00739        INST_ELEMENT_TEMPLATE(lt, "lt"),
00740        INST_ELEMENT_TEMPLATE(le, "le"),
00741        INST_ELEMENT_TEMPLATE(ge, "ge"),
00742        INST_ELEMENT_TEMPLATE(eql, "eql"),
00743 
00744        INST_ELEMENT_TEMPLATE(propsize, "propsize"),
00745        INST_ELEMENT_TEMPLATE(propmbeg, "propmbeg"),
00746        INST_ELEMENT_TEMPLATE(propmend, "propmend"),
00747        INST_ELEMENT_TEMPLATE(evval, "evval"),
00748        INST_ELEMENT_TEMPLATE(evmod, "evmod"),
00749        INST_ELEMENT_TEMPLATE(strlen, "strlen"),
00750        INST_ELEMENT_TEMPLATE(strcmp, "strcmp"),
00751        INST_ELEMENT_TEMPLATE(add, "add"),
00752        INST_ELEMENT_TEMPLATE(sub, "sub"),
00753        INST_ELEMENT_TEMPLATE(mul, "mul"),
00754        INST_ELEMENT_TEMPLATE(div, "div"),
00755        INST_ELEMENT_TEMPLATE(mod, "mod"),
00756        INST_ELEMENT_TEMPLATE(bor, "bor"),
00757        INST_ELEMENT_TEMPLATE(band, "band"),
00758        INST_ELEMENT_TEMPLATE(bxor, "bxor"),
00759        INST_ELEMENT_TEMPLATE(UCSval, "UCSval"),
00760        INST_ELEMENT_TEMPLATE(propadd, "propadd"),
00761        INST_ELEMENT_TEMPLATE(propcopy, "propcopy"),
00762        INST_ELEMENT_TEMPLATE(evchar, "evchar"),
00763        INST_ELEMENT_TEMPLATE(makechar, "makechar"),
00764        INST_ELEMENT_TEMPLATE(strref, "strref"),
00765        INST_ELEMENT_TEMPLATE(commit, "commit"),
00766        INST_ELEMENT_TEMPLATE(next, "next"),
00767        INST_ELEMENT_TEMPLATE(evtype, "evtype"),
00768        INST_ELEMENT_TEMPLATE(evmtext, "evmtext"),
00769        INST_ELEMENT_TEMPLATE(commit, "commit"),
00770        INST_ELEMENT_TEMPLATE(concat, "concat"),
00771        INST_ELEMENT_TEMPLATE(substr, "substr"),
00772        INST_ELEMENT_TEMPLATE(makeev, "makeev"),
00773        INST_ELEMENT_TEMPLATE(unroll, "unroll"),
00774        INST_ELEMENT_TEMPLATE(propdel, "propdel"),
00775        INST_ELEMENT_TEMPLATE(addmprop, "addmprop"),
00776        INST_ELEMENT_TEMPLATE(addmprop, "delmprop"),
00777        INST_ELEMENT_TEMPLATE(addmprop, "setmprop"),
00778 
00779        /* <propval> PROP IDX </propval> retrives
00780           a value of property.  */
00781        INST_ELEMENT_TEMPLATE(propval, "propval"),
00782 
00783        /* <return> </return> returns a value of function. */
00784        {"return", PCE_return_parser, NULL,
00785         PCE_arg_option, NULL,
00786         &PCE_return_inst_template},
00787 
00788        /* exc(exception name) attribute */
00789        {"throw", PCE_throw_parser, NULL,
00790         PCE_noarg_option, NULL,
00791         &PCE_throw_inst_template},
00792        /* to(label name) attribute */
00793        {"go", PCE_go_parser, PCE_attr_go,
00794         PCE_noarg_option, NULL, NULL},
00795        /* name(label name) attribute */
00796        {"label", PCE_label_parser, PCE_attr_label,
00797         PCE_noarg_option, NULL, NULL},
00798        /* t(table name) attribute */
00799        {"tblkeymaxsize", PCE_tblkeymaxsize_parser, NULL,
00800         EIMIL_element_EMPTY | EIMIL_element_multiple, NULL},
00801        {"tblvalmaxsize", PCE_tblvalmaxsize_parser, NULL,
00802         EIMIL_element_EMPTY | EIMIL_element_multiple, NULL},
00803        {"tblref", PCE_tblref_parser, NULL,
00804         PCE_arg_option, PCE_statement_template},
00805 
00806        /* p(property name) attribute */
00807        {"makeprop", PCE_makeprop_parser, NULL,
00808         EIMIL_element_EMPTY| EIMIL_element_multiple, NULL},
00809        {"getmprop", PCE_getmprop_parser, NULL,
00810         PCE_arg_option, PCE_statement_template},
00811        {"findmprop", PCE_findmprop_parser, NULL,
00812         PCE_arg_option, PCE_statement_template},
00813 
00814        /* op(operation name) attribute */
00815        {"interact", PCE_interact_parser, NULL,
00816         PCE_noarg_option, NULL},
00817 
00818        /* p(pattern name) attribute */
00819        {"match", PCE_match_parser, NULL,
00820         PCE_arg_option, PCE_statement_template},
00821 
00822        /* to(EIMIL name) attribute */
00823        {"forward", PCE_forward_parser, PCE_attr_forward,
00824         PCE_noarg_option, NULL},
00825        {"send", PCE_send_parser, PCE_attr_send,
00826         PCE_arg_option, PCE_statement_template},
00827 
00828        /* v(variable name) attribute */
00829        {"set", PCE_set_parser, NULL,
00830         PCE_arg_option, PCE_statement_template},
00831        /* f(function name) attribute */
00832        {"e", PCE_e_parser, NULL,
00833         PCE_arg_option, PCE_statement_template},
00834 
00835        /* ends here */
00836        {NULL, NULL, NULL, 0, NULL}
00837 };
00838 
00839 static EIMIL_element_template
00840 PCE_if_full_template[EIMIL_TEMPLATE_NUM(PCE_statement_template)
00841                    + EIMIL_TEMPLATE_NUM(PCE_if_else_template) - 1];
00842 static EIMIL_element_template
00843 PCE_try_full_template[EIMIL_TEMPLATE_NUM(PCE_statement_template)
00844                    + EIMIL_TEMPLATE_NUM(PCE_try_catch_template) - 1];
00845 
00846 static EIMIL_attr_template
00847 PCE_attr_defvar[] = {{"name", EIMIL_attr_REQUIRED, NULL},
00848                    {"type", EIMIL_attr_REQUIRED, NULL},
00849                    {"val", EIMIL_attr_NORMAL, "nil"},
00850                    {NULL, 0, NULL}};
00851 
00852 static EIMIL_attr_template
00853 PCE_attr_defun[] = {{"name", EIMIL_attr_REQUIRED, NULL},
00854                   {"type", EIMIL_attr_REQUIRED, NULL},
00855                   {"args", EIMIL_attr_NORMAL, ""},
00856                   {NULL, 0, NULL}};
00857 
00858 static EIMIL_attr_template
00859 PCE_attr_defpattern[] = {{"name", EIMIL_attr_REQUIRED, NULL},
00860                       {NULL, 0, NULL}};
00861 
00862 static EIMIL_attr_template
00863 PCE_attr_mnemonic[] = {{"c", EIMIL_attr_REQUIRED, NULL},
00864                      {NULL, 0, NULL}};
00865 
00866 static EIMIL_attr_template
00867 PCE_attr_pattern[] = {{"e", EIMIL_attr_REQUIRED, NULL},
00868                     {"v", EIMIL_attr_REQUIRED, NULL},
00869                     {NULL, 0, NULL}};
00870 
00871 static EIMIL_element_template
00872 PCE_defpattern_template[] = {
00873        {"mnemonic", PCE_mnemonic_parser, NULL,
00874         PCE_arg_option, NULL},
00875        {"pattern", PCE_pattern_parser, PCE_attr_pattern,
00876         PCE_noarg_option, NULL},
00877        {NULL, NULL, NULL, 0, NULL}
00878 };
00879 
00880 static EIMIL_attr_template
00881 PCE_attr_deftable[] = {{"name", EIMIL_attr_REQUIRED, NULL},
00882                      {"from", EIMIL_attr_REQUIRED, NULL},
00883                      {"to", EIMIL_attr_REQUIRED, NULL},
00884                      {NULL, 0, NULL}};
00885 
00886 static EIMIL_attr_template
00887 PCE_attr_key[] = {{"code", EIMIL_attr_IMPLIED, NULL},
00888                 {"char", EIMIL_attr_IMPLIED, NULL},
00889                 {"mod", EIMIL_attr_IMPLIED, NULL},
00890                 {NULL, 0, NULL}};
00891 
00892 static EIMIL_element_template
00893 PCE_defkeymap_template[] = {
00894        {"key", PCE_key_parser, NULL,
00895         PCE_arg_option, NULL},
00896        {NULL, NULL, NULL, 0, NULL}
00897 };
00898 
00899 static EIMIL_attr_template
00900 PCE_attr_defkeymap[] = {{"name", EIMIL_attr_REQUIRED, NULL},
00901                      {"to", EIMIL_attr_REQUIRED, NULL},
00902                      {NULL, 0, NULL}};
00903 
00904 static EIMIL_element_template
00905 PCE_template[] = {{"defvar", PCE_defvar_parser,
00906                  PCE_attr_defvar,
00907                  PCE_arg_option, NULL},
00908                 {"defun", PCE_defun_parser,
00909                  PCE_attr_defun,
00910                  PCE_arg_option,
00911                  PCE_statement_template, &PCE_defun_inst_template},
00912                 {"deftable", PCE_deftable_parser,
00913                  PCE_attr_deftable,
00914                  PCE_arg_option, NULL},
00915                 {"defkeymap", PCE_defkeymap_parser,
00916                  PCE_attr_defkeymap,
00917                  PCE_arg_option,
00918                  PCE_defkeymap_template},
00919                 {"defpattern", PCE_defpattern_parser,
00920                  PCE_attr_defpattern,
00921                  PCE_arg_option,
00922                  PCE_defpattern_template},
00923                 {"main", PCE_main_parser, NULL,
00924                  EIMIL_element_single | EIMIL_allow_PCDATA,
00925                  PCE_statement_template, &PCE_main_inst_template},
00926                 {NULL, NULL, NULL, 0, NULL}};
00927 
00928 EIMIL_element_template
00929 PCE_docroot[] = {{"PCE", PCE_PCE_parser, NULL,
00930                 EIMIL_element_single, PCE_template},
00931                {NULL, NULL, NULL, 0, NULL}};
00932 
00933 /********************************************************************************
00934                          PCE precompilation part
00935 *********************************************************************************/
00936 
00937 enum PCE_inst {
00938        PCE_INVALID_INST = -1,
00939        PCE_NOP = 0,
00940        PCE_WHILE,
00941        PCE_GO,
00942        PCE_LABEL,
00943        PCE_UNDO,
00944        PCE_MARK_UNDO,
00945        PCE_TRY,
00946        PCE_THROW,
00947        PCE_IF,
00948        PCE_SELECT,
00949        PCE_TOGGLE_PREEDIT,
00950        PCE_TOGGLE_LOOKUP_CHOICE,
00951        PCE_KEYEVENTP,
00952        PCE_OR,
00953        PCE_AND,
00954        PCE_NOT,
00955        PCE_GT,
00956        PCE_LT,
00957        PCE_LE,
00958        PCE_GE,
00959        PCE_EQL,
00960        PCE_TBLKEYMAXSIZE,
00961        PCE_TBLVALMAXSIZE,
00962        PCE_PROPSIZE,
00963        PCE_PROPMBEG,
00964        PCE_PROPMEND,
00965        PCE_EVVAL,
00966        PCE_EVMOD,
00967        PCE_STRLEN,
00968        PCE_STRCMP,
00969        PCE_ADD,
00970        PCE_SUB,
00971        PCE_MUL,
00972        PCE_DIV,
00973        PCE_MOD,
00974        PCE_BOR,
00975        PCE_BAND,
00976        PCE_BXOR,
00977        PCE_UCSVAL,
00978        PCE_MAKEPROP,
00979        PCE_PROPADD,
00980        PCE_PROPCOPY,
00981        PCE_GETMPROP,
00982        PCE_FINDMPROP,
00983        PCE_EVCHAR,
00984        PCE_STRREF,
00985        PCE_MAKECHAR,
00986        PCE_INTERACT,
00987        PCE_MATCH,
00988        PCE_EVTYPE,
00989        PCE_EVMTEXT,
00990        PCE_CONCAT,
00991        PCE_SUBSTR,
00992        PCE_NEXT,
00993        PCE_FORWARD,
00994        PCE_SEND,
00995        PCE_MAKEEV,
00996        PCE_COMMIT,
00997        PCE_UNROLL,
00998        PCE_PROPDEL,
00999        PCE_ADDMPROP,
01000        PCE_DELMPROP,
01001        PCE_SETMPROP,
01002        PCE_SET,
01003        PCE_E,
01004        PCE_TBLREF
01005 };
01006 
01007 static EIMIL_symbol*
01008 PCE_intern_soft(
01009     PCE_context *pctx,
01010     unsigned char *name
01011 )
01012 {
01013     EIMIL_symbol *psym;
01014 
01015     psym = EIMIL_intern_soft(pctx->pdic, name);
01016     if (!psym) {
01017        psym = EIMIL_intern_soft(pctx->ped->pdic, name);
01018     }
01019     return psym;
01020 }
01021 
01022 static EIMIL_symbol*
01023 PCE_intern_soft_for_parser(
01024     PCE_parse_context *pcx,
01025     unsigned char *name
01026 )
01027 {
01028     EIMIL_symbol *psym;
01029     PCE_context *pctx = pcx->pctx;
01030 
01031     if (pcx->pdic)
01032        psym = EIMIL_intern_soft(pcx->pdic, name);
01033     else
01034        psym = NULL;
01035     if (!psym) {
01036        psym = EIMIL_intern_soft(pctx->pdic, name);
01037        if (!psym) {
01038            psym = EIMIL_intern_soft(pctx->ped->pdic, name);
01039        }
01040     }
01041     return psym;
01042 }
01043 
01044 static EIMIL_symbol*
01045 PCE_register_symbol(
01046     PCE_context *pctx,
01047     unsigned char *name,
01048     enum EIMIL_CATEGORY cat,
01049     enum EIMIL_TYPE type
01050 )
01051 {
01052     EIMIL_symbol *psym;
01053     psym = EIMIL_intern_soft(pctx->ped->pdic, name);
01054     if (!psym) {
01055        psym = EIMIL_register_symbol(pctx->ped,
01056                                  pctx->pdic, name,
01057                                  cat, type);
01058        if (psym) return psym;
01059     }
01060     EIMIL_set_error_pt(pctx->ped, NULL,
01061                      "Duplicated symbol name:%s.", name);
01062     return NULL;
01063 }
01064 
01065 static EIMIL_symbol*
01066 PCE_get_variable(
01067     EIMIL_data *ped,
01068     PCE_parse_context *pcx,
01069     UTF8 *varname
01070 )
01071 {
01072     EIMIL_symbol *psym;
01073 
01074     psym = PCE_intern_soft_for_parser(pcx, varname);
01075     if (!psym) {
01076        PCE_set_error(ped, PCE_PARSE_UNKNOWN_SYMBOL_ERROR);
01077        return NULL;
01078     }
01079     if (psym->cat != EIMIL_CAT_VARIABLE) {
01080        PCE_set_error(ped, PCE_NOT_VARIABLE_ERROR);
01081        return NULL;
01082     }
01083     return psym;
01084 }
01085 
01086 static EIMIL_symbol*
01087 PCE_get_function(
01088     EIMIL_data *ped,
01089     PCE_parse_context *pcx,
01090     UTF8 *varname
01091 )
01092 {
01093     EIMIL_symbol *psym;
01094 
01095     psym = PCE_intern_soft_for_parser(pcx, varname);
01096     if (!psym) {
01097        PCE_set_error(ped, PCE_PARSE_UNKNOWN_SYMBOL_ERROR);
01098        return NULL;
01099     }
01100     if (psym->cat != EIMIL_CAT_FUNCTION) {
01101        PCE_set_error(ped, PCE_NOT_FUNCTION_ERROR);
01102        return NULL;
01103     }
01104     return psym;
01105 }
01106 
01107 static EIMIL_symbol*
01108 PCE_get_exception(
01109     EIMIL_data *ped,
01110     PCE_parse_context *pcx,
01111     UTF8 *varname
01112 )
01113 {
01114     EIMIL_symbol *psym;
01115 
01116     psym = PCE_intern_soft_for_parser(pcx, varname);
01117     if (!psym) {
01118        PCE_set_error(ped, PCE_PARSE_UNKNOWN_SYMBOL_ERROR);
01119        return NULL;
01120     }
01121     if (psym->cat != EIMIL_CAT_EXCEPTION) {
01122        PCE_set_error(ped, PCE_NOT_EXCEPTION_ERROR);
01123        return NULL;
01124     }
01125     return psym;
01126 }
01127 
01128 static EIMIL_symbol*
01129 PCE_get_property(
01130     EIMIL_data *ped,
01131     PCE_parse_context *pcx,
01132     UTF8 *propname
01133 )
01134 {
01135     EIMIL_symbol *psym;
01136 
01137     psym = PCE_intern_soft_for_parser(pcx, propname);
01138     if (!psym) {
01139        PCE_set_error(ped, PCE_PARSE_UNKNOWN_SYMBOL_ERROR);
01140        return NULL;
01141     }
01142     if (psym->cat != EIMIL_CAT_PROPERTY) {
01143        PCE_set_error(ped, PCE_NOT_EXCEPTION_ERROR);
01144        return NULL;
01145     }
01146     return psym;
01147 }
01148 
01149 static PCE_code*
01150 PCE_new_code_for_inst(PCE_EXEC_HANDLER h)
01151 {
01152     PCE_code *p;
01153 
01154     p = (PCE_code*) malloc(sizeof(PCE_code));
01155     if (!p) return NULL;
01156     p->type = PCE_CODE_INST;
01157     p->val.h = h;
01158     p->parg = NULL;
01159     p->pnext = NULL;
01160 
01161     return p;
01162 }
01163 
01164 static PCE_code*
01165 PCE_new_code_for_value(EIMIL_value *pv)
01166 {
01167     PCE_code *p;
01168 
01169     p = (PCE_code*) malloc(sizeof(PCE_code));
01170     if (!p) return NULL;
01171     p->type = PCE_CODE_VALUE;
01172     p->val.pv = pv;
01173     p->parg = NULL;
01174     p->pnext = NULL;
01175 
01176     return p;
01177 }
01178 
01179 static PCE_code*
01180 PCE_new_code_for_symbol(
01181     EIMIL_symbol *psym
01182 )
01183 {
01184     PCE_code *p;
01185 
01186     p = (PCE_code*) malloc(sizeof(PCE_code));
01187     if (!p) return NULL;
01188     p->type = PCE_CODE_SYMBOL;
01189     p->val.symid = psym->symbolid;
01190     p->parg = NULL;
01191     p->pnext = NULL;
01192 
01193     return p;
01194 }
01195 
01196 static PCE_code*
01197 PCE_new_code_for_function(
01198     PCE_function *pf
01199 )
01200 {
01201     PCE_code *p;
01202 
01203     p = (PCE_code*) malloc(sizeof(PCE_code));
01204     if (!p) return NULL;
01205     p->type = PCE_CODE_FUNCTION;
01206     p->val.pf = pf;
01207     p->parg = NULL;
01208     p->pnext = NULL;
01209 
01210     return p;
01211 }
01212 
01213 static PCE_code*
01214 PCE_new_code_for_etc(
01215     enum PCE_CODE_TYPE type
01216 )
01217 {
01218     PCE_code *p;
01219 
01220     p = (PCE_code*) malloc(sizeof(PCE_code));
01221     if (!p) return NULL;
01222     memset(p, 0, sizeof(PCE_code));
01223     p->type = type;
01224 
01225     return p;
01226 }
01227 
01228 static PCE_code*
01229 PCE_new_code_for_jmp(
01230     enum PCE_CODE_TYPE jmptype,
01231     int id
01232 )
01233 {
01234     PCE_code *p;
01235 
01236     p = (PCE_code*) malloc(sizeof(PCE_code));
01237     if (!p) return NULL;
01238     memset(p, 0, sizeof(PCE_code));
01239 
01240     ASSERT((jmptype == PCE_CODE_UNRESOLVED_JMP)
01241           || (jmptype == PCE_CODE_UNRESOLVED_COND_JMP)
01242           || (jmptype == PCE_CODE_UNRESOLVED_COND_NOT_JMP));
01243 
01244     p->type = jmptype;
01245     p->val.to_labelid = id;
01246 
01247     return p;
01248 }
01249 
01250 static EIMIL_symbol*
01251 PCE_lookup_symbol(
01252     PCE_context *pctx,
01253     PCE_code *pc
01254 )
01255 {
01256     EIMIL_symbol *psym;
01257     ASSERT((pc->type & PCE_CODE_SYMBOL) || (pc->type & PCE_CODE_DEFUN));
01258 
01259     if (pctx->pdic_f) {
01260        psym = EIMIL_lookup_symbol_internal(pctx->pdic_f, pc->val.symid);
01261        if (psym) return psym;
01262     }
01263 
01264     psym = EIMIL_lookup_symbol_internal(pctx->pdic, pc->val.symid);
01265     if (psym) return psym;
01266 
01267     psym = EIMIL_lookup_symbol_internal(pctx->ped->pdic, pc->val.symid);
01268     return psym;
01269 }
01270 
01271 static EIMIL_value*
01272 PCE_symbol_value(
01273     PCE_context *pctx,
01274     PCE_code *pc
01275 )
01276 {
01277     EIMIL_symbol *psym = PCE_lookup_symbol(pctx, pc);
01278     ASSERT(psym && psym->cat == EIMIL_CAT_VARIABLE);
01279     return psym->obj.v.pv;
01280 }
01281 
01282 static EIMIL_dictionary*
01283 PCE_new_dictionary(
01284     EIMIL_data *ped,
01285     PCE_context *pctx
01286 )
01287 {
01288     EIMIL_symbol *psym;
01289     EIMIL_dictionary *pdic;
01290     pdic = EIMIL_new_dictionary(PCE_DICTIONARY_DEFAULT_SIZE, 1);
01291     if (!pdic) return NULL;
01292     /* internal variables */
01293 
01294     psym = EIMIL_register_symbol(ped, pdic, "cev",
01295                              EIMIL_CAT_VARIABLE,
01296                              EIMIL_TYPE_EVENT);
01297     if (!psym) return NULL;
01298     psym->obj.v.type = EIMIL_TYPE_EVENT;
01299     psym->obj.v.constp = 1;
01300     psym->obj.v.pv = NULL;
01301     pctx->psym_cev = psym;
01302 
01303     psym = EIMIL_register_symbol(ped, pdic, "mapval",
01304                              EIMIL_CAT_VARIABLE,
01305                              EIMIL_TYPE_ANY);
01306     if (!psym) return NULL;
01307     psym->obj.v.type = EIMIL_TYPE_ANY;
01308     psym->obj.v.constp = 1;
01309     psym->obj.v.pv = NULL;
01310 
01311     pctx->pdic = pdic;
01312 
01313     return pdic;
01314 }
01315 
01316 static PCE_code*
01317 PCE_reverse_code(
01318     PCE_code *p
01319 )
01320 {
01321     PCE_code *p1, *p2;
01322 
01323     if (!p) return NULL;
01324 
01325     p1 = NULL;
01326     for (;;) {
01327        p2 = p->pnext;
01328        p->pnext = p1;
01329        if (!p2) return p;
01330        p1 = p;
01331        p = p2;
01332     }
01333 
01334     /* notreached */
01335     return NULL;
01336 }
01337 
01338 static enum EIMIL_TYPE
01339 PCE_get_type_from_name(
01340     UTF8 *name
01341 )
01342 {
01343     if (strcmp(name, "bool") == 0) return EIMIL_TYPE_BOOL;
01344     else if (strcmp(name, "number") == 0) return EIMIL_TYPE_NUMBER;
01345     else if (strcmp(name, "char") == 0) return EIMIL_TYPE_CHAR;
01346     else if (strcmp(name, "mtext") == 0) return EIMIL_TYPE_MTEXT;
01347     else if (strcmp(name, "event") == 0) return EIMIL_TYPE_EVENT;
01348     else if (strcmp(name, "prop") == 0) return EIMIL_TYPE_PROP;
01349 
01350     return EIMIL_TYPE_INVALID;
01351 }
01352 
01353 #define TYPE_NAME_LEN_MAX 64
01354 static int
01355 PCE_get_type_name(
01356     int type, char *buf, int len
01357 )
01358 {
01359     char *tn = buf;
01360     buf[0] = '\0';
01361     if (type & EIMIL_TYPE_ANY) {
01362        tn = "any type";
01363        if (strlen(tn) >= len) return 0;
01364        strcpy(buf, tn);
01365        return 1;
01366     }
01367     if (type & EIMIL_TYPE_BOOL) {
01368        tn = "bool";
01369        len -= strlen(tn);
01370        if (len <= 0) return 0;
01371        strcat(buf, tn);
01372     }
01373     if (type & EIMIL_TYPE_NUMBER) {
01374        if (*tn)
01375            tn = " or number";
01376        else
01377            tn = "number";
01378        len -= strlen(tn);
01379        if (len <= 0) return 0;
01380        strcat(buf, tn);
01381     }
01382     if (type & EIMIL_TYPE_CHAR) {
01383        if (*tn)
01384            tn = " or char";
01385        else
01386            tn = "char";
01387        len -= strlen(tn);
01388        if (len <= 0) return 0;
01389        strcat(buf, tn);
01390     }
01391     if (type & EIMIL_TYPE_MTEXT) {
01392        if (*tn)
01393            tn = " or mtext";
01394        else
01395            tn = "mtext";
01396        len -= strlen(tn);
01397        if (len <= 0) return 0;
01398        strcat(buf, tn);
01399     }
01400     if (type & EIMIL_TYPE_EVENT) {
01401        if (*tn)
01402            tn = " or event";
01403        else
01404            tn = "event";
01405        len -= strlen(tn);
01406        if (len <= 0) return 0;
01407        strcat(buf, tn);
01408     }
01409     if (type & EIMIL_TYPE_PROP) {
01410        if (*tn)
01411            tn = " or prop";
01412        else
01413            tn = "prop";
01414        len -= strlen(tn);
01415        if (len <= 0) return 0;
01416        strcat(buf, tn);
01417     }
01418     if (type & EIMIL_TYPE_NIL) {
01419        if (*tn)
01420            tn = " or nil";
01421        else
01422            tn = "nil";
01423        len -= strlen(tn);
01424        if (len <= 0) return 0;
01425        strcat(buf, tn);
01426     }
01427 
01428     return 1;
01429 }
01430 
01431 static void
01432 PCE_type_mismatch_error(
01433     EIMIL_data *ped,
01434     int type,
01435     int req
01436 )
01437 {
01438     char mes_req[TYPE_NAME_LEN_MAX], mes_type[TYPE_NAME_LEN_MAX];
01439 
01440     if (!PCE_get_type_name(req, mes_req, sizeof(mes_req))) return;
01441     if (!PCE_get_type_name(type, mes_type, sizeof(mes_type))) return;
01442     EIMIL_set_error_pt(ped, NULL, "Argument type is wrong.(%s, %s)",
01443                      mes_req, mes_type);
01444 }
01445 
01446 static int
01447 PCE_check_type(
01448     EIMIL_data *ped,
01449     PCE_parse_context *pcx,
01450     int type
01451 )
01452 {
01453     int i;
01454     int req;
01455 
01456     /* argument type */
01457     if (pcx->mode & PCE_IN_E) {
01458        PCE_function *pf = pcx->pf;
01459        if (pf->nargs <= pcx->idx) {
01460            req = 0;
01461        } else {
01462            PCE_funcproto *pfp = pf->pfp + pcx->idx;
01463            req = pfp->type;
01464        }
01465     } else {
01466        for (i = 0; i <= pcx->idx; i++) {
01467            if (i >= PCE_ARG_MAX) {
01468               req = 0;
01469               break;
01470            }
01471            req = pcx->required_type[i];
01472            if (!req) break;
01473            /* 
01474               Note that EIMIL_TYPE_OPTION1 means it allows
01475               arbitrary number of arguments.
01476            */
01477            if (req & EIMIL_TYPE_OPTION1) break;
01478        }
01479     }
01480     if (req == 0) {
01481        EIMIL_set_error_pt(ped, NULL, "Too many arguments.");
01482        return 0;
01483     }
01484     if ((req & EIMIL_TYPE_NIL) && (type == EIMIL_TYPE_NIL)) return 1;
01485     if ((req & EIMIL_TYPE_ANY) || (type & EIMIL_TYPE_ANY)) return 1;
01486     if ((req | type) == req) return 1;
01487 
01488     PCE_type_mismatch_error(ped, type, req);
01489 
01490     return 0;
01491 }
01492 
01493 static int
01494 PCE_setup_arg(
01495     EIMIL_data *ped,
01496     PCE_parse_context *pcx,
01497     PCE_code **ppc
01498 )
01499 {
01500     int i, j, *pra;
01501     PCE_code *pc;
01502 
01503     /* Check the number of argument. */
01504     if (pcx->mode & PCE_IN_E) {
01505        i = pcx->pf->nargs;
01506     } else {
01507        pra = pcx->required_type;
01508        for (i = 0; i <= PCE_ARG_MAX; i++, pra++) {
01509            if (!*pra) break;
01510            if (*pra | EIMIL_TYPE_OPTION2) break;
01511            if (*pra | EIMIL_TYPE_OPTION1) break;
01512        }
01513     }
01514     for (j = 0, pc = pcx->pc; pc; pc = pc->pnext, j++);
01515     if (j < i) {
01516        PCE_set_error(ped, PCE_TOO_FEW_ARGUMENTS_ERROR);
01517        return 0;
01518     }
01519 
01520     *ppc = PCE_reverse_code(pcx->pc);
01521     return 1;
01522 }
01523 
01524 static void
01525 PCE_free_code(
01526     PCE_code *pc
01527 )
01528 {
01529     PCE_code *pc2;
01530     while (pc) {
01531        pc2 = pc->pnext;
01532        if (pc->parg) PCE_free_code(pc->parg);
01533 
01534        if (pc->type == PCE_CODE_VALUE) {
01535            EIMIL_RMREF(*pc->val.pv);
01536        }
01537        free(pc);
01538        pc = pc2;
01539     }
01540 }
01541 
01542 static void
01543 PCE_free_parse_context(
01544     PCE_parse_context *pcx
01545 )
01546 {
01547     PCE_parse_context *pcx2;
01548 
01549     if (pcx->pc)
01550        PCE_free_code(pcx->pc);
01551     pcx2 = pcx->pnext;
01552     free(pcx);
01553     if (pcx2) PCE_free_parse_context(pcx2);
01554 }
01555 
01556 /*****************************************
01557              PCE label
01558  *****************************************/
01559 
01560 #define PCE_LABEL_INITIALI_ALLOC_SIZE 16;
01561 
01562 static enum PCE_ERROR_CODE
01563 PCE_initialize_labels(
01564     PCE_parse_context *pcx
01565 )
01566 {
01567     PCE_labelset *pls;
01568     pls = (PCE_labelset*) malloc(sizeof(PCE_labelset));
01569     if (!pls) return PCE_MEMORY_ERROR;
01570     memset(pls, 0, sizeof(*pls));
01571     pcx->plabels = pls;
01572     pls->pdic = EIMIL_new_dictionary(7, 0);
01573     if (!pls->pdic) {
01574        free(pls);
01575        return PCE_MEMORY_ERROR;
01576     }
01577     return PCE_SUCCESS;
01578 }
01579 
01580 static int
01581 PCE_make_label(
01582     PCE_parse_context *pcx
01583 )
01584 {
01585     PCE_labelset *pls = pcx->plabels;
01586     PCE_label *pl;
01587 
01588     if (pls->allocednum <= pls->labelnum) {
01589        int newsize;
01590        if (pls->allocednum == 0) {
01591            newsize = PCE_LABEL_INITIALI_ALLOC_SIZE;
01592        } else {
01593            newsize = pls->allocednum * 2;
01594        }
01595        pl = (PCE_label*) realloc(pls->pl, sizeof(PCE_label) * newsize);
01596        if (!pl) return -1;
01597        pls->allocednum = newsize;
01598        pls->pl = pl;
01599     }
01600 
01601     pl = pls->pl + pls->labelnum;
01602     pl->id = pls->labelnum;
01603     pl->pc = NULL;
01604     pl->psym = NULL;
01605     pls->labelnum++;
01606 
01607     return pl->id;
01608 }
01609 
01610 static int
01611 PCE_make_named_label(
01612     EIMIL_data *ped,
01613     PCE_parse_context *pcx,
01614     UTF8 *name
01615 )
01616 {
01617     int id;
01618     EIMIL_symbol *psym;
01619     PCE_labelset *pls = pcx->plabels;
01620     PCE_label *pl;
01621 
01622     id = PCE_make_label(pcx);
01623     if (id < 0) return id;
01624     pl = pls->pl + id;
01625 
01626     psym = EIMIL_register_symbol(ped, pls->pdic, name,
01627                              EIMIL_CAT_OPTIONAL,
01628                              EIMIL_TYPE_NONE);
01629     if (!psym) return -1;
01630     psym->obj.opt.optnum1 = id;
01631     pl->psym = psym;
01632 
01633     return id;
01634 }
01635 
01636 static int
01637 PCE_lookup_named_label(
01638     PCE_parse_context *pcx,
01639     UTF8 *name
01640 )
01641 {
01642     int id;
01643     EIMIL_symbol *psym;
01644     PCE_labelset *pls = pcx->plabels;
01645 
01646     id = PCE_make_label(pcx);
01647 
01648     psym = EIMIL_intern_soft(pls->pdic, name);
01649     if (!psym) return -1;
01650 
01651     return psym->obj.opt.optnum1;
01652 }
01653 
01654 static void
01655 PCE_mark_label(
01656     PCE_parse_context *pcx,
01657     int id,
01658     PCE_code *pc,
01659     int nextp
01660 )
01661 {
01662     PCE_labelset *pls = pcx->plabels;
01663     PCE_label *pl;
01664     ASSERT(id < pls->labelnum);
01665     pl = pls->pl + id;
01666     ASSERT(!pl->pc);
01667     pl->pc = pc;
01668     pl->nextp = nextp;
01669 }
01670 
01671 static void
01672 PCE_mark_label_yet(
01673     PCE_parse_context *pcx,
01674     int id,
01675     PCE_code *pc,
01676     int nextp
01677 )
01678 {
01679     if (!((pcx->plabels->pl)[id].pc))
01680        PCE_mark_label(pcx, id, pc, nextp);
01681 }
01682 
01683 static enum PCE_ERROR_CODE
01684 PCE_fixate_labels(
01685     EIMIL_data *ped,
01686     PCE_labelset *pls,
01687     PCE_code *pc_st
01688 )
01689 {
01690     enum PCE_ERROR_CODE r;
01691     PCE_label *pl;
01692     PCE_code *pc;
01693 
01694     for (pc = pc_st; pc; pc = pc->pnext) {
01695        if ((pc->type == PCE_CODE_UNRESOLVED_JMP)
01696            || (pc->type == PCE_CODE_UNRESOLVED_COND_JMP)
01697            || (pc->type == PCE_CODE_UNRESOLVED_COND_NOT_JMP)) {
01698            ASSERT(pc->val.to_labelid < pls->labelnum);
01699            pl = pls->pl + pc->val.to_labelid;
01700            if (!pl->pc) {
01701               ASSERT(pl->psym);
01702               EIMIL_set_error(ped, "label:%s is not defined, but refered.",
01703                             pl->psym->name);
01704               return PCE_LABEL_NOT_DEFINED_ERROR;
01705            }
01706            if (pc->type == PCE_CODE_UNRESOLVED_JMP)
01707               pc->type = PCE_CODE_JMP;
01708            else if (pc->type == PCE_CODE_UNRESOLVED_COND_JMP)
01709               pc->type = PCE_CODE_COND_JMP;
01710            else
01711               pc->type = PCE_CODE_COND_NOT_JMP;
01712 
01713            if (pl->nextp)
01714               pc->val.pc_to = pl->pc->pnext;
01715            else
01716               pc->val.pc_to = pl->pc;
01717        }
01718        if (pc->parg) {
01719            r = PCE_fixate_labels(ped, pls, pc->parg);
01720            if (r != PCE_SUCCESS) return r;
01721        }
01722     }
01723     return PCE_SUCCESS;
01724 }
01725 
01726 static enum PCE_ERROR_CODE
01727 PCE_finalize_labels(
01728     EIMIL_data *ped,
01729     PCE_parse_context *pcx
01730 )
01731 {
01732     enum PCE_ERROR_CODE r;
01733     PCE_labelset *pls = pcx->plabels;
01734 
01735     r = PCE_fixate_labels(ped, pls, pcx->pc);
01736     if (r != PCE_SUCCESS) return r;
01737 
01738     EIMIL_free_dictionary_and_symbol(pls->pdic);
01739     free(pls->pl);
01740     free(pls);
01741 
01742     return PCE_SUCCESS;
01743 }
01744 
01745 /*****************************************
01746               literal
01747  *****************************************/
01748 
01749 #define PCE_ischdec(c) (((c) >= '0' && (c) <= '9'))
01750 #define PCE_chdec(c) ((c) - '0')
01751 #define PCE_ischhex(c) (((c) >= '0' && (c) <= '9') \
01752                         || ((c) >= 'a' && (c) <= 'f') \
01753                         || ((c) >= 'A' && (c) <= 'F'))
01754 #define PCE_chhex(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
01755                       ((c) >= 'a' && (c) <= 'f') ? ((c) - 'a') : ((c) - 'A'))
01756 
01757 static enum PCE_ERROR_CODE
01758 PCE_parse_literal(
01759     EIMIL_data *ped,
01760     UTF8 *pchars,
01761     EIMIL_value **ppv
01762 )
01763 {
01764     EIMIL_value *pv;
01765     if ((*pchars >= '1') && (*pchars <= '9')) {
01766        /* DEC NUMBER */
01767        int n = 0;
01768        for (; *pchars; pchars++) {
01769            if (!PCE_ischdec(*pchars)) {
01770               PCE_set_error(ped, PCE_DEC_NUMBER_ERROR);
01771               return PCE_DEC_NUMBER_ERROR;
01772            }
01773            n = n * 10 + PCE_chdec(*pchars);
01774            if (n > PCE_MAX_NUMBER) {
01775               PCE_set_error(ped, PCE_LITERAL_OVERFLOW);
01776               return PCE_LITERAL_OVERFLOW;
01777            }
01778        }
01779        pv = EIMIL_construct_number(n);
01780     } else if (*pchars == '0') {
01781        int n;
01782        if (pchars[1] == '\0') {
01783            n = 0;
01784        } else {
01785            /* HEX NUMBER */
01786            if (pchars[1] != 'x') {
01787               PCE_set_error(ped, PCE_HEX_NUMBER_ERROR);
01788               return PCE_HEX_NUMBER_ERROR;
01789            }
01790            pchars += 2;
01791            n = 0;
01792            for (; *pchars; pchars++) {
01793               if (!PCE_ischhex(*pchars)) {
01794                   PCE_set_error(ped, PCE_HEX_NUMBER_ERROR);
01795                   return PCE_HEX_NUMBER_ERROR;
01796               }
01797               n = n * 10 + PCE_chhex(*pchars);
01798               if (n > PCE_MAX_NUMBER) {
01799                   PCE_set_error(ped, PCE_LITERAL_OVERFLOW);
01800                   return PCE_LITERAL_OVERFLOW;
01801               }
01802            }
01803        }
01804        pv = EIMIL_construct_number(n);
01805     } else if (*pchars == '\'') {
01806        /* CHAR */
01807        UTF32 ch;
01808        int n = EIMIL_convert_UTF8_to_UTF32char(pchars + 1, &ch);
01809        if ((pchars[n + 1] != '\'') || (pchars[n + 2] != 0)) {
01810            PCE_set_error(ped, PCE_CHAR_LITERAL_ERROR);
01811            return PCE_CHAR_LITERAL_ERROR;
01812        }
01813        pv = EIMIL_construct_char(ch);
01814     } else if (*pchars == '"') {
01815        /* MTEXT */
01816        UTF32 *pu32;
01817        int n = strlen(pchars);
01818        if (pchars[n - 1] != '"') {
01819            PCE_set_error(ped, PCE_MTEXT_LITERAL_ERROR);
01820            return PCE_MTEXT_LITERAL_ERROR;
01821        }
01822        pchars[n - 1] = 0;
01823        pu32 = EIMIL_convert_UTF8_to_UTF32(pchars + 1);
01824        pv = EIMIL_construct_mtext_from_UTF32(n - 2, pu32);
01825        free(pu32);
01826     } else {
01827        return PCE_PARSE_NOT_LITERAL;
01828     }
01829     if (!pv) {
01830        PCE_set_error(ped, PCE_MEMORY_ERROR);
01831        return PCE_MEMORY_ERROR;
01832     }
01833 
01834     *ppv = pv;
01835     return PCE_SUCCESS;
01836 }
01837 
01838 static enum PCE_ERROR_CODE
01839 PCE_parse_token(
01840     EIMIL_data *ped,
01841     PCE_parse_context *pcx,
01842     UTF8 *pchars
01843 )
01844 {
01845     EIMIL_value *pv;
01846     enum PCE_ERROR_CODE r;
01847     r = PCE_parse_literal(ped, pchars, &pv);
01848     switch (r) {
01849       case PCE_SUCCESS:
01850       {
01851          PCE_code *pc;
01852          if (!PCE_check_type(ped, pcx, pv->type))
01853              return PCE_WRONG_TYPE_ARGUMENT_ERROR;
01854          pc = PCE_new_code_for_value(pv);
01855          if (!pc) {
01856              PCE_set_error(ped, PCE_MEMORY_ERROR);
01857              return PCE_MEMORY_ERROR;
01858          }
01859          EIMIL_ADDREF(*pv);
01860          PCE_ADD_CODE(pcx, pc);
01861          return PCE_SUCCESS;
01862       }
01863       case PCE_PARSE_NOT_LITERAL:
01864       {
01865          /* maybe VARIABLE */
01866          PCE_code *pc;
01867          EIMIL_symbol *psym;
01868 
01869          psym = PCE_get_variable(ped, pcx, pchars);
01870          if (!psym) return PCE_MEMORY_ERROR;
01871          if (!PCE_check_type(ped, pcx, psym->obj.v.type))
01872              return PCE_WRONG_TYPE_ARGUMENT_ERROR;
01873          pc = PCE_new_code_for_symbol(psym);
01874          if (!pc) return PCE_MEMORY_ERROR;
01875          PCE_ADD_CODE(pcx, pc);
01876 
01877          return PCE_SUCCESS;
01878       }
01879       default:
01880         break;
01881     }
01882     return r;
01883 }
01884 
01885 static enum EIMIL_TYPE
01886 PCE_get_type_from_attrs(
01887     EIMIL_data *ped,
01888     EIMIL_attrs *patr
01889 )
01890 {
01891     UTF8 *name;
01892     enum EIMIL_TYPE type;
01893 
01894     for (; patr->name; patr++) {
01895        if (strcmp(patr->name, "type") == 0) {
01896            if (!EIMIL_get_attr_nmtoken(patr->val, &name)) {
01897               type = EIMIL_TYPE_INVALID;
01898               break;
01899            }
01900            type = PCE_get_type_from_name(name);
01901            free(name);
01902            free(patr->name);
01903            free(patr->val);
01904            EIMIL_remove_attr(patr);
01905            break;
01906        }
01907     }
01908     if (type == EIMIL_TYPE_INVALID) {
01909        EIMIL_set_error_pt(ped, NULL,
01910                         "Invalid type name:%s", patr->name);
01911     }
01912 
01913     return type;
01914 }
01915 
01916 
01917 /****************************************
01918            parser handlers
01919  ****************************************/
01920 
01921 static PCE_parse_context*
01922 PCE_parser_decl_start(
01923     EIMIL_data *ped,
01924     PCE_parse_context *pcx
01925 )
01926 {
01927     /* TODO */
01928     return NULL;
01929 }
01930 
01931 static PCE_parse_context*
01932 PCE_new_parse_context(
01933     EIMIL_data *ped
01934 )
01935 {
01936     PCE_parse_context *pcnx;
01937 
01938     pcnx = (PCE_parse_context*) malloc(sizeof(PCE_parse_context));
01939     if (!pcnx) {
01940        EIMIL_set_out_of_memory(ped);
01941        return NULL;
01942     }
01943     memset(pcnx, 0, sizeof(PCE_parse_context));
01944     return pcnx;
01945 }
01946 
01947 static PCE_parse_context*
01948 PCE_parser_generic_start(
01949     EIMIL_data *ped,
01950     PCE_parse_context *pcx,
01951     int type
01952 )
01953 {
01954     PCE_parse_context *pcnx;
01955 
01956     if (!PCE_check_type(ped, pcx, type)) return NULL;
01957     pcnx = PCE_new_parse_context(ped);
01958     if (!pcnx) return NULL;
01959     /* already done: pcnx->idx = 0; */
01960     pcnx->pnext = pcx;
01961     pcnx->result = type;
01962     pcnx->pctx = pcx->pctx;
01963     pcnx->mode = pcx->mode;
01964     pcnx->pdic = pcx->pdic;
01965     pcnx->pf = pcx->pf;
01966     pcnx->plabels = pcx->plabels;
01967 
01968     return pcnx;
01969 }
01970 
01971 static PCE_parse_context*
01972 PCE_parser_generic_end( 
01973     EIMIL_data *ped,
01974     PCE_parse_context *pcx,
01975     PCE_code *pc
01976 )
01977 {
01978     PCE_parse_context *pcx2;
01979     if (!pc) {
01980        EIMIL_set_out_of_memory(ped);
01981        PCE_free_parse_context(pcx);
01982        return NULL;
01983     }
01984     pcx2 = pcx->pnext;
01985     if (!PCE_setup_arg(ped, pcx, &pc->parg)) {
01986        PCE_free_parse_context(pcx);
01987        return NULL;
01988     }
01989     PCE_ADD_CODE(pcx2, pc);
01990     free(pcx);
01991 
01992     return pcx2;
01993 }
01994 
01995 static PCE_code*
01996 PCE_insert_head_code(
01997     PCE_code *pc,
01998     PCE_code *pc_ins,
01999     int first_argp
02000 )
02001 {
02002     PCE_code *pc2, *pc_end, *pc_prevend;
02003 
02004     pc_end = pc_prevend = NULL;
02005     for (pc2 = pc; pc2; pc2 = pc2->pnext) {
02006        pc_prevend = pc_end;
02007        pc_end = pc2;
02008     }
02009 
02010     if (first_argp) {
02011        ASSERT(pc_end);
02012        pc_ins->parg = pc_end;
02013        if (pc_prevend)      pc_prevend->pnext = pc_ins;
02014        pc_ins->parg->pnext = NULL;
02015     } else {
02016        if (pc_end)
02017            pc_end->pnext = pc_ins;
02018        else
02019            return pc_ins;
02020     }
02021 
02022     return pc;
02023 }
02024 
02025 enum PCE_JMP_END_FLAG {
02026        PCE_UNCOND_JMP_END,
02027        PCE_COND_JMP_END,
02028        PCE_COND_NOT_JMP_END
02029 };
02030 static PCE_parse_context*
02031 PCE_parser_jmp_end(
02032     EIMIL_data *ped,
02033     PCE_parse_context *pcx,
02034     enum PCE_JMP_END_FLAG condflag,
02035     int loopp
02036 )
02037 {
02038     int cflag;
02039     PCE_parse_context *pcx2;
02040     PCE_code *pc, *pc2;
02041 
02042     if (condflag == PCE_UNCOND_JMP_END) {
02043        pc = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_JMP, pcx->labelid);
02044        cflag = 0;
02045     } else if (condflag == PCE_COND_JMP_END) {
02046        pc = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_COND_JMP,
02047                               pcx->labelid);
02048        cflag = 1;
02049     } else {
02050        pc = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_COND_NOT_JMP,
02051                               pcx->labelid);
02052        cflag = 1;
02053     }
02054 
02055     if (!pc) {
02056        EIMIL_set_out_of_memory(ped);
02057        PCE_free_parse_context(pcx);
02058        return NULL;
02059     }
02060 
02061     if (cflag && !pcx->pc) {
02062        PCE_set_error(ped, PCE_TOO_FEW_ARGUMENTS_ERROR);
02063        return NULL;
02064     }
02065 
02066     pc2 = PCE_insert_head_code(pcx->pc, pc, cflag);
02067 
02068     pcx2 = pcx->pnext;
02069     pc->pnext = pcx2->pc;
02070 
02071     if (loopp) {
02072        int loopid;
02073        PCE_code *pc_loop;
02074 
02075        loopid = PCE_make_label(pcx2);
02076        if (loopid < 0) return NULL;
02077        pc_loop = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_JMP, loopid);
02078        if (!pc_loop) return NULL;
02079        pc_loop->pnext = pc2;
02080        pcx2->pc = pc_loop;
02081        PCE_mark_label(pcx2, loopid, pc, 0);
02082     } else {
02083        pcx2->pc = pc2;
02084     }
02085 
02086     free(pcx);
02087 
02088     return pcx2;
02089 }
02090 
02091 static PCE_parse_context*
02092 PCE_parser_select_case_end(
02093     EIMIL_data *ped,
02094     PCE_parse_context *pcx
02095 )
02096 {
02097     PCE_parse_context *pcx2;
02098     PCE_code *pc_case_cond, *pc_jmp_to_tail;
02099 
02100     pcx2 = pcx->pnext;
02101 
02102     pc_case_cond = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_COND_JMP,
02103                                    pcx->labelid2);
02104     pc_jmp_to_tail = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_JMP,
02105                                    pcx2->labelid);
02106     if ((!pc_case_cond) || (!pc_jmp_to_tail)) {
02107        EIMIL_set_out_of_memory(ped);
02108        PCE_free_parse_context(pcx);
02109        return NULL;
02110     }
02111 
02112     PCE_ADD_CODE(pcx, pc_jmp_to_tail);
02113 
02114     {
02115        PCE_code *pc2, *pc_end, *pc_prevend;
02116 
02117        pc_end = pc_prevend = NULL;
02118        for (pc2 = pcx->pc; pc2; pc2 = pc2->pnext) {
02119            pc_prevend = pc_end;
02120            pc_end = pc2;
02121        }
02122 
02123        if (!(pc_end && pc_prevend)) {
02124            PCE_set_error(ped, PCE_TOO_FEW_ARGUMENTS_ERROR);
02125            return NULL;
02126        }
02127 
02128        pc_case_cond->parg = pc_end;
02129        pc_case_cond->pnext = pcx2->pc_head;
02130        pcx2->pc_head = pc_case_cond;
02131 
02132        pc_prevend->pnext = pcx2->pc;
02133        pcx2->pc = pcx->pc;
02134        PCE_mark_label(pcx2, pcx->labelid2, pc_prevend, 0);
02135     }
02136 
02137     free(pcx);
02138     return pcx2;
02139 }
02140 
02141 static PCE_parse_context*
02142 PCE_parser_select_default_end(
02143     EIMIL_data *ped,
02144     PCE_parse_context *pcx
02145 )
02146 {
02147     PCE_parse_context *pcx2;
02148     PCE_code *pc_def_jmp;
02149 
02150     pcx2 = pcx->pnext;
02151 
02152     if (pcx->pc) {
02153        PCE_code *pc2, *pc_end;
02154 
02155        pc_def_jmp = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_JMP,
02156                                      pcx->labelid2);
02157        if (!pc_def_jmp) {
02158            EIMIL_set_out_of_memory(ped);
02159            return NULL;
02160        }
02161        pc_end = NULL;
02162        for (pc2 = pcx->pc; pc2; pc2 = pc2->pnext) {
02163            pc_end = pc2;
02164        }
02165        PCE_mark_label(pcx2, pcx->labelid2, pc_end, 0);
02166        pc_end->pnext = pcx2->pc;
02167        pcx2->pc = pc_end;
02168        pcx2->mode |= PCE_SELECT_HAS_DEFAULT;
02169     } else {
02170        pc_def_jmp = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_JMP,
02171                                      pcx->labelid);
02172     }
02173     pc_def_jmp->pnext = pcx2->pc_head;
02174     pcx2->pc_head = pc_def_jmp;
02175 
02176     free(pcx);
02177     return pcx2;
02178 }
02179 
02180 static PCE_parse_context*
02181 PCE_parser_select_end(
02182     EIMIL_data *ped,
02183     PCE_parse_context *pcx
02184 )
02185 {
02186     PCE_parse_context *pcx2;
02187     PCE_code *pc_cond_end;
02188     PCE_code *pc_block_end;
02189 
02190     pcx2 = pcx->pnext;
02191 
02192     pc_cond_end = pcx->pc_head;
02193     pc_block_end = pcx->pc;
02194 
02195     if (!(pcx->mode & PCE_SELECT_HAS_DEFAULT)) {
02196        PCE_code *pc = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_JMP,
02197                                        pcx->labelid);
02198        if (!pc) return NULL;
02199        pc->pnext = pc_cond_end;
02200        pc_cond_end = pc;
02201     }
02202     pc_block_end = PCE_insert_head_code(pc_block_end, pc_cond_end, 0);
02203     pcx2->pc = PCE_insert_head_code(pc_block_end, pcx2->pc, 0);
02204     PCE_mark_label_yet(pcx, pcx->labelid, pcx2->pc, 1);
02205     free(pcx);
02206     return pcx2;
02207 }
02208 
02209 /*
02210   attribute access
02211  */
02212 static UTF8*
02213 PCE_get_name_attribute(
02214     EIMIL_data *ped,
02215     EIMIL_attrs *patr
02216 )
02217 {
02218     UTF8 *name;
02219     for (; patr->name;patr++) {
02220        if (strcmp(patr->name, "name") == 0) {
02221            if (!EIMIL_get_attr_nmtoken(patr->val, &name)) {
02222               EIMIL_set_error_pt(ped, NULL, "Invalid nmtoken in `name'");
02223               return NULL;
02224            }
02225            return name;
02226        }
02227     }
02228     return NULL;
02229 }
02230 
02231 enum PCE_VAL_TYPE {
02232        PCE_VAL_TYPE_INVALID,
02233        PCE_VAL_TYPE_NIL,
02234        PCE_VAL_TYPE_CONST,
02235        PCE_VAL_TYPE_INIT
02236 };
02237 
02238 static enum PCE_VAL_TYPE
02239 PCE_get_val_type_attribute(
02240     EIMIL_data *ped,
02241     EIMIL_attrs *patr
02242 )
02243 {
02244     for (; patr->name; patr++) {
02245        if (strcmp(patr->name, "val") == 0) {
02246            enum PCE_VAL_TYPE vt;
02247            UTF8 *val;
02248 
02249            if (!EIMIL_get_attr_nmtoken(patr->val, &val)) {
02250               EIMIL_set_error_pt(ped, NULL, "Unrecogized keyword in `val'");
02251               return PCE_VAL_TYPE_INVALID;
02252            }
02253            if (strcmp(val, "const") == 0) {
02254               vt = PCE_VAL_TYPE_CONST;
02255            } else if (strcmp(val, "nil") == 0) {
02256               vt = PCE_VAL_TYPE_NIL;
02257            } else if (strcmp(val, "init") == 0) {
02258               vt = PCE_VAL_TYPE_INIT;
02259            } else {
02260               vt = PCE_VAL_TYPE_INVALID;
02261            }
02262            free(val);
02263            return vt;
02264        }
02265     }
02266     return PCE_VAL_TYPE_INVALID;
02267 }
02268 
02269 #define PCE_ARGUMENT_DICTIONARY_SIZE 5
02270 static int
02271 PCE_get_funcproto_attribute(
02272     EIMIL_data *ped,
02273     EIMIL_attrs *patr,
02274     PCE_function **ppf
02275 )
02276 {
02277     for (; patr->name;patr++) {
02278        if (strcmp(patr->name, "args") == 0) {
02279            enum EIMIL_TYPE type;
02280            UTF8 *argname, *typename;
02281            EIMIL_dictionary *pdic = NULL;
02282            EIMIL_symbol *psym;
02283            PCE_function *pf;
02284            PCE_funcproto *pfp, *pfp2;
02285            Ebyte *c = patr->val;
02286            int i = 0;
02287            int n = 0;
02288 
02289            pfp2 = pfp = NULL;
02290            while ((c = EIMIL_get_attr_nmtokens(c, &argname)) != NULL) {
02291               if (i >= n) {
02292                   n += 10;
02293                   pfp2 = (PCE_funcproto*) realloc(pfp2,
02294                                               sizeof(PCE_funcproto) * n);
02295                   if (!pfp2) {
02296                      PCE_set_error(ped, PCE_MEMORY_ERROR);
02297                      return 0;
02298                   }
02299                   pfp = pfp2 + i;
02300               }
02301               typename = strchr(argname, ':');
02302               if (!typename) {
02303                   EIMIL_set_error_pt(ped, NULL,
02304                                    "Function argument must specify type name.");
02305                   return 0;
02306               }
02307               *typename = '\0';
02308               typename++;
02309               type = PCE_get_type_from_name(typename);
02310               if (type == EIMIL_TYPE_INVALID) {
02311                   EIMIL_set_error_pt(ped, NULL,
02312                                    "Invalid type name:%s.", typename);
02313                   return 0;
02314               }
02315               pfp->type = type;
02316               if (!pdic) {
02317                   pdic = EIMIL_new_dictionary(PCE_ARGUMENT_DICTIONARY_SIZE, 1);
02318                   if (!pdic) {
02319                      PCE_set_error(ped, PCE_MEMORY_ERROR);
02320                      return 0;
02321                   }
02322               }
02323               psym = EIMIL_register_symbol(ped, pdic, argname,
02324                                         EIMIL_CAT_VARIABLE, type);
02325               pfp->psym = psym;
02326               pfp++;
02327               i++;
02328            }
02329            if (i > 0) {
02330               pfp = (PCE_funcproto*) realloc(pfp2,
02331                                           sizeof(PCE_funcproto) * i);
02332               if (!pfp) {
02333                   PCE_set_error(ped, PCE_MEMORY_ERROR);
02334                   return 0;
02335               }
02336            }         
02337            pf = (PCE_function*) malloc(sizeof(PCE_function));
02338            if (!pf) {
02339               PCE_set_error(ped, PCE_MEMORY_ERROR);
02340               return 0;
02341            }
02342            memset(pf, 0, sizeof(PCE_function));
02343            pf->nargs = i;
02344            pf->pdic = pdic;
02345            pf->pfp = pfp;
02346            pf->pc = NULL;
02347            *ppf = pf;
02348            return 1;
02349        }
02350     }
02351     return 0;
02352 }
02353 
02354 /*
02355   declaration.
02356  */
02357 
02358 DEFINE_PARSER_METHOD(defvar)
02359 {
02360     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02361 
02362     switch (type) {
02363       case EIMIL_START_TAG:
02364       {
02365          int constp = 0;
02366          enum PCE_VAL_TYPE vt;
02367          EIMIL_symbol *psym;
02368          char *name;
02369          
02370          type = PCE_get_type_from_attrs(ped, patr);
02371          if (type == EIMIL_TYPE_INVALID) return 0;
02372          vt = PCE_get_val_type_attribute(ped, patr);
02373          if (vt == PCE_VAL_TYPE_INVALID) return 0;
02374          name = PCE_get_name_attribute(ped, patr);
02375          if (!name) return 0;
02376          if (vt == PCE_VAL_TYPE_CONST) {
02377              constp = 1;
02378          } else if (vt == PCE_VAL_TYPE_NIL) {
02379              pcx->mode = PCE_SET_PARSER_CONTEXT_MODE(pcx,
02380                                                 PCE_DEFVAR_NIL);
02381          }
02382 
02383          psym = PCE_register_symbol(pcx->pctx, name,
02384                                  EIMIL_CAT_VARIABLE,
02385                                  type);
02386          free(name);
02387          if (!psym) return 0;
02388          psym->publicp = 0;
02389          psym->obj.v.constp = constp;
02390          psym->obj.v.type = type;
02391          psym->obj.v.pv = NULL;
02392          pcx->psym = psym;
02393          return 1;
02394       }
02395       case EIMIL_CHARDATA:
02396       {
02397          EIMIL_value *pv;
02398          EIMIL_symbol *psym = pcx->psym;
02399          enum PCE_ERROR_CODE r;
02400 
02401          if (pcx->mode & PCE_DEFVAR_DONE) {
02402              PCE_set_error(ped, PCE_DEFVAR_DONE_ERROR);
02403              return 0;
02404          }
02405          if (pcx->mode & PCE_DEFVAR_NIL) {
02406              PCE_set_error(ped, PCE_DEFVAR_NIL_ERROR);
02407              return 0;
02408          }
02409          r = PCE_parse_literal(ped, pchars, &pv);
02410          if (r != PCE_SUCCESS) {
02411              PCE_set_error(ped, r);
02412              return 0;
02413          }
02414          if (psym->obj.v.type != pv->type) {
02415              PCE_type_mismatch_error(ped, psym->obj.v.type, pv->type);
02416              return 0;
02417          }
02418          
02419          psym = pcx->psym;
02420          ASSERT(psym);
02421          pcx->psym->obj.v.pv = pv;
02422          EIMIL_ADDREF(*pv);
02423          pcx->mode = PCE_SET_PARSER_CONTEXT_MODE(pcx,
02424                                             PCE_DEFVAR_DONE);
02425          return 1;
02426       }
02427 
02428       case EIMIL_END_TAG:
02429        pcx->mode = PCE_RESET_PARSER_CONTEXT_MODE(pcx,
02430                                            PCE_DEFVAR_NIL_ERROR
02431                                            | PCE_DEFVAR_DONE);
02432        return 1;
02433        
02434       default:
02435        EIMIL_set_error_pt(ped, NULL, "Unknown error.");
02436     }
02437 
02438     return 0;
02439 }
02440 
02441 DEFINE_PARSER_METHOD(defun)
02442 {
02443     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02444     PCE_inst_template *pit = (PCE_inst_template*) ped->pcommon->ps.pcet->private;
02445 
02446     switch (type) {
02447       case EIMIL_START_TAG:
02448       {
02449          PCE_function *pf;
02450          EIMIL_symbol *psym;
02451          char *name;
02452          enum EIMIL_TYPE rettype;
02453 
02454          rettype = PCE_get_type_from_attrs(ped, patr);
02455          if (rettype == EIMIL_TYPE_INVALID) return 0;
02456          name = PCE_get_name_attribute(ped, patr);
02457          if (!name) return 0;
02458          if (!PCE_get_funcproto_attribute(ped, patr, &pf)) return 0;
02459          pf->rettype = rettype;
02460          psym = PCE_register_symbol(pcx->pctx, name,
02461                                  EIMIL_CAT_FUNCTION,
02462                                  type);
02463          free(name);
02464          if (!psym)  return 0;
02465          psym->publicp = 0;
02466          psym->obj.f.type = type;
02467          psym->obj.f.def = pf;
02468 
02469          pcx = PCE_parser_generic_start(ped, pcx, pit->result);
02470          if (!pcx) return 0;
02471          PCE_SET_REQUIRED_TYPES(pcx, pit);
02472          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, PCE_IN_DEFUN);
02473          pcx->psym = psym;
02474          pcx->pdic = pf->pdic;
02475          pcx->pf = pf;
02476          *pprivate = pcx;
02477          return 1;
02478       }
02479       case EIMIL_CHARDATA:
02480        EIMIL_set_error(ped, NULL, "The expression has no effect.");
02481        return 0;
02482 
02483       case EIMIL_END_TAG:
02484       {
02485          EIMIL_symbol *psym = pcx->psym;
02486          PCE_function *pf = (PCE_function*) psym->obj.f.def;
02487          int symid;
02488          symid = pcx->psym->symbolid;
02489          pcx = PCE_parser_generic_end(ped, pcx,
02490                                    PCE_new_code_for_etc(PCE_CODE_DEFUN));
02491          pcx->pc->val.symid = symid;
02492          if (!pcx) return 0;
02493          pf->pc = pcx->pc;
02494          return 1;
02495       }
02496        
02497       default:
02498        EIMIL_set_error_pt(ped, NULL, "Unknown error.");
02499     }
02500 
02501     return 0;
02502 }
02503 
02504 DEFINE_PARSER_METHOD(main)
02505 {
02506     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02507     PCE_inst_template *pit = (PCE_inst_template*) ped->pcommon->ps.pcet->private;
02508 
02509     switch (type) {
02510       case EIMIL_START_TAG:
02511       {
02512          pcx = PCE_parser_generic_start(ped, pcx, pit->result);
02513          if (!pcx) return 0;
02514          PCE_SET_REQUIRED_TYPES(pcx, pit);
02515          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, PCE_IN_MAIN);
02516          *pprivate = pcx;
02517          return 1;
02518       }
02519       case EIMIL_CHARDATA:
02520        EIMIL_set_error(ped, NULL, "The expression has no effect.");
02521        return 0;
02522 
02523       case EIMIL_END_TAG:
02524       {
02525          PCE_data *pd = pcx->pctx->ppce_data;
02526          pcx = PCE_parser_generic_end(ped, pcx,
02527                                    PCE_new_code_for_etc(PCE_CODE_MAIN));
02528          if (!pcx) return 0;
02529          pd->pcode = pcx->pc;
02530          return 1;
02531       }
02532        
02533       default:
02534        EIMIL_set_error_pt(ped, NULL, "Unknown error.");
02535     }
02536 
02537     return 0;
02538 }
02539 
02540 DEFINE_PARSER_METHOD(deftable)
02541 {
02542     /* TODO */
02543     return 1;
02544 }
02545 
02546 DEFINE_PARSER_METHOD(key)
02547 {
02548     return 0;
02549 }
02550 
02551 DEFINE_PARSER_METHOD(defkeymap)
02552 {
02553     /* TODO */
02554     return 1;
02555 }
02556 
02557 DEFINE_PARSER_METHOD(mnemonic)
02558 {
02559     /* TODO */
02560     return 1;
02561 }
02562 DEFINE_PARSER_METHOD(pattern)
02563 {
02564     /* TODO */
02565     return 1;
02566 }
02567 DEFINE_PARSER_METHOD(defpattern)
02568 {
02569     /* TODO */
02570     return 1;
02571 }
02572 
02573 /*
02574   generic parser
02575  */
02576 
02577 static int
02578 PCE_generic_inst_parser(
02579     EIMIL_data *ped,
02580     EIMIL_attrs *patr,
02581     enum EIMIL_TAG_TYPE type,
02582     UTF8 *pchars,
02583     void **pprivate
02584 )
02585 {
02586     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02587     PCE_inst_template *pit = (PCE_inst_template*) ped->pcommon->ps.pcet->private;
02588 
02589     switch (type) {
02590       case EIMIL_START_TAG:
02591        pcx = PCE_parser_generic_start(ped, pcx, pit->result);
02592        if (!pcx) return 0;
02593        PCE_SET_REQUIRED_TYPES(pcx, pit);
02594        if ((pit->newmode & PCE_ONLY_IN_MAIN_STATEMENT)
02595           && !(pcx->mode & PCE_IN_MAIN)) {
02596           EIMIL_set_error_pt(ped, NULL, "`%s' element must be in `main' element.",
02597                            ped->pcommon->ps.pcet->name);
02598           return 0;
02599        }
02600        pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, pit->newmode);
02601        *pprivate = pcx;
02602        return 1;
02603 
02604       case EIMIL_CHARDATA:
02605        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
02606        return 0;
02607 
02608       case EIMIL_END_TAG:
02609        if (pit->code_type == PCE_CODE_INST)
02610           pcx = PCE_parser_generic_end(ped, pcx, PCE_new_code_for_inst(pit->handler));
02611        else
02612           pcx = PCE_parser_generic_end(ped, pcx, PCE_new_code_for_etc(pit->code_type));
02613        if (!pcx) return 0;
02614        return 1;
02615 
02616       default:
02617        EIMIL_set_error_pt(ped, NULL, "Unknown error.");
02618     }
02619 
02620     return 0;
02621 }
02622 
02623 /*
02624   return element
02625  */
02626 
02627 DEFINE_PARSER_METHOD(return)
02628 {
02629     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02630 
02631     if (type == EIMIL_START_TAG) {
02632        int r;
02633        if (!(pcx->mode & PCE_IN_DEFUN)) {
02634            PCE_set_error(ped, PCE_PARSE_RETURN_IN_DEFUN_ERROR);
02635        }
02636        r = PCE_generic_inst_parser(ped, patr, type, pchars, pprivate);
02637        ASSERT(pcx->pf);
02638        pcx->required_type[0] = pcx->pf->rettype;
02639        return r;
02640     }
02641     return PCE_generic_inst_parser(ped, patr, type, pchars, pprivate);
02642 }
02643 
02644 /*
02645   flow control
02646  */
02647 
02648 DEFINE_PARSER_METHOD(if)
02649 {
02650     int id;
02651     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02652 
02653     switch (type) {
02654       case EIMIL_START_TAG:
02655        id = PCE_make_label(pcx);
02656        if (id < 0) return 0;
02657        pcx = PCE_parser_generic_start(ped, pcx, EIMIL_TYPE_NONE);
02658        if (!pcx) return 0;
02659        pcx->required_type[0] = EIMIL_TYPE_ANY;
02660        pcx->required_type[1] = EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1;
02661        pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, PCE_IN_IF);
02662        pcx->labelid = pcx->labelid2 = id;
02663        *pprivate = pcx;
02664        return 1;
02665 
02666       case EIMIL_CHARDATA:
02667        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
02668        return 0;
02669 
02670       case EIMIL_END_TAG:
02671       {
02672          int st_label_id = pcx->labelid2;
02673          pcx = PCE_parser_jmp_end(ped, pcx, PCE_COND_NOT_JMP_END, 0);
02674          if (!pcx) return 0;
02675          PCE_mark_label_yet(pcx, st_label_id, pcx->pc, 1);
02676          return 1;
02677       }
02678       default:
02679         break;
02680     }
02681 
02682     return 0;
02683 }
02684 
02685 DEFINE_PARSER_METHOD(else)
02686 {
02687     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02688 
02689     switch (type) {
02690       case EIMIL_START_TAG:
02691       {
02692          int id;
02693          PCE_code *pc;
02694 
02695          id = PCE_make_label(pcx);
02696          if (id < 0) return 0;
02697          pc = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_JMP, id);
02698          if (!pc) return 0;
02699          PCE_ADD_CODE(pcx, pc);
02700          PCE_mark_label(pcx, pcx->labelid, pc, 1);
02701          pcx->labelid2 = id;
02702          return 1;
02703       }
02704 
02705       case EIMIL_CHARDATA:
02706        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
02707        return 0;
02708 
02709       case EIMIL_END_TAG:
02710        return 1;
02711 
02712       default:
02713        break;
02714     }
02715 
02716     return 0;
02717 }
02718 
02719 DEFINE_PARSER_METHOD(while)
02720 {
02721     int id;
02722     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02723 
02724     switch (type) {
02725       case EIMIL_START_TAG:
02726        id = PCE_make_label(pcx);
02727        if (id < 0) return 0;
02728        pcx = PCE_parser_generic_start(ped, pcx, EIMIL_TYPE_NONE);
02729        if (!pcx) return 0;
02730        pcx->required_type[0] = EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1;
02731        pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, PCE_IN_IF);
02732        pcx->labelid = id;
02733        *pprivate = pcx;
02734        return 1;
02735 
02736       case EIMIL_CHARDATA:
02737        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
02738        return 0;
02739 
02740       case EIMIL_END_TAG:
02741       {
02742          int st_label_id = pcx->labelid;
02743          pcx = PCE_parser_jmp_end(ped, pcx, PCE_COND_NOT_JMP_END, 1);
02744          if (!pcx) return 0;
02745          PCE_mark_label_yet(pcx, st_label_id, pcx->pc, 1);
02746          return 1;
02747       }
02748 
02749       default:
02750         break;
02751     }
02752 
02753     return 0;
02754 }
02755 
02756 DEFINE_PARSER_METHOD(case)
02757 {
02758     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02759 
02760     switch (type) {
02761       case EIMIL_START_TAG:
02762       {
02763          int id;
02764 
02765          id = PCE_make_label(pcx);
02766          if (id < 0) return 0;
02767          pcx = PCE_parser_generic_start(ped, pcx, EIMIL_TYPE_NONE);
02768          if (!pcx) return 0;
02769          pcx->required_type[0] = EIMIL_TYPE_ANY;
02770          pcx->required_type[1] = EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1;
02771          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, PCE_IN_SELECT);
02772          pcx->labelid2 = id;
02773          *pprivate = pcx;
02774          return 1;
02775       }
02776 
02777       case EIMIL_CHARDATA:
02778        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
02779        return 0;
02780 
02781       case EIMIL_END_TAG:
02782        pcx = PCE_parser_select_case_end(ped, pcx);
02783        if (!pcx) return 0;
02784        return 1;
02785       default:
02786        break;
02787     }
02788 
02789     return 0;
02790 }
02791 
02792 DEFINE_PARSER_METHOD(default)
02793 {
02794     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02795 
02796     switch (type) {
02797       case EIMIL_START_TAG:
02798       {
02799          int id;
02800 
02801          id = PCE_make_label(pcx);
02802          if (id < 0) return 0;
02803          pcx = PCE_parser_generic_start(ped, pcx, EIMIL_TYPE_NONE);
02804          if (!pcx) return 0;
02805          pcx->required_type[0] = EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1;
02806          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, PCE_IN_SELECT);
02807          pcx->labelid2 = id;
02808          *pprivate = pcx;
02809          return 1;
02810       }
02811 
02812       case EIMIL_CHARDATA:
02813        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
02814        return 0;
02815 
02816       case EIMIL_END_TAG:
02817        pcx = PCE_parser_select_default_end(ped, pcx);
02818        if (!pcx) return 0;
02819        return 1;
02820 
02821       default:
02822        break;
02823     }
02824 
02825     return 0;
02826 }
02827 
02828 DEFINE_PARSER_METHOD(select)
02829 {
02830     int id;
02831     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02832 
02833     switch (type) {
02834       case EIMIL_START_TAG:
02835        id = PCE_make_label(pcx); /* label for the tail.  */
02836        if (id < 0) return 0;
02837        pcx = PCE_parser_generic_start(ped, pcx, EIMIL_TYPE_NONE);
02838        if (!pcx) return 0;
02839        pcx->required_type[0] = EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1;
02840        pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, PCE_IN_SELECT);
02841        pcx->labelid = id;
02842        pcx->pc_head = NULL; /* Used for the head jmp table(s). */
02843        *pprivate = pcx;
02844        return 1;
02845 
02846       case EIMIL_CHARDATA:
02847        return 0;
02848 
02849       case EIMIL_END_TAG:
02850       {
02851          pcx = PCE_parser_select_end(ped, pcx);
02852          if (!pcx) return 0;
02853          return 1;
02854       }
02855       default:
02856        break;
02857     }
02858 
02859     return 0;
02860 }
02861 
02862 /*
02863   SEH
02864 */
02865 
02866 DEFINE_PARSER_METHOD(try)
02867 {
02868     /* TODO */
02869     return 1;
02870 }
02871 
02872 /*
02873   inst with attr.
02874 */
02875 
02876 /* exc attr */
02877 static EIMIL_symbol*
02878 PCE_attr_get_exception_symbol(
02879     EIMIL_data *ped,
02880     PCE_parse_context *pcx,
02881     EIMIL_attrs *patr
02882 )
02883 {
02884     for (; patr->name;patr++) {
02885        if (strcmp(patr->name, "exc") == 0) {
02886            EIMIL_symbol *psym;
02887            UTF8 *name;
02888            if (!EIMIL_get_attr_nmtokens(patr->val, &name)) {
02889               EIMIL_set_error_pt(ped, NULL, "Unrecogized keyword in `v'");
02890               return NULL;
02891            }
02892            psym = PCE_get_exception(ped, pcx, name);
02893            free(name);
02894            if (!psym) return NULL;
02895            return psym;
02896        }
02897     }
02898     return NULL;
02899 }
02900 DEFINE_PARSER_METHOD(throw)
02901 {
02902     if (type != EIMIL_EMPTY_TAG) return 0;
02903 
02904     {
02905        PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02906 
02907        EIMIL_symbol *psym;
02908        PCE_code *pc, *pc_arg;
02909          
02910        psym = PCE_attr_get_exception_symbol(ped, pcx, patr);
02911 
02912        pc_arg = PCE_new_code_for_symbol(pcx->psym);
02913        if (!pc_arg) {
02914            PCE_set_error(ped, PCE_MEMORY_ERROR);
02915            return 0;
02916        }
02917        pc = PCE_new_code_for_inst(PCE_throw_exec);
02918        if (!pc) {
02919            PCE_set_error(ped, PCE_MEMORY_ERROR);
02920            return 0;
02921        }
02922        pc->parg = pc_arg;
02923        PCE_ADD_CODE(pcx, pc);
02924     }
02925 
02926     return 1;
02927 }
02928 
02929 DEFINE_PARSER_METHOD(catch)
02930 {
02931     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
02932 
02933     switch (type) {
02934       case EIMIL_START_TAG:
02935       {
02936          EIMIL_symbol *psym;
02937          
02938          psym = PCE_attr_get_exception_symbol(ped, pcx, patr);
02939          pcx = PCE_parser_generic_start(ped, pcx, EIMIL_TYPE_NONE);
02940          if (!pcx) return 0;
02941          pcx->required_type[0] = EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1;
02942          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, 0);
02943          pcx->psym = psym;
02944          *pprivate = pcx;
02945          return 1;
02946       }
02947       case EIMIL_CHARDATA:
02948        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
02949        return 0;
02950 
02951       case EIMIL_END_TAG:
02952       {
02953          PCE_code *pc = PCE_new_code_for_symbol(pcx->psym);
02954          if (!pc) {
02955              PCE_set_error(ped, PCE_MEMORY_ERROR);
02956              return 0;
02957          }
02958          pcx = PCE_parser_generic_end(ped, pcx,
02959                                    PCE_new_code_for_inst(PCE_catch_exec));
02960          /* Insert EIMIL_exception symbol
02961             to the first argument of `catch'.  */
02962          pc->pnext = pcx->pc->parg;
02963          pcx->pc->parg = pc;
02964          if (!pcx) return 0;
02965          return 1;
02966       }
02967       default:
02968       break;
02969     }
02970 
02971     return 0;
02972 }
02973 
02974 /* exc attr */
02975 static UTF8*
02976 PCE_attr_get_label_symbol(
02977     EIMIL_data *ped,
02978     PCE_parse_context *pcx,
02979     EIMIL_attrs *patr
02980 )
02981 {
02982     for (; patr->name;patr++) {
02983        if (strcmp(patr->name, "to") == 0) {
02984            UTF8 *name;
02985            if (!EIMIL_get_attr_nmtokens(patr->val, &name)) {
02986               EIMIL_set_error_pt(ped, NULL, "Unrecogized keyword in `v'");
02987               return NULL;
02988            }
02989            return name;
02990        }
02991     }
02992     return NULL;
02993 }
02994 DEFINE_PARSER_METHOD(go)
02995 {
02996     int id;
02997     UTF8* labelname;
02998     PCE_code *pc;
02999     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
03000 
03001     ASSERT(type == EIMIL_EMPTY_TAG);
03002 
03003     if (!(pcx->mode & PCE_IN_MAIN)) {
03004        EIMIL_set_error_pt(ped, NULL, "`go' element must be in `main' element.");
03005        return 0;
03006     }
03007 
03008     labelname = PCE_attr_get_label_symbol(ped, pcx, patr);
03009     if (!labelname) return 0;
03010 
03011     id = PCE_lookup_named_label(pcx, labelname);
03012     if (id < 0) {
03013        id = PCE_make_named_label(ped, pcx, labelname);
03014        if (id < 0) {
03015            free(labelname);
03016            return 0;
03017        }
03018     }
03019     free(labelname);
03020     pc = PCE_new_code_for_jmp(PCE_CODE_UNRESOLVED_JMP, id);
03021     PCE_ADD_CODE(pcx, pc);
03022 
03023     return 1;
03024 }
03025 
03026 DEFINE_PARSER_METHOD(label)
03027 {
03028     int id;
03029     UTF8* labelname;
03030     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
03031 
03032     ASSERT(type == EIMIL_EMPTY_TAG);
03033 
03034     if (!(pcx->mode & PCE_IN_MAIN)) {
03035        EIMIL_set_error_pt(ped, NULL, "`label' element must be in `main' element.");
03036        return 0;
03037     }
03038 
03039     labelname = PCE_attr_get_label_symbol(ped, pcx, patr);
03040     if (!labelname) return 0;
03041 
03042     id = PCE_lookup_named_label(pcx, labelname);
03043     if (id < 0) {
03044        id = PCE_make_named_label(ped, pcx, labelname);
03045        if (id < 0) return 0;
03046     }
03047     PCE_mark_label(pcx, id, pcx->pc, 1);
03048 
03049     return 1;
03050 }
03051 
03052 DEFINE_PARSER_METHOD(tblkeymaxsize)
03053 {
03054     return 1;
03055 }
03056 
03057 DEFINE_PARSER_METHOD(tblvalmaxsize)
03058 {
03059     return 1;
03060 }
03061 
03062 DEFINE_PARSER_METHOD(tblref)
03063 {
03064     return 1;
03065 }
03066 
03067 /* exc attr */
03068 static EIMIL_symbol*
03069 PCE_attr_get_property_symbol(
03070     EIMIL_data *ped,
03071     PCE_parse_context *pcx,
03072     EIMIL_attrs *patr
03073 )
03074 {
03075     for (; patr->name;patr++) {
03076        if (strcmp(patr->name, "p") == 0) {
03077            EIMIL_symbol *psym;
03078            UTF8 *name;
03079            if (!EIMIL_get_attr_nmtokens(patr->val, &name)) {
03080               EIMIL_set_error_pt(ped, NULL, "Unrecogized keyword in `p'");
03081               return NULL;
03082            }
03083            psym = PCE_get_property(ped, pcx, name);
03084            return psym;
03085        }
03086     }
03087     return NULL;
03088 }
03089 DEFINE_PARSER_METHOD(makeprop)
03090 {
03091     if (type != EIMIL_EMPTY_TAG) return 0;
03092 
03093     {
03094        PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
03095 
03096        EIMIL_symbol *psym;
03097        PCE_code *pc, *pc_arg;
03098          
03099        psym = PCE_attr_get_property_symbol(ped, pcx, patr);
03100 
03101        pc_arg = PCE_new_code_for_symbol(pcx->psym);
03102        if (!pc_arg) {
03103            PCE_set_error(ped, PCE_MEMORY_ERROR);
03104            return 0;
03105        }
03106        pc = PCE_new_code_for_inst(PCE_makeprop_exec);
03107        if (!pc) {
03108            PCE_set_error(ped, PCE_MEMORY_ERROR);
03109            return 0;
03110        }
03111        pc->parg = pc_arg;
03112        PCE_ADD_CODE(pcx, pc);
03113     }
03114 
03115     return 1;
03116 }
03117 
03118 DEFINE_PARSER_METHOD(getmprop)
03119 {
03120     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
03121 
03122     switch (type) {
03123       case EIMIL_START_TAG:
03124       {
03125          EIMIL_symbol *psym;
03126          
03127          psym = PCE_attr_get_property_symbol(ped, pcx, patr);
03128          pcx = PCE_parser_generic_start(ped, pcx, EIMIL_TYPE_NONE);
03129          if (!pcx) return 0;
03130          pcx->required_type[0] = EIMIL_TYPE_MTEXT;
03131          pcx->required_type[1] = EIMIL_TYPE_NUMBER;
03132          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, 0);
03133          pcx->psym = psym;
03134          *pprivate = pcx;
03135          return 1;
03136       }
03137       case EIMIL_CHARDATA:
03138        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
03139        return 0;
03140 
03141       case EIMIL_END_TAG:
03142       {
03143          PCE_code *pc = PCE_new_code_for_symbol(pcx->psym);
03144          if (!pc) {
03145              PCE_set_error(ped, PCE_MEMORY_ERROR);
03146              return 0;
03147          }
03148          pcx = PCE_parser_generic_end(ped, pcx,
03149                                    PCE_new_code_for_inst(PCE_getmprop_exec));
03150          /* Insert EIMIL_exception symbol
03151             to the first argument of `catch'.  */
03152          pc->pnext = pcx->pc->parg;
03153          pcx->pc->parg = pc;
03154          if (!pcx) return 0;
03155          return 1;
03156       }
03157       default:
03158         break;
03159     }
03160 
03161     return 0;
03162 }
03163 
03164 DEFINE_PARSER_METHOD(findmprop)
03165 {
03166     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
03167 
03168     switch (type) {
03169       case EIMIL_START_TAG:
03170       {
03171          EIMIL_symbol *psym;
03172          
03173          psym = PCE_attr_get_property_symbol(ped, pcx, patr);
03174          pcx = PCE_parser_generic_start(ped, pcx, EIMIL_TYPE_NONE);
03175          if (!pcx) return 0;
03176          pcx->required_type[0] = EIMIL_TYPE_MTEXT;
03177          pcx->required_type[1] = EIMIL_TYPE_NUMBER;
03178          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, 0);
03179          pcx->psym = psym;
03180          *pprivate = pcx;
03181          return 1;
03182       }
03183       case EIMIL_CHARDATA:
03184        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
03185        return 0;
03186 
03187       case EIMIL_END_TAG:
03188       {
03189          PCE_code *pc = PCE_new_code_for_symbol(pcx->psym);
03190          if (!pc) {
03191              PCE_set_error(ped, PCE_MEMORY_ERROR);
03192              return 0;
03193          }
03194          pcx = PCE_parser_generic_end(ped, pcx,
03195                                    PCE_new_code_for_inst(PCE_findmprop_exec));
03196          /* Insert EIMIL_exception symbol
03197             to the first argument of `catch'.  */
03198          pc->pnext = pcx->pc->parg;
03199          pcx->pc->parg = pc;
03200          if (!pcx) return 0;
03201          return 1;
03202       }
03203       default:
03204         break;
03205     }
03206 
03207     return 0;
03208 }
03209 
03210 DEFINE_PARSER_METHOD(interact)
03211 {
03212     return 1;
03213 }
03214 
03215 DEFINE_PARSER_METHOD(match)
03216 {
03217     return 1;
03218 }
03219 
03220 DEFINE_PARSER_METHOD(forward)
03221 {
03222     return 1;
03223 }
03224 
03225 DEFINE_PARSER_METHOD(send)
03226 {
03227     return 1;
03228 }
03229 
03230 /* v attr */
03231 static EIMIL_symbol*
03232 PCE_attr_get_variable_symbol(
03233     EIMIL_data *ped,
03234     PCE_parse_context *pcx,
03235     EIMIL_attrs *patr
03236 )
03237 {
03238     for (; patr->name;patr++) {
03239        if (strcmp(patr->name, "v") == 0) {
03240            EIMIL_symbol *psym;
03241            UTF8 *name;
03242            if (!EIMIL_get_attr_nmtokens(patr->val, &name)) {
03243               EIMIL_set_error_pt(ped, NULL, "Unrecogized keyword in `v'");
03244               return NULL;
03245            }
03246            psym = PCE_get_variable(ped, pcx, name);
03247            free(name);
03248            if (!psym) return NULL;
03249            return psym;
03250        }
03251     }
03252     return NULL;
03253 }
03254 
03255 DEFINE_PARSER_METHOD(set)
03256 {
03257     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
03258 
03259     switch (type) {
03260       case EIMIL_START_TAG:
03261       {
03262          EIMIL_symbol *psym;
03263          
03264          psym = PCE_attr_get_variable_symbol(ped, pcx, patr);
03265          if (!psym) {
03266              EIMIL_set_error_pt(ped, NULL,
03267                              "invalid `v' attribute in `set' element.");
03268              return 0;
03269          }
03270          pcx = PCE_parser_generic_start(ped, pcx, psym->obj.v.type);
03271          if (!pcx) return 0;
03272          pcx->required_type[0] = psym->obj.v.type | EIMIL_TYPE_NIL;
03273          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, 0);
03274          pcx->psym = psym;
03275          *pprivate = pcx;
03276          return 1;
03277       }
03278       case EIMIL_CHARDATA:
03279        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
03280        return 0;
03281 
03282       case EIMIL_END_TAG:
03283       {
03284          PCE_code *pc = PCE_new_code_for_symbol(pcx->psym);
03285          if (!pc) {
03286              PCE_set_error(ped, PCE_MEMORY_ERROR);
03287              return 0;
03288          }
03289          PCE_ADD_CODE(pcx, pc);
03290          pcx = PCE_parser_generic_end(ped, pcx,
03291                                    PCE_new_code_for_inst(PCE_set_exec));
03292          if (!pcx) return 0;
03293          return 1;
03294       }
03295       default:
03296           break;
03297     }
03298 
03299     return 0;
03300 }
03301 
03302 /* f attr */
03303 static EIMIL_symbol*
03304 PCE_attr_get_function_symbol(
03305     EIMIL_data *ped,
03306     PCE_parse_context *pcx,
03307     EIMIL_attrs *patr
03308 )
03309 {
03310     for (; patr->name;patr++) {
03311        if (strcmp(patr->name, "f") == 0) {
03312            EIMIL_symbol *psym;
03313            UTF8 *name;
03314            if (!EIMIL_get_attr_nmtokens(patr->val, &name)) {
03315               EIMIL_set_error_pt(ped, NULL, "Unrecogized keyword in `v'");
03316               return NULL;
03317            }
03318            psym = PCE_get_function(ped, pcx, name);
03319            free(name);
03320            if (!psym) return NULL;
03321            return psym;
03322        }
03323     }
03324     return NULL;
03325 }
03326 DEFINE_PARSER_METHOD(e)
03327 {
03328     PCE_parse_context *pcx = (PCE_parse_context*) *pprivate;
03329 
03330     switch (type) {
03331       case EIMIL_START_TAG:
03332       {
03333          EIMIL_symbol *psym;
03334          PCE_function *pf;
03335 
03336          psym = PCE_attr_get_function_symbol(ped, pcx, patr);
03337          pf = (PCE_function*) psym->obj.f.def;
03338          pcx = PCE_parser_generic_start(ped, pcx, pf->rettype);
03339          if (!pcx) return 0;
03340          pcx->mode = PCE_NEW_PARSER_CONTEXT_MODE(pcx, PCE_IN_E);
03341          pcx->pf = pf;
03342          *pprivate = pcx;
03343          return 1;
03344       }
03345       case EIMIL_CHARDATA:
03346        if (PCE_parse_token(ped, pcx, pchars) == PCE_SUCCESS) return 1;
03347        return 0;
03348 
03349       case EIMIL_END_TAG:
03350        pcx = PCE_parser_generic_end(ped, pcx,
03351                                 PCE_new_code_for_function(pcx->pf));
03352        if (!pcx) return 0;
03353        return 1;
03354 
03355       default:
03356        break;
03357     }
03358 
03359     return 0;
03360 }
03361 
03362 /*
03363   PCE root element
03364 */
03365 
03366 DEFINE_PARSER_METHOD(PCE)
03367 {
03368     PCE_parse_context *pcx;
03369 
03370     if (type == EIMIL_START_TAG) {
03371        PCE_context *pctx = (PCE_context*) *pprivate;
03372 
03373        pcx = PCE_new_parse_context(ped);
03374        if (!pcx) return 0;
03375        if (PCE_initialize_labels(pcx) != PCE_SUCCESS) return 0;
03376        pcx->pctx = pctx;
03377        pcx->required_type[0] = EIMIL_TYPE_ANY | EIMIL_TYPE_OPTION1;
03378        *pprivate = pcx;
03379        return 1;
03380     } else {
03381        pcx = (PCE_parse_context*) *pprivate;
03382        ASSERT(!pcx->pnext);
03383        PCE_finalize_labels(ped, pcx);
03384        /*
03385          Almost all of the work on pcx->pctx should be done in the
03386          subelement parsers.  Thus currently do nothing in the root parser.
03387        */
03388        free(pcx);
03389        return 1;
03390     }
03391 
03392     return 0;
03393 }
03394 
03395 /****************************************
03396             factory method
03397  ****************************************/
03398 
03399 static void
03400 PCE_SEH_free(
03401     PCE_SEH_block *pseh
03402 );
03403 
03404 static void
03405 PCE_destruct_context(
03406     PCE_context *pctx
03407 )
03408 {
03409     EIMIL_free_dictionary(pctx->pdic);
03410     {
03411        PCE_SEH_block *pseh1, *pseh2;
03412        for (pseh1 = pctx->pseh; pseh1; ) {
03413            pseh2 = pseh1->pnext;
03414            PCE_SEH_free(pseh1);
03415            pseh1 = pseh2;
03416        }
03417     }
03418     free(pctx);
03419 }
03420 
03421 static void
03422 PCE_destruct_data(
03423     PCE_data *pd
03424 )
03425 {
03426     PCE_free_code(pd->pcode);
03427     free(pd);
03428 }
03429 
03430 
03431 static void*
03432 PCE_handler(
03433     enum EIMIL_ENGINE_COMMAND m,
03434     EIMIL_data *ped,
03435     void *class_private,
03436     void *handle_private
03437 )
03438 {
03439     PCE_data *pd = (PCE_data*) class_private;
03440     PCE_context *ph = (PCE_context*) handle_private;
03441 
03442     switch (m) {
03443       case EIMIL_ENGINE_INSTANCIATE:
03444        pd = (PCE_data*) malloc(sizeof(PCE_data));
03445        if (!pd) return NULL;
03446        memset(pd, 0, sizeof(*pd));
03447        return pd;
03448        
03449       case EIMIL_ENGINE_DUPLICATE:
03450        if (!ph) {
03451           ph = (PCE_context*) malloc(sizeof(PCE_context));
03452           if (!ph) return NULL;
03453           memset(ph, 0, sizeof(PCE_context));
03454           ph->ped = ped;
03455           PCE_new_dictionary(ped, ph);
03456           ph->ppce_data = pd;
03457           if (!ph->pdic) {
03458               free(ph);
03459               return NULL;
03460           }
03461           return ph;
03462        } else {
03463           PCE_context *pnh;
03464           pnh = (PCE_context*) malloc(sizeof(PCE_context));
03465           if (!pnh) return NULL;
03466           memset(pnh, 0, sizeof(PCE_context));
03467           pnh->ped = ped;
03468           pnh->pdic = EIMIL_duplicate_dictionary(ph->pdic);
03469           pnh->ppce_data = ph->ppce_data;
03470           if (!pnh->pdic) {
03471               free(pnh);
03472               return NULL;
03473           }
03474           return pnh;
03475        }
03476 
03477       case EIMIL_ENGINE_DESTRUCT:
03478        PCE_destruct_context(ph);
03479        return NULL;
03480        
03481       case EIMIL_ENGINE_UNINSTANCIATE:
03482        PCE_destruct_data(pd);
03483        return NULL;
03484     }
03485 
03486     return NULL;
03487 }
03488 
03489 /********************************************************************************
03490                           PCE execution part
03491 *********************************************************************************/
03492 
03493 /****************************************
03494                    SEH
03495  ****************************************/
03496 
03497 static enum PCE_ERROR_CODE
03498 PCE_SEH_start(
03499     PCE_context *pctx
03500 )
03501 {
03502     PCE_SEH_block* pseh = (PCE_SEH_block*) malloc(sizeof(PCE_SEH_block));
03503     if (!pseh) return PCE_MEMORY_ERROR;
03504     memset(pseh, 0, sizeof(PCE_SEH_block));
03505     pseh->pnext = pctx->pseh;
03506     pctx->pseh = pseh;
03507     return PCE_SUCCESS;
03508 }
03509 
03510 static void
03511 PCE_SEH_free(
03512     PCE_SEH_block *pseh
03513 )
03514 {
03515     PCE_SEH_catchblock *pc1, *pc2;
03516 
03517     for (pc1 = pseh->pcatchers; pc1; ) {
03518        pc2 = pc1->pnext;
03519        free(pc1);
03520        pc1 = pc2;
03521     }
03522     free(pseh);
03523 }
03524 
03525 static enum PCE_ERROR_CODE
03526 PCE_SEH_catch(
03527     PCE_context *pctx,
03528     enum PCE_ERROR_CODE e,
03529     PCE_SEH_CATCH_FUNCTION f,
03530     void *arg
03531 )
03532 {
03533     PCE_SEH_catchblock *pc;
03534     PCE_SEH_block *pseh = pctx->pseh;
03535 
03536     pc = (PCE_SEH_catchblock*) malloc(sizeof(PCE_SEH_catchblock));
03537     if (!pc) return PCE_MEMORY_ERROR;
03538     pc->pnext = pseh->pcatchers;
03539     pc->type = e;
03540     pc->pcfs = f;
03541     pc->catcharg = arg;
03542     pseh->pcatchers = pc;
03543 
03544     return PCE_SUCCESS;
03545 }
03546 
03547 static enum PCE_ERROR_CODE
03548 PCE_SEH_try(
03549     PCE_context *pctx,
03550     PCE_SEH_TRY_FUNCTION tf,
03551     void *arg
03552 )
03553 {
03554     int ecode;
03555     enum PCE_ERROR_CODE r;
03556     PCE_SEH_block *pseh = pctx->pseh;
03557 
03558     if ((ecode = setjmp(pseh->jmp)) != 0) {
03559        PCE_SEH_catchblock *pcb;
03560 
03561        PCE_SEH_block *psehh1, *psehh2;
03562        for (psehh1 = pctx->pseh; psehh1 != pseh; ) {
03563            psehh2 = psehh1->pnext;
03564            PCE_SEH_free(psehh1);
03565            psehh1 = psehh2;
03566        }
03567        for (pcb = pseh->pcatchers; pcb; pcb = pcb->pnext) {
03568            if ((pcb->type == PCE_ANY_ERROR)
03569               || (ecode == pcb->type)) {
03570               void *throwarg = pseh->arg;
03571               void *catcharg = pcb->catcharg;
03572               PCE_SEH_CATCH_FUNCTION pcfs = pcb->pcfs;
03573               pctx->pseh = pseh->pnext;
03574               PCE_SEH_free(pseh);
03575               r = (*pcfs)(pctx, ecode, throwarg, catcharg);
03576               return r;
03577            }
03578        }
03579 
03580        /* fail to find out any handlers,
03581           thus propagate the exception.  */
03582        if (!pseh->pnext) abort();
03583        pseh->pnext->arg = pseh->arg;
03584        pctx->pseh = pseh->pnext;
03585        PCE_SEH_free(pseh);
03586        longjmp(pctx->pseh->jmp, ecode);
03587     } else {
03588        r = (*tf)(pctx, arg);
03589     }
03590 
03591     pctx->pseh = pseh->pnext;
03592     PCE_SEH_free(pseh);
03593 
03594     return r;
03595 }
03596 
03597 static void
03598 PCE_SEH_throw(
03599     PCE_context *pctx,
03600     int ecode,
03601     void *arg
03602 )
03603 {
03604     PCE_SEH_block *pseh = pctx->pseh;
03605     pseh->arg = arg;
03606     longjmp(pseh->jmp, ecode);
03607 }
03608 
03609 /****************************************
03610           Expression Evaluation
03611  ****************************************/
03612 
03613 static EIMIL_value*
03614 PCE_call(
03615     PCE_context *pctx,
03616     PCE_function *pf,
03617     PCE_code *parg
03618 );
03619 
03620 static EIMIL_value*
03621 PCE_eval(
03622     PCE_context *pctx,
03623     PCE_code *pc
03624 )
03625 {
03626     EIMIL_value *pv;
03627 
03628     for (;;) {
03629        if (!pc) break;
03630        switch (pc->type) {
03631          case PCE_CODE_VALUE:
03632           pv = pc->val.pv;
03633           pctx->pcur = pc->pnext;
03634           return pv;
03635          case PCE_CODE_SYMBOL:
03636           pv = PCE_symbol_value(pctx, pc);
03637           pctx->pcur = pc->pnext;
03638           return pv;
03639 
03640          case PCE_CODE_JMP:
03641           pc = pctx->pcur = pc->val.pc_to;
03642           continue;
03643 
03644          case PCE_CODE_COND_JMP:
03645           pv = PCE_eval(pctx, pc->parg);
03646           if (pv) {
03647               EIMIL_REFCHECK(*pv);
03648               pc = pctx->pcur = pc->val.pc_to;
03649           } else {
03650               pc = pctx->pcur = pc->pnext;
03651           }
03652           continue;
03653 
03654          case PCE_CODE_COND_NOT_JMP:
03655           pv = PCE_eval(pctx, pc->parg);
03656           if (pv) {
03657               EIMIL_REFCHECK(*pv);
03658               pc = pctx->pcur = pc->pnext;
03659           } else {
03660               pc = pctx->pcur = pc->val.pc_to;
03661           }
03662           continue;
03663 
03664          case PCE_CODE_FUNCTION:
03665           pv = PCE_call(pctx, pc->val.pf, pc->parg);
03666           pctx->pcur = pc->pnext;
03667           return pv;
03668 
03669          default:
03670           ASSERT(pc->type == PCE_CODE_INST);
03671           pctx->pcur = pc;
03672           pv = (*pc->val.h)(pctx);
03673           pctx->pcur = pc->pnext;
03674 
03675           return pv;
03676        }
03677     }
03678 
03679     return NULL;
03680 }
03681 
03682 enum PCE_ERROR_CODE
03683 PCE_execute_loop(
03684     PCE_context *pctx,
03685     void *arg
03686 )
03687 {
03688     PCE_code *pc;
03689     EIMIL_value *pv;
03690 
03691     if (!pctx->pcur) {
03692        pc = pctx->ppce_data->pcode;
03693        ASSERT(pc->type == PCE_CODE_MAIN);
03694        pc = pc->parg;
03695        pctx->pcur = pc;
03696     }
03697     for (;;){
03698        pc = pctx->pcur;
03699        if (!pc) break;
03700        pv = PCE_eval(pctx, pc);
03701        if (pv) EIMIL_REFCHECK(*pv);
03702     }
03703 
03704     return PCE_SUCCESS;
03705 }
03706 
03707 static void
03708 PCE_bind_function_arg(
03709     PCE_context *pctx,
03710     PCE_function *pf,
03711     PCE_code *parg
03712 )
03713 {
03714     int i;
03715     PCE_funcproto *pfp;
03716     EIMIL_value *pv;
03717     int idx = pctx->depth++;
03718 
03719     pctx->pfuncdic[idx] = pf->pdic;
03720     for (i = 0, pfp = pf->pfp; i < pf->nargs; i++, pfp++) {
03721        ASSERT(parg);
03722        pv = PCE_eval(pctx, parg);
03723        pfp->psym->obj.v.pv = pv;
03724        if (pv) EIMIL_ADDREF(*pv);
03725        parg = parg->pnext;
03726     }
03727     pctx->pdic_f = pf->pdic;
03728 
03729     return;
03730 }
03731 
03732 static void
03733 PCE_unbind_function_arg(
03734     PCE_context *pctx,
03735     PCE_function *pf
03736 )
03737 {
03738     int i;
03739     PCE_funcproto *pfp;
03740     EIMIL_value *pv;
03741     int idx = --pctx->depth;
03742 
03743     if (idx == 0)
03744        pctx->pdic_f = NULL;
03745     else
03746        pctx->pdic_f = pctx->pfuncdic[idx - 1];
03747 
03748     for (i = 0, pfp = pf->pfp; i < pf->nargs; i++, pfp++) {
03749        pv = pfp->psym->obj.v.pv;
03750        if (pv) EIMIL_RMREF(*pv);
03751     }
03752 
03753     return;
03754 }
03755 
03756 struct PCE_call_catcharg {
03757     EIMIL_value *pv;
03758     PCE_function *pf;
03759 };
03760 static enum PCE_ERROR_CODE
03761 PCE_call_exception_handler(
03762     PCE_context *pctx,
03763     int ecode,
03764     void *throwarg,
03765     void *catcharg
03766 )
03767 {
03768     struct PCE_call_catcharg *pcarg = (struct PCE_call_catcharg*) catcharg;
03769 
03770     if (ecode == PCE_RETURN_JMP_ERROR) {
03771        pcarg->pv = (EIMIL_value*) throwarg;
03772     } else {
03773        PCE_unbind_function_arg(pctx, pcarg->pf);
03774        PCE_SEH_throw(pctx, ecode, throwarg);
03775     }
03776 
03777     return PCE_SUCCESS;
03778 }
03779 
03780 static EIMIL_value*
03781 PCE_call(
03782     PCE_context *pctx,
03783     PCE_function *pf,
03784     PCE_code *parg
03785 )
03786 {
03787     enum PCE_ERROR_CODE r;
03788     struct PCE_call_catcharg carg;
03789 
03790     if (pctx->depth >= PCE_CALL_MAX_DEPTH) {
03791        PCE_SEH_throw(pctx, PCE_OVER_EVAL_DEPTH_ERROR, NULL);
03792     }
03793 
03794     if (PCE_SEH_start(pctx) != PCE_SUCCESS) return NULL;
03795 
03796     PCE_bind_function_arg(pctx, pf, parg);
03797     carg.pv = NULL;
03798     carg.pf = pf;
03799     if (PCE_SEH_catch(pctx, PCE_ANY_ERROR,
03800                     PCE_call_exception_handler,
03801                     &carg)
03802        != PCE_SUCCESS)
03803        return NULL;
03804 
03805     pctx->pcur = pf->pc;
03806     r = PCE_SEH_try(pctx, PCE_execute_loop, NULL);
03807     PCE_unbind_function_arg(pctx, pf);
03808     if (r == PCE_SUCCESS) return carg.pv;
03809 
03810     return NULL;
03811 }
03812 
03813 /*
03814   Retrieve the argument of current instruction.
03815   Return code:
03816       PCE_SUCCESS
03817             --> Successfully retrieve the value of argument.
03818       PCE_NO_MORE_ARG_ERROR
03819             --> There is no arg of idx.
03820   Exception:
03821       PCE_WRONG_TYPE_ARGUMENT_ERROR
03822  */
03823 static enum PCE_ERROR_CODE
03824 PCE_get_arg(
03825     PCE_context *pctx,
03826     int idx,
03827     int type,
03828     EIMIL_value** ppv
03829 )
03830 {
03831     int i;
03832     EIMIL_value *pv;
03833     PCE_code *pc_orig, *pc;
03834 
03835     pc_orig = pctx->pcur;
03836     pc = pc_orig->parg;
03837     for (i = 0; i < idx; i++) {
03838        if (!pc) break;
03839        pc = pc->pnext;
03840     }
03841     if (!pc) return PCE_NO_MORE_ARG_ERROR;
03842     pv = PCE_eval(pctx, pc);
03843     pctx->pcur = pc_orig;
03844 
03845     if ((type & EIMIL_TYPE_ANY)
03846        || (!pv && (type & EIMIL_TYPE_NIL))
03847        || (pv && ((pv->type & type) != 0))) {
03848        *ppv = pv;
03849        return PCE_SUCCESS;
03850     }
03851 
03852     PCE_SEH_throw(pctx, PCE_WRONG_TYPE_ARGUMENT_ERROR, NULL);
03853     return PCE_UNKNOWN_ERROR;
03854 }
03855 
03856 static EIMIL_symbol*
03857 PCE_get_symbol_arg(
03858     PCE_context *pctx,
03859     int idx,
03860     enum EIMIL_CATEGORY cat
03861 )
03862 {
03863     int i;
03864     EIMIL_symbol *psym;
03865     PCE_code *pc = pctx->pcur;
03866 
03867     pc = pc->parg;
03868     for (i = 0; i < idx; i++) {
03869        if (!pc) {
03870            ERROR_INTERNAL("!!Invalid PCE_code(Too few args).");
03871        }
03872        pc = pc->pnext;
03873     }
03874     ASSERT(pc->type == PCE_CODE_SYMBOL);
03875     psym = PCE_lookup_symbol(pctx, pc);
03876     ASSERT(psym);
03877     ASSERT(psym->cat == cat);
03878 
03879     return psym;
03880 }
03881 
03882 static enum PCE_ERROR_CODE
03883 PCE_get_arg_or_error(
03884     PCE_context *pctx,
03885     int idx,
03886     int type,
03887     EIMIL_value** ppv
03888 )
03889 {
03890     enum PCE_ERROR_CODE r = PCE_get_arg(pctx, idx, type, ppv);
03891     if (r == PCE_NO_MORE_ARG_ERROR) {
03892        PCE_SEH_throw(pctx, PCE_TOO_FEW_ARGUMENTS_ERROR, NULL);
03893     } else if (r != PCE_SUCCESS) {
03894        PCE_SEH_throw(pctx, PCE_UNKNOWN_ERROR, NULL);
03895     }
03896     return r;
03897 }
03898 
03899 static int
03900 PCE_get_arg_totnum(
03901     PCE_context *pctx
03902 )
03903 {
03904     int i;
03905     PCE_code *pc = pctx->pcur;
03906 
03907     for (i = 0, pc = pc->parg; pc; i++, pc = pc->pnext);
03908     return i;
03909 }
03910 
03911 /****************************************
03912           Predefined variables.
03913  ****************************************/
03914 
03915 static void
03916 PCE_set_current_event(
03917     PCE_context *pctx,
03918     EIMIL_value *pv_event
03919 )
03920 {
03921     EIMIL_symbol *psym = pctx->psym_cev;
03922 
03923     psym->obj.v.pv = pv_event;
03924     EIMIL_ADDREF(*pv_event);
03925 
03926     return;
03927 }
03928 
03929 /****************************************
03930           Execution methods.
03931  ****************************************/
03932 
03933 DEFINE_EXEC_METHOD(undo)
03934 {
03935     /* TODO */
03936     return NULL;
03937 }
03938 
03939 DEFINE_EXEC_METHOD(mark_undo)
03940 {
03941     /* TODO */
03942     return NULL;
03943 }
03944 
03945 DEFINE_EXEC_METHOD(try)
03946 {
03947     /* TODO */
03948     return NULL;
03949 }
03950 
03951 DEFINE_EXEC_METHOD(catch)
03952 {
03953     /* TODO */
03954     return NULL;
03955 }
03956 
03957 DEFINE_EXEC_METHOD(throw)
03958 {
03959     /* TODO */
03960     return NULL;
03961 }
03962 
03963 DEFINE_EXEC_METHOD(keycase)
03964 {
03965     /* TODO */
03966     return NULL;
03967 }
03968 
03969 DEFINE_EXEC_METHOD(keymap)
03970 {
03971     /* TODO */
03972     return NULL;
03973 }
03974 
03975 DEFINE_EXEC_METHOD(toggle_preedit)
03976 {
03977     /* TODO */
03978     return NULL;
03979 }
03980 
03981 DEFINE_EXEC_METHOD(toggle_lookup_choice)
03982 {
03983     /* TODO */
03984     return NULL;
03985 }
03986 
03987 DEFINE_EXEC_METHOD(keyeventp)
03988 {
03989     EIMIL_value *pv;
03990 
03991     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_EVENT, &pv);
03992     if (strcmp(pv->v.event.type, "key") == 0)
03993        return EIMIL_construct_bool(1);
03994 
03995     return NULL;
03996 }
03997 
03998 DEFINE_EXEC_METHOD(or)
03999 {
04000     int i;
04001     EIMIL_value *pv;
04002 
04003     for (i = 0; ; i++) {
04004        if (PCE_get_arg(pctx, i, EIMIL_TYPE_ANY, &pv)
04005            == PCE_NO_MORE_ARG_ERROR)
04006            break;
04007        if (pv) return EIMIL_construct_bool(1);
04008     }
04009     return NULL;
04010 }
04011 
04012 DEFINE_EXEC_METHOD(and)
04013 {
04014     int i;
04015     EIMIL_value *pv;
04016 
04017     for (i = 0; ; i++) {
04018        if (PCE_get_arg(pctx, i, EIMIL_TYPE_ANY, &pv)
04019            == PCE_NO_MORE_ARG_ERROR)
04020            break;
04021        if (!pv) return NULL;
04022     }
04023     return EIMIL_construct_bool(1);
04024 }
04025 
04026 DEFINE_EXEC_METHOD(not)
04027 {
04028     EIMIL_value *pv;
04029     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_ANY, &pv);
04030 
04031     if (pv) {
04032        EIMIL_REFCHECK(*pv);
04033        return NULL;
04034     }
04035 
04036     return EIMIL_construct_bool(1);
04037 }
04038 
04039 DEFINE_EXEC_METHOD(gt)
04040 {
04041     EIMIL_value *pv1, *pv2, *pvr;
04042 
04043     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv1);
04044     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv2);
04045 
04046     if (pv1->v.number > pv2->v.number)
04047        pvr = EIMIL_construct_bool(1);
04048     else
04049        pvr = NULL;
04050     EIMIL_REFCHECK(*pv1);
04051     EIMIL_REFCHECK(*pv2);
04052 
04053     return pvr;
04054 }
04055 
04056 DEFINE_EXEC_METHOD(lt)
04057 {
04058     EIMIL_value *pv1, *pv2, *pvr;
04059 
04060     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv1);
04061     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv2);
04062 
04063     if (pv1->v.number < pv2->v.number)
04064        pvr = EIMIL_construct_bool(1);
04065     else
04066        pvr = NULL;
04067     EIMIL_REFCHECK(*pv1);
04068     EIMIL_REFCHECK(*pv2);
04069 
04070     return pvr;
04071 }
04072 
04073 DEFINE_EXEC_METHOD(le)
04074 {
04075     EIMIL_value *pv1, *pv2, *pvr;
04076 
04077     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv1);
04078     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv2);
04079 
04080     if (pv1->v.number <= pv2->v.number)
04081        pvr = EIMIL_construct_bool(1);
04082     else
04083        pvr = NULL;
04084     EIMIL_REFCHECK(*pv1);
04085     EIMIL_REFCHECK(*pv2);
04086 
04087     return pvr;
04088 }
04089 
04090 DEFINE_EXEC_METHOD(ge)
04091 {
04092     EIMIL_value *pv1, *pv2, *pvr;
04093 
04094     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv1);
04095     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv2);
04096 
04097     if (pv1->v.number >= pv2->v.number)
04098        pvr = EIMIL_construct_bool(1);
04099     else
04100        pvr = NULL;
04101     EIMIL_REFCHECK(*pv1);
04102     EIMIL_REFCHECK(*pv2);
04103 
04104     return pvr;
04105 }
04106 
04107 DEFINE_EXEC_METHOD(eql)
04108 {
04109     EIMIL_value *pv1, *pv2, *pvr;
04110 
04111     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv1);
04112     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv2);
04113 
04114     if (pv1->v.number == pv2->v.number)
04115        pvr = EIMIL_construct_bool(1);
04116     else
04117        pvr = NULL;
04118     EIMIL_REFCHECK(*pv1);
04119     EIMIL_REFCHECK(*pv2);
04120 
04121     return pvr;
04122 }
04123 
04124 DEFINE_EXEC_METHOD(propval)
04125 {
04126     int idx;
04127     EIMIL_value *pv_prop, *pv_idx, *pvr;
04128     EIMIL_prop *pprop;
04129 
04130     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_PROP, &pv_prop);
04131     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv_idx);
04132 
04133     pprop = &pv_prop->v.prop;
04134     idx = pv_idx->v.number;
04135     EIMIL_REFCHECK(*pv_idx);
04136     if ((idx < 0) || (pprop->size <= idx)) {
04137        EIMIL_REFCHECK(*pv_prop);
04138        return NULL;
04139     }
04140     pvr = pprop->pvals[idx];
04141 
04142     EIMIL_REFCHECK_GUARD(*pv_prop, *pvr);
04143 
04144     return pvr;
04145 }
04146 
04147 DEFINE_EXEC_METHOD(propsize)
04148 {
04149     EIMIL_value *pv_prop;
04150     EIMIL_prop *pprop;
04151 
04152     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_PROP, &pv_prop);
04153 
04154     pprop = &pv_prop->v.prop;
04155 
04156     return EIMIL_construct_number(pprop->size);
04157 }
04158 
04159 DEFINE_EXEC_METHOD(propmbeg)
04160 {
04161     EIMIL_value *pv_prop;
04162     EIMIL_prop *pprop;
04163 
04164     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_PROP, &pv_prop);
04165 
04166     pprop = &pv_prop->v.prop;
04167 
04168     return EIMIL_construct_number(pprop->st);
04169 }
04170 
04171 DEFINE_EXEC_METHOD(propmend)
04172 {
04173     EIMIL_value *pv_prop;
04174     EIMIL_prop *pprop;
04175 
04176     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_PROP, &pv_prop);
04177 
04178     pprop = &pv_prop->v.prop;
04179 
04180     return EIMIL_construct_number(pprop->end);
04181 }
04182 
04183 DEFINE_EXEC_METHOD(evval)
04184 {
04185     EIMIL_value *pv, *pvr;
04186 
04187     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_EVENT, &pv);
04188 
04189     pvr = pv->v.event.pv_val;
04190     EIMIL_REFCHECK_GUARD(*pv, *pvr);
04191 
04192     return pvr;
04193 }
04194 
04195 DEFINE_EXEC_METHOD(evmod)
04196 {
04197     EIMIL_value *pv, *pvr;
04198 
04199     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_EVENT, &pv);
04200 
04201     pvr = pv->v.event.pv_mod;
04202     EIMIL_REFCHECK_GUARD(*pv, *pvr);
04203 
04204     return pvr;
04205 }
04206 
04207 DEFINE_EXEC_METHOD(strlen)
04208 {
04209     int len;
04210     EIMIL_value *pv_mtext;
04211 
04212     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_MTEXT, &pv_mtext);
04213 
04214     len = pv_mtext->v.mtext.len;
04215     EIMIL_REFCHECK(*pv_mtext);
04216 
04217     return EIMIL_construct_number(len);
04218 }
04219 
04220 DEFINE_EXEC_METHOD(strcmp)
04221 {
04222     int r;
04223     EIMIL_value *pv_mtext1, *pv_mtext2;
04224 
04225     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_MTEXT, &pv_mtext1);
04226     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_MTEXT, &pv_mtext2);
04227 
04228     r = EIMIL_UTF32_strcmp(pv_mtext1->v.mtext.ustr, pv_mtext2->v.mtext.ustr);
04229 
04230     EIMIL_REFCHECK(*pv_mtext1);
04231     EIMIL_REFCHECK(*pv_mtext2);
04232 
04233     return EIMIL_construct_number(r);
04234 }
04235 
04236 DEFINE_EXEC_METHOD(add)
04237 {
04238     int i, n;
04239     EIMIL_value *pv;
04240 
04241     n = 0;
04242     for (i = 0; ; i++) {
04243        if (PCE_get_arg(pctx, i, EIMIL_TYPE_NUMBER, &pv)
04244            == PCE_NO_MORE_ARG_ERROR)
04245            break;
04246        n += pv->v.number;
04247        EIMIL_REFCHECK(*pv);
04248     }
04249     pv = EIMIL_construct_number(n);
04250     if (!pv) PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04251 
04252     return pv;
04253 }
04254 
04255 DEFINE_EXEC_METHOD(sub)
04256 {
04257     int i, n;
04258     EIMIL_value *pv;
04259 
04260     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv);
04261     n = pv->v.number;
04262     EIMIL_REFCHECK(*pv);
04263     for (i = 1; ; i++) {
04264        if (PCE_get_arg(pctx, i, EIMIL_TYPE_NUMBER, &pv)
04265            == PCE_NO_MORE_ARG_ERROR)
04266            break;
04267        n -= pv->v.number;
04268        EIMIL_REFCHECK(*pv);
04269     }
04270     pv = EIMIL_construct_number(n);
04271     if (!pv) PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04272 
04273     return pv;
04274 }
04275 
04276 DEFINE_EXEC_METHOD(mul)
04277 {
04278     int i, n;
04279     EIMIL_value *pv;
04280 
04281     n = 1;
04282     for (i = 0; ; i++) {
04283        if (PCE_get_arg(pctx, i, EIMIL_TYPE_NUMBER, &pv)
04284            == PCE_NO_MORE_ARG_ERROR)
04285            break;
04286        n *= pv->v.number;
04287        EIMIL_REFCHECK(*pv);
04288     }
04289     pv = EIMIL_construct_number(n);
04290     if (!pv) PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04291 
04292     return pv;
04293 }
04294 
04295 DEFINE_EXEC_METHOD(div)
04296 {
04297     int i, n;
04298     EIMIL_value *pv;
04299 
04300     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv);
04301     n = pv->v.number;
04302     EIMIL_REFCHECK(*pv);
04303     for (i = 1; ; i++) {
04304        if (PCE_get_arg(pctx, i, EIMIL_TYPE_NUMBER, &pv)
04305            == PCE_NO_MORE_ARG_ERROR)
04306            break;
04307        n /= pv->v.number;
04308        EIMIL_REFCHECK(*pv);
04309     }
04310     pv = EIMIL_construct_number(n);
04311     if (!pv) PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04312 
04313     return pv;
04314 }
04315 
04316 DEFINE_EXEC_METHOD(mod)
04317 {
04318     int i, n;
04319     EIMIL_value *pv;
04320 
04321     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv);
04322     n = pv->v.number;
04323     EIMIL_REFCHECK(*pv);
04324     for (i = 1; ; i++) {
04325        if (PCE_get_arg(pctx, i, EIMIL_TYPE_NUMBER, &pv)
04326            == PCE_NO_MORE_ARG_ERROR)
04327            break;
04328        n %= pv->v.number;
04329        EIMIL_REFCHECK(*pv);
04330     }
04331     pv = EIMIL_construct_number(n);
04332     if (!pv) PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04333 
04334     return pv;
04335 }
04336 
04337 DEFINE_EXEC_METHOD(bor)
04338 {
04339     int i, n;
04340     EIMIL_value *pv;
04341 
04342     if (PCE_get_arg(pctx, 0, EIMIL_TYPE_NUMBER, &pv)
04343        == PCE_NO_MORE_ARG_ERROR) {
04344        PCE_SEH_throw(pctx, PCE_TOO_FEW_ARGUMENTS_ERROR, NULL);
04345     }
04346     n = pv->v.number;
04347     EIMIL_REFCHECK(*pv);
04348     for (i = 1; ; i++) {
04349        if (PCE_get_arg(pctx, i, EIMIL_TYPE_NUMBER, &pv)
04350            == PCE_NO_MORE_ARG_ERROR)
04351            break;
04352        n |= pv->v.number;
04353        EIMIL_REFCHECK(*pv);
04354     }
04355     pv = EIMIL_construct_number(n);
04356     if (!pv) PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04357 
04358     return pv;
04359 }
04360 
04361 DEFINE_EXEC_METHOD(band)
04362 {
04363     int i, n;
04364     EIMIL_value *pv;
04365 
04366     if (PCE_get_arg(pctx, 0, EIMIL_TYPE_NUMBER, &pv)
04367        == PCE_NO_MORE_ARG_ERROR) {
04368        PCE_SEH_throw(pctx, PCE_TOO_FEW_ARGUMENTS_ERROR, NULL);
04369     }
04370     n = pv->v.number;
04371     EIMIL_REFCHECK(*pv);
04372     for (i = 1; ; i++) {
04373        if (PCE_get_arg(pctx, i, EIMIL_TYPE_NUMBER, &pv)
04374            == PCE_NO_MORE_ARG_ERROR)
04375            break;
04376        n &= pv->v.number;
04377        EIMIL_REFCHECK(*pv);
04378     }
04379     pv = EIMIL_construct_number(n);
04380     if (!pv) PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04381 
04382     return pv;
04383 }
04384 
04385 DEFINE_EXEC_METHOD(bxor)
04386 {
04387     int i, n;
04388     EIMIL_value *pv;
04389 
04390     if (PCE_get_arg(pctx, 0, EIMIL_TYPE_NUMBER, &pv)
04391        == PCE_NO_MORE_ARG_ERROR) {
04392        PCE_SEH_throw(pctx, PCE_TOO_FEW_ARGUMENTS_ERROR, NULL);
04393     }
04394     n = pv->v.number;
04395     EIMIL_REFCHECK(*pv);
04396     for (i = 1; ; i++) {
04397        if (PCE_get_arg(pctx, i, EIMIL_TYPE_NUMBER, &pv)
04398            == PCE_NO_MORE_ARG_ERROR)
04399            break;
04400        n ^= pv->v.number;
04401        EIMIL_REFCHECK(*pv);
04402     }
04403     pv = EIMIL_construct_number(n);
04404     if (!pv) PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04405 
04406     return pv;
04407 }
04408 
04409 DEFINE_EXEC_METHOD(UCSval)
04410 {
04411     UTF32 ch;
04412     EIMIL_value *pv;
04413 
04414     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_CHAR, &pv);
04415     ch = pv->v.ch;
04416     EIMIL_REFCHECK(*pv);
04417 
04418     return EIMIL_construct_number((int)ch);
04419 }
04420 
04421 DEFINE_EXEC_METHOD(propadd)
04422 {
04423     EIMIL_value *pv_prop, *pv_val;
04424 
04425     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_PROP, &pv_prop);
04426     PCE_get_arg_or_error(pctx, 1, pv_prop->v.prop.type, &pv_val);
04427 
04428     if (!EIMIL_add_prop(&pv_prop->v.prop, pv_val)) {
04429        PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04430     }
04431     EIMIL_ADDREF(*pv_val);
04432 
04433     return pv_prop;
04434 }
04435 
04436 DEFINE_EXEC_METHOD(propcopy)
04437 {
04438     EIMIL_value *pv_prop, *pv_prop2;
04439 
04440     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_PROP, &pv_prop);
04441     pv_prop2 = EIMIL_copy_value(pv_prop);
04442 
04443     if (!pv_prop2) {
04444        PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04445     }
04446 
04447     return pv_prop2;
04448 }
04449 
04450 DEFINE_EXEC_METHOD(evchar)
04451 {
04452     EIMIL_value *pv;
04453 
04454     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_EVENT, &pv);
04455 
04456     return pv->v.event.pv_char;
04457 }
04458 
04459 DEFINE_EXEC_METHOD(strref)
04460 {
04461     int idx, len;
04462     UTF32* pstr, ch;
04463     EIMIL_value *pv_mtext, *pv_idx;
04464 
04465     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_MTEXT, &pv_mtext);
04466     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv_idx);
04467 
04468     pstr = pv_mtext->v.mtext.ustr;
04469     len = pv_mtext->v.mtext.len;
04470     idx = pv_idx->v.number;
04471     if ((idx < 0) || (idx >= len)) {
04472        PCE_SEH_throw(pctx, PCE_OUT_OF_RANGE_ERROR, NULL);
04473     }
04474 
04475     ch = pstr[idx];
04476 
04477     EIMIL_REFCHECK(*pv_mtext);
04478     EIMIL_REFCHECK(*pv_idx);
04479 
04480     return EIMIL_construct_char(ch);
04481 }
04482 
04483 DEFINE_EXEC_METHOD(makechar)
04484 {
04485     int n;
04486     EIMIL_value *pv;
04487 
04488     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_NUMBER, &pv);
04489     n = pv->v.number;
04490     EIMIL_REFCHECK(*pv);
04491 
04492     return EIMIL_construct_char((UTF32)n);
04493 }
04494 
04495 DEFINE_EXEC_METHOD(evtype)
04496 {
04497     EIMIL_value *pv;
04498 
04499     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_EVENT, &pv);
04500 
04501     return EIMIL_construct_mtext_from_UTF8(pv->v.event.type);
04502 }
04503 
04504 DEFINE_EXEC_METHOD(evmtext)
04505 {
04506     EIMIL_value *pv, *pvr;
04507 
04508     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_EVENT, &pv);
04509 
04510     pvr = pv->v.event.pv_mtext;
04511     EIMIL_REFCHECK_GUARD(*pv, *pvr);
04512 
04513     return pvr;
04514 }
04515 
04516 DEFINE_EXEC_METHOD(concat)
04517 {
04518     int i, n;
04519     EIMIL_value *pvr;
04520     EIMIL_value **ppv;
04521 
04522     n = PCE_get_arg_totnum(pctx);
04523     if (n == 0) return EIMIL_construct_mtext_from_UTF8("");
04524 
04525 #if 1
04526     ppv = (EIMIL_value**) alloca(sizeof(EIMIL_value*) * n);
04527 #else
04528     ppv = (EIMIL_value**) malloc(sizeof(EIMIL_value*) * n);
04529 #endif
04530 
04531     for (i = 0; i < n; i++) {
04532        PCE_get_arg_or_error(pctx, i,
04533                           EIMIL_TYPE_CHAR | EIMIL_TYPE_MTEXT,
04534                           ppv + i);
04535     }
04536 
04537     pvr = EIMIL_mtext_concat(n, ppv);
04538 
04539     for (i = 0; i < n; i++) {
04540        EIMIL_REFCHECK(*(ppv[i]));
04541     }
04542 
04543 #if 1
04544 #else
04545     free(ppv);
04546 #endif
04547 
04548     return pvr;
04549 }
04550 
04551 DEFINE_EXEC_METHOD(substr)
04552 {
04553     int beg, end, len;
04554     EIMIL_value *pv_mtext, *pv_beg, *pv_end, *pvr;
04555 
04556     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_MTEXT, &pv_mtext);
04557     len = pv_mtext->v.mtext.len;
04558     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv_beg);
04559     beg = pv_beg->v.number;
04560     EIMIL_REFCHECK(*pv_beg);
04561 
04562     if (PCE_get_arg(pctx, 2, EIMIL_TYPE_NUMBER, &pv_end)
04563        == PCE_NO_MORE_ARG_ERROR) {
04564        end = len;
04565     } else {
04566        end = pv_end->v.number;
04567        EIMIL_REFCHECK(*pv_end);
04568     }
04569 
04570     if ((beg < 0) || (beg >= end) || (end > len)) {
04571        PCE_SEH_throw(pctx, PCE_OUT_OF_RANGE_ERROR, NULL);
04572     }
04573 
04574     pvr = EIMIL_mtext_substr(pv_mtext, beg, end);
04575 
04576     EIMIL_REFCHECK(*pv_mtext);
04577 
04578     return pvr;
04579 }
04580 
04581 DEFINE_EXEC_METHOD(next)
04582 {
04583     EIMIL_value *pv_event;
04584 
04585     if (PCE_get_arg(pctx, 0, EIMIL_TYPE_ANY, &pv_event)
04586        == PCE_SUCCESS) {
04587        EIMIL_reply_event(pctx->ped, pv_event);
04588     }
04589     EIMIL_REFCHECK(*pv_event);
04590 
04591     pv_event = EIMIL_next_event(pctx->ped);
04592 
04593     if (pv_event) {
04594        PCE_set_current_event(pctx, pv_event);
04595     } else {
04596        PCE_SEH_throw(pctx, PCE_WAIT_NEXT_EVENT_ERROR, NULL);
04597     }
04598 
04599     return NULL;
04600 }
04601 
04602 DEFINE_EXEC_METHOD(makeev)
04603 {
04604     UTF8* type;
04605     EIMIL_value *pv_type, *pv_val, *pv_mod, *pv_char, *pv_mtext;
04606     EIMIL_value *ret;
04607 
04608     pv_val = pv_char = pv_mtext = NULL;
04609     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_MTEXT, &pv_type);
04610     
04611     type = EIMIL_convert_UTF32_to_UTF8(pv_type->v.mtext.ustr);
04612     if (!type) {
04613        PCE_SEH_throw(pctx, PCE_MEMORY_ERROR, NULL);
04614     }
04615     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER | EIMIL_TYPE_NIL, &pv_val);
04616     PCE_get_arg_or_error(pctx, 2, EIMIL_TYPE_NUMBER | EIMIL_TYPE_NIL, &pv_mod);
04617     PCE_get_arg_or_error(pctx, 3, EIMIL_TYPE_CHAR | EIMIL_TYPE_NIL, &pv_char);
04618     PCE_get_arg_or_error(pctx, 4, EIMIL_TYPE_MTEXT | EIMIL_TYPE_NIL, &pv_mtext);
04619 
04620     ret = EIMIL_construct_event(type, pv_val, pv_mod, pv_char, pv_mtext);
04621 
04622     if (type) free(type);
04623     
04624     return ret;
04625 }
04626 
04627 DEFINE_EXEC_METHOD(commit)
04628 {
04629     return NULL;
04630 }
04631 
04632 DEFINE_EXEC_METHOD(unroll)
04633 {
04634     return NULL;
04635 }
04636 
04637 DEFINE_EXEC_METHOD(propdel)
04638 {
04639     int idx;
04640     EIMIL_value *pv_prop, *pv_idx;
04641     EIMIL_prop *pprop;
04642 
04643     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_PROP, &pv_prop);
04644     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_NUMBER, &pv_idx);
04645 
04646     pprop = &pv_prop->v.prop;
04647     idx = pv_idx->v.number;
04648     EIMIL_delete_prop(pprop, idx);
04649     EIMIL_REFCHECK(*pv_prop);
04650     EIMIL_REFCHECK(*pv_idx);
04651 
04652     return NULL;
04653 }
04654 
04655 DEFINE_EXEC_METHOD(addmprop)
04656 {
04657     int beg, end, len;
04658     EIMIL_value *pv_target, *pv_prop, *pv_beg, *pv_end;
04659 
04660     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_MTEXT, &pv_target);
04661     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_PROP, &pv_prop);
04662     PCE_get_arg_or_error(pctx, 2, EIMIL_TYPE_NUMBER, &pv_beg);
04663     PCE_get_arg_or_error(pctx, 3, EIMIL_TYPE_NUMBER, &pv_end);
04664 
04665     len = pv_target->v.mtext.len;
04666     beg = pv_beg->v.number;
04667     end = pv_end->v.number;
04668 
04669     if ((beg < 0) || (beg >= end) || (end > len)) {
04670        PCE_SEH_throw(pctx, PCE_OUT_OF_RANGE_ERROR, NULL);
04671     }
04672 
04673     EIMIL_add_prop_on_mtext(&pv_target->v.mtext, pv_prop, beg, end);
04674 
04675     EIMIL_REFCHECK(*pv_target);
04676     EIMIL_REFCHECK(*pv_prop);
04677     EIMIL_REFCHECK(*pv_beg);
04678     EIMIL_REFCHECK(*pv_end);
04679 
04680     return NULL;
04681 }
04682 
04683 DEFINE_EXEC_METHOD(delmprop)
04684 {
04685     EIMIL_value *pv;
04686 
04687     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_PROP, &pv);
04688 
04689     EIMIL_detach_prop_from_mtext(pv);
04690 
04691     EIMIL_REFCHECK(*pv);
04692 
04693     return NULL;
04694 }
04695 
04696 DEFINE_EXEC_METHOD(setmprop)
04697 {
04698     int beg, end, len;
04699     EIMIL_value *pv_target, *pv_prop, *pv_beg, *pv_end;
04700 
04701     PCE_get_arg_or_error(pctx, 0, EIMIL_TYPE_MTEXT, &pv_target);
04702     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_PROP, &pv_prop);
04703     PCE_get_arg_or_error(pctx, 2, EIMIL_TYPE_NUMBER, &pv_beg);
04704     PCE_get_arg_or_error(pctx, 3, EIMIL_TYPE_NUMBER, &pv_end);
04705 
04706     len = pv_target->v.mtext.len;
04707     beg = pv_beg->v.number;
04708     end = pv_end->v.number;
04709 
04710     if ((beg < 0) || (beg >= end) || (end > len)) {
04711        PCE_SEH_throw(pctx, PCE_OUT_OF_RANGE_ERROR, NULL);
04712     }
04713 
04714     EIMIL_set_prop_on_mtext(&pv_target->v.mtext, pv_prop, beg, end);
04715 
04716     EIMIL_REFCHECK(*pv_target);
04717     EIMIL_REFCHECK(*pv_prop);
04718     EIMIL_REFCHECK(*pv_beg);
04719     EIMIL_REFCHECK(*pv_end);
04720 
04721     return NULL;
04722 }
04723 
04724 DEFINE_EXEC_METHOD(tblref)
04725 {
04726     return NULL;
04727 }
04728 
04729 DEFINE_EXEC_METHOD(makeprop)
04730 {
04731     EIMIL_symbol *psym;
04732 
04733     psym = PCE_get_symbol_arg(pctx, 0, EIMIL_CAT_PROPERTY);
04734 
04735     return EIMIL_construct_prop(psym);
04736 }
04737 
04738 DEFINE_EXEC_METHOD(getmprop)
04739 {
04740     EIMIL_symbol *psym;
04741     EIMIL_value *pv_mtext, *pv_beg, *pvr;
04742 
04743     psym = PCE_get_symbol_arg(pctx, 0, EIMIL_CAT_PROPERTY);
04744     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_MTEXT, &pv_mtext);
04745     PCE_get_arg_or_error(pctx, 2, EIMIL_TYPE_NUMBER, &pv_beg);
04746 
04747     pvr = EIMIL_get_prop_from_mtext(&pv_mtext->v.mtext,
04748                                 psym, pv_beg->v.number);
04749 
04750     EIMIL_REFCHECK(*pv_mtext);
04751     EIMIL_REFCHECK(*pv_beg);
04752 
04753     return pvr;
04754 }
04755 
04756 DEFINE_EXEC_METHOD(findmprop)
04757 {
04758     EIMIL_symbol *psym;
04759     EIMIL_value *pv_mtext, *pv_beg, *pvr;
04760 
04761     psym = PCE_get_symbol_arg(pctx, 0, EIMIL_CAT_PROPERTY);
04762     PCE_get_arg_or_error(pctx, 1, EIMIL_TYPE_MTEXT, &pv_mtext);
04763     PCE_get_arg_or_error(pctx, 2, EIMIL_TYPE_NUMBER, &pv_beg);
04764 
04765     pvr = EIMIL_find_prop_from_mtext(&pv_mtext->v.mtext,
04766                                  psym, pv_beg->v.number);
04767 
04768     EIMIL_REFCHECK(*pv_mtext);
04769     EIMIL_REFCHECK(*pv_beg);
04770 
04771     return pvr;
04772 }
04773 
04774 DEFINE_EXEC_METHOD(interact)
04775 {
04776     return NULL;
04777 }
04778 
04779 DEFINE_EXEC_METHOD(match)
04780 {
04781     return NULL;
04782 }
04783 
04784 DEFINE_EXEC_METHOD(forward)
04785 {
04786     return NULL;
04787 }
04788 
04789 DEFINE_EXEC_METHOD(send)
04790 {
04791     return NULL;
04792 }
04793 
04794 DEFINE_EXEC_METHOD(set)
04795 {
04796     EIMIL_value *pv, *pvo;
04797     EIMIL_symbol *psym;
04798 
04799     ASSERT(pctx->pcur->parg && pctx->pcur->parg->pnext);
04800     psym = PCE_lookup_symbol(pctx, pctx->pcur->parg->pnext);
04801     ASSERT(psym && psym->cat == EIMIL_CAT_VARIABLE);
04802 
04803     if (!PCE_get_arg(pctx, 0, EIMIL_TYPE_ANY, &pv)
04804        == PCE_NO_MORE_ARG_ERROR) {
04805        PCE_SEH_throw(pctx, PCE_TOO_FEW_ARGUMENTS_ERROR, NULL);
04806     }
04807     if (psym->obj.v.constp) {
04808        PCE_SEH_throw(pctx, PCE_VARIABLE_CONSTANT_ERROR, NULL);
04809     }
04810     if (pv && (pv->type != psym->obj.v.type)) {
04811        PCE_SEH_throw(pctx, PCE_WRONG_TYPE_ARGUMENT_ERROR, NULL);
04812     }
04813     pvo = psym->obj.v.pv;
04814     if (pvo) EIMIL_RMREF(*pvo);
04815     psym->obj.v.pv = pv;
04816     if (pv) EIMIL_ADDREF(*pv);
04817 
04818     return pv;
04819 }
04820 
04821 DEFINE_EXEC_METHOD(return)
04822 {
04823     EIMIL_value *pv;
04824 
04825     if (!PCE_get_arg(pctx, 0, EIMIL_TYPE_ANY, &pv)
04826        == PCE_NO_MORE_ARG_ERROR) {
04827        PCE_SEH_throw(pctx, PCE_TOO_FEW_ARGUMENTS_ERROR, NULL);
04828     }
04829     PCE_SEH_throw(pctx, PCE_RETURN_JMP_ERROR, pv);
04830     return NULL;
04831 }
04832 
04833 static enum PCE_ERROR_CODE
04834 PCE_root_exception_handler(
04835     PCE_context *pctx,
04836     int ecode,
04837     void *throwarg,
04838     void *catcharg
04839 )
04840 {
04841     /* TODO */
04842     if (ecode == PCE_WAIT_NEXT_EVENT_ERROR) {
04843        pctx->pcur = pctx->pcur->pnext;
04844        return PCE_WAIT_NEXT_EVENT_ERROR;
04845     }
04846 
04847     EIMIL_set_error(pctx->ped, "Exception received.");
04848     return PCE_UNKNOWN_ERROR;
04849 }
04850 
04851 static enum EIMIL_ENGINE_STATUS
04852 PCE_execute(
04853     void *private
04854 )
04855 {
04856     EIMIL_value *pv;
04857     PCE_context *pctx = (PCE_context*) private;
04858     enum PCE_ERROR_CODE r;
04859 
04860     pv = EIMIL_next_event(pctx->ped);
04861     if (pv) {
04862        PCE_set_current_event(pctx, pv);
04863     }
04864 
04865     if (PCE_SEH_start(pctx) != PCE_SUCCESS)
04866        return EIMIL_ENGINE_STATUS_ERROR;
04867     if (PCE_SEH_catch(pctx, PCE_ANY_ERROR,
04868                     PCE_root_exception_handler,
04869                     NULL)
04870        != PCE_SUCCESS)
04871        return EIMIL_ENGINE_STATUS_ERROR;
04872     r = PCE_SEH_try(pctx, PCE_execute_loop, NULL);
04873 
04874     if (r == PCE_SUCCESS)
04875        return EIMIL_ENGINE_STATUS_SUCCESS;
04876     else if (r == PCE_WAIT_NEXT_EVENT_ERROR)
04877        return EIMIL_ENGINE_STATUS_SUSPENDED;
04878 
04879     return EIMIL_ENGINE_STATUS_ERROR;
04880 }
04881 
04882 /********************************************************************************
04883                             initialization
04884 *********************************************************************************/
04885 
04886 static void
04887 PCE_init_document_template()
04888 {
04889     int n;
04890     EIMIL_element_template *p;
04891 
04892     p = PCE_if_full_template;
04893     n = EIMIL_TEMPLATE_NUM(PCE_if_else_template) - 1;
04894     memcpy(p , PCE_if_else_template, n * sizeof(*p));
04895     p += n;
04896     n = EIMIL_TEMPLATE_NUM(PCE_statement_template);
04897     memcpy(p , PCE_statement_template, n * sizeof(*p));
04898 
04899     p = PCE_try_full_template;
04900     n = EIMIL_TEMPLATE_NUM(PCE_try_catch_template) - 1;
04901     memcpy(p , PCE_try_catch_template, n * sizeof(*p));
04902     p += n;
04903     n = EIMIL_TEMPLATE_NUM(PCE_statement_template);
04904     memcpy(p , PCE_statement_template, n * sizeof(*p));
04905 }
04906 
04907 int
04908 PCE_init()
04909 {
04910     PCE_init_document_template();
04911     EIMIL_register_engine(PCE_classname,
04912                        PCE_docroot,
04913                        PCE_handler,
04914                        PCE_execute,
04915                        PCE_xmlns_uri);
04916     return 1;
04917 }
04918 
04919 /********************************************************************************
04920                                  API
04921 *********************************************************************************/
04922 
04923 #ifdef DEBUG
04924 static void
04925 dump_header(
04926     int lv,
04927     PCE_code *pc
04928 )
04929 {
04930     int i;
04931     for (i = 0; i < lv; i++) {
04932        fputs("  ", stderr);
04933     }
04934     fprintf(stderr, "%X:", (int) pc);
04935 }
04936 
04937 void
04938 EIMIL_dump_value(
04939     EIMIL_value *pv
04940 )
04941 {
04942     if (pv) {
04943        switch (pv->type) {
04944          case EIMIL_TYPE_BOOL:
04945           fprintf(stderr, "Bool:%d", pv->v.bool_val);
04946           break;
04947          case EIMIL_TYPE_NUMBER:
04948           fprintf(stderr, "Int:%d", pv->v.number);
04949           break;
04950          case EIMIL_TYPE_CHAR:
04951           fprintf(stderr, "Char:%c(%X)", pv->v.ch, pv->v.ch);
04952           break;
04953          case EIMIL_TYPE_MTEXT:
04954           fprintf(stderr, "MTEXT");
04955           break;
04956          case EIMIL_TYPE_EVENT:
04957           fprintf(stderr, "EVENT");
04958           break;
04959          case EIMIL_TYPE_PROP:
04960           fprintf(stderr, "PROP");
04961           break;
04962          default:
04963           fprintf(stderr, "!!Unknown value:%X", pv->type);
04964           break;
04965        }
04966     } else {
04967        fprintf(stderr, "nil");
04968     }
04969     fputc('\n', stderr);
04970 }
04971 
04972 void
04973 PCE_dump_code_internal(
04974     PCE_context *pctx,
04975     PCE_code *pc,
04976     int lv
04977 )
04978 {
04979     char *pn;
04980     EIMIL_symbol *psym;
04981 
04982     for ( ; pc; pc = pc->pnext) {
04983        switch (pc->type) {
04984          case PCE_CODE_MAIN:
04985           dump_header(lv, pc);
04986           fprintf(stderr, "MAIN:\n");
04987           PCE_dump_code_internal(pctx, pc->parg, lv + 1);
04988           break;
04989          case PCE_CODE_DEFUN:
04990           dump_header(lv, pc);
04991           psym = PCE_lookup_symbol(pctx, pc);
04992           fprintf(stderr, "DEFUN:%s\n", psym->name);
04993           PCE_dump_code_internal(pctx, pc->parg, lv + 1);
04994           break;
04995          case PCE_CODE_INST:
04996           if (pc->val.h == PCE_add_exec) {
04997              pn = "add";
04998           } else if (pc->val.h == PCE_sub_exec) {
04999              pn = "sub";
05000           } else if (pc->val.h == PCE_mul_exec) {
05001              pn = "mul";
05002           } else if (pc->val.h == PCE_div_exec) {
05003              pn = "div";
05004           } else if (pc->val.h == PCE_lt_exec) {
05005              pn = "lt";
05006           } else if (pc->val.h == PCE_gt_exec) {
05007              pn = "gt";
05008           } else if (pc->val.h == PCE_le_exec) {
05009              pn = "le";
05010           } else if (pc->val.h == PCE_ge_exec) {
05011              pn = "ge";
05012           } else if (pc->val.h == PCE_eql_exec) {
05013              pn = "eql";
05014           } else if (pc->val.h == PCE_strcmp_exec) {
05015              pn = "strcmp";
05016           } else if (pc->val.h == PCE_set_exec) {
05017              pn = "set";
05018           } else if (pc->val.h == PCE_next_exec) {
05019              pn = "next";
05020           } else if (pc->val.h == PCE_makeev_exec) {
05021              pn = "makeev";
05022           } else {
05023              pn = "unknown";
05024           }
05025           dump_header(lv, pc);
05026           fprintf(stderr, "Inst:%s\n", pn);
05027           PCE_dump_code_internal(pctx, pc->parg, lv + 1);
05028           break;
05029          case PCE_CODE_VALUE:
05030           dump_header(lv, pc);
05031           EIMIL_dump_value(pc->val.pv);
05032           break;
05033          case PCE_CODE_SYMBOL:
05034           dump_header(lv, pc);
05035           psym = PCE_lookup_symbol(pctx, pc);
05036           if (!psym) {
05037               fprintf(stderr,
05038                      "!!Unknown symid:%d\n",
05039                      pc->val.symid);
05040               break;
05041           }
05042           if (psym->cat != EIMIL_CAT_VARIABLE) {
05043               fprintf(stderr,
05044                      "!!not variable:%s\n",
05045                      psym->name);
05046               break;
05047           }
05048           fprintf(stderr, "Var:%s\n", psym->name);
05049           break;
05050          case PCE_CODE_JMP:
05051           dump_header(lv, pc);
05052           fprintf(stderr, "Jump:%x\n", (int) pc->val.pc_to);
05053           PCE_dump_code_internal(pctx, pc->parg, lv + 1);
05054           break;
05055          case PCE_CODE_COND_JMP:
05056           dump_header(lv, pc);
05057           fprintf(stderr, "Jump if:%x\n", (int) pc->val.pc_to);
05058           PCE_dump_code_internal(pctx, pc->parg, lv + 1);
05059           break;
05060          case PCE_CODE_COND_NOT_JMP:
05061           dump_header(lv, pc);
05062           fprintf(stderr, "Jump unless:%x\n", (int) pc->val.pc_to);
05063           PCE_dump_code_internal(pctx, pc->parg, lv + 1);
05064           break;
05065           default:
05066            /* TODO */
05067            break;
05068        }
05069     }
05070 }
05071 
05072 void
05073 PCE_dump_code(
05074     PCE_context *pctx
05075 )
05076 {
05077     PCE_dump_code_internal(pctx, pctx->pcur, 0);
05078 }
05079 
05080 #endif
05081 
05082 /* Local Variables: */
05083 /* c-file-style: "iiim-project" */
05084 /* End: */