/* make a new node as following tree: new_node | node1__ \ node2 */ static struct finsh_node* make_sys_node(u_char type, struct finsh_node* node1, struct finsh_node* node2) { struct finsh_node* node; node = finsh_node_allocate(type); if ((node1 != NULL) && (node != NULL)) { finsh_node_child(node) = node1; finsh_node_sibling(node1) = node2; } else finsh_error_set(FINSH_ERROR_NULL_NODE); return node; }
/* param_list -> empty | expr_assign | param_list ',' expr_assign */ static struct finsh_node* proc_param_list(struct finsh_parser* self) { enum finsh_token_type token; struct finsh_node *node, *assign; assign = proc_assign_expr(self); if (assign == NULL) return NULL; node = assign; next_token(token, &(self->token)); while (token == finsh_token_type_comma ) { finsh_node_sibling(assign) = proc_assign_expr(self); if (finsh_node_sibling(assign) != NULL) assign = finsh_node_sibling(assign); else finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); next_token(token, &(self->token)); } finsh_token_replay(&(self->token)); return node; }
/* process for function and variable declaration. decl_variable -> type declaration_list ';' declarator_list -> declarator_list ',' declarator | declarator declarator -> identifier | identifier ASSIGN expr_assign */ static struct finsh_node* proc_variable_decl(struct finsh_parser* self) { enum finsh_token_type token; enum finsh_type type; char id[FINSH_NAME_MAX + 1]; struct finsh_node *node; struct finsh_node *end; struct finsh_node *assign; node = NULL; end = NULL; /* get type */ type = proc_type(self); /*process id.*/ if (proc_identifier(self, id) == 0) { /* if add variable failed */ if (finsh_var_insert(id, type) < 0) { finsh_error_set(FINSH_ERROR_VARIABLE_EXIST); } } next_token(token, &(self->token)); switch ( token ) { case finsh_token_type_comma:/*',', it's a variable_list declaration.*/ if (proc_identifier(self, id) == 0) { /* if add variable failed */ if (finsh_var_insert(id, type) < 0) { finsh_error_set(FINSH_ERROR_VARIABLE_EXIST); } } next_token(token, &(self->token)); if ( token == finsh_token_type_assign ) { /* get the right side of assign expression */ assign = proc_assign_expr(self); if (assign != NULL) { struct finsh_node* idnode; idnode = finsh_node_new_id(id); end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign); node = end; next_token(token, &(self->token)); } } while ( token == finsh_token_type_comma ) { if (proc_identifier(self, id) == 0) { /* if add variable failed */ if (finsh_var_insert(id, type) < 0) { finsh_error_set(FINSH_ERROR_VARIABLE_EXIST); } } next_token(token, &(self->token)); if ( token == finsh_token_type_assign ) { /* get the right side of assign expression */ assign = proc_assign_expr(self); if (assign != NULL) { struct finsh_node* idnode; idnode = finsh_node_new_id(id); /* make assign expression node */ if (node != NULL) { finsh_node_sibling(end) = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign); end = finsh_node_sibling(end); } else { end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign); node = end; } next_token(token, &(self->token)); } } } check_token(token, &(self->token), finsh_token_type_semicolon); return node; case finsh_token_type_assign:/*'=', it's a variable with assign declaration.*/ { struct finsh_node *idnode; assign = proc_assign_expr(self); if (assign != NULL) { idnode = finsh_node_new_id(id); /* make assign expression node */ end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign); node = end; next_token(token, &(self->token)); } while ( token == finsh_token_type_comma ) { if (proc_identifier(self, id) == 0) { /* if add variable failed */ if (finsh_var_insert(id, type) < 0) { finsh_error_set(FINSH_ERROR_VARIABLE_EXIST); } } next_token(token, &(self->token)); if (token == finsh_token_type_assign) { /* get the right side of assign expression */ assign = proc_assign_expr(self); if (assign != NULL) { idnode = finsh_node_new_id(id); /* make assign expression node */ if (node != NULL) { finsh_node_sibling(end) = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign); end = finsh_node_sibling(end); } else { end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign); node = end; } next_token(token, &(self->token)); } } } check_token(token, &(self->token), finsh_token_type_semicolon); return node; } case finsh_token_type_semicolon:/*';', it's a variable declaration.*/ return node; default: finsh_error_set(FINSH_ERROR_EXPECT_TYPE); return NULL; } }
/* start -> statement_expr | decl_variable */ void finsh_parser_run(struct finsh_parser* self, const u_char* string) { enum finsh_token_type token; struct finsh_node *node; node = NULL; /* init parser */ self->parser_string = (u_char*)string; /* init token */ finsh_token_init(&(self->token), self->parser_string); /* get next token */ next_token(token, &(self->token)); while (token != finsh_token_type_eof && token != finsh_token_type_bad) { switch (token) { case finsh_token_type_identifier: /* process expr_statement */ finsh_token_replay(&(self->token)); if (self->root != NULL) { finsh_node_sibling(node) = proc_expr_statement(self); if (finsh_node_sibling(node) != NULL) node = finsh_node_sibling(node); } else { node = proc_expr_statement(self); self->root = node; } break; default: if (is_base_type(token) || token == finsh_token_type_unsigned) { /* variable decl */ finsh_token_replay(&(self->token)); if (self->root != NULL) { finsh_node_sibling(node) = proc_variable_decl(self); if (finsh_node_sibling(node) != NULL) node = finsh_node_sibling(node); } else { node = proc_variable_decl(self); self->root = node; } } else { /* process expr_statement */ finsh_token_replay(&(self->token)); if (self->root != NULL) { finsh_node_sibling(node) = proc_expr_statement(self); if (finsh_node_sibling(node) != NULL) node = finsh_node_sibling(node); else next_token(token, &(self->token)); } else { node = proc_expr_statement(self); self->root = node; } } break; } /* get next token */ next_token(token, &(self->token)); } }
static int finsh_type_check(struct finsh_node* node, u_char is_addr) { if (node != NULL) { /* address & value */ if (node->node_type == FINSH_NODE_SYS_ASSIGN || node->node_type == FINSH_NODE_SYS_PREINC || node->node_type == FINSH_NODE_SYS_PREDEC || node->node_type == FINSH_NODE_SYS_GETADDR) { /* address */ finsh_type_check(finsh_node_child(node), FINSH_IDTYPE_ADDRESS); } else if (node->node_type == FINSH_NODE_SYS_GETVALUE && is_addr) { /* change the attribute of getvalue in left expr */ finsh_type_check(finsh_node_child(node), 0); } else { /* transfer 'av' to child node */ finsh_type_check(finsh_node_child(node), is_addr); } /* always does not load address in sibling */ finsh_type_check(finsh_node_sibling(node), FINSH_NODE_VALUE); /** set attribute of current node */ /* make sure the current node is address or value */ if (node->idtype != FINSH_IDTYPE_SYSCALL) node->idtype |= is_addr; if (finsh_node_child(node) != NULL) { node->data_type = finsh_node_child(node)->data_type; return 0; } if (node->node_type == FINSH_NODE_ID) { if (node->idtype & FINSH_IDTYPE_VAR) { struct finsh_var* var; var = node->id.var; if (var != NULL) { switch (var->type) { case finsh_type_void: node->data_type = FINSH_DATA_TYPE_VOID; break; case finsh_type_char: case finsh_type_uchar: node->data_type = FINSH_DATA_TYPE_BYTE; break; case finsh_type_short: case finsh_type_ushort: node->data_type = FINSH_DATA_TYPE_WORD; break; case finsh_type_int: case finsh_type_uint: case finsh_type_long: case finsh_type_ulong: node->data_type = FINSH_DATA_TYPE_DWORD; break; case finsh_type_charp: case finsh_type_voidp: case finsh_type_shortp: case finsh_type_intp: case finsh_type_longp: node->data_type = FINSH_DATA_TYPE_DWORD; break; default: finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE); break; } } } else if (node->idtype & FINSH_IDTYPE_SYSVAR) { struct finsh_sysvar *sysvar; sysvar = node->id.sysvar; if (sysvar != NULL) { switch (sysvar->type) { case finsh_type_void: node->data_type = FINSH_DATA_TYPE_VOID; break; case finsh_type_char: case finsh_type_uchar: node->data_type = FINSH_DATA_TYPE_BYTE; break; case finsh_type_short: case finsh_type_ushort: node->data_type = FINSH_DATA_TYPE_WORD; break; case finsh_type_int: case finsh_type_uint: case finsh_type_long: case finsh_type_ulong: node->data_type = FINSH_DATA_TYPE_DWORD; break; case finsh_type_charp: case finsh_type_voidp: case finsh_type_shortp: case finsh_type_intp: case finsh_type_longp: node->data_type = FINSH_DATA_TYPE_DWORD; break; default: finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE); break; } } } } else if (node->node_type == FINSH_NODE_VALUE_CHAR) { node->data_type = FINSH_DATA_TYPE_BYTE; } else if (node->node_type == FINSH_NODE_VALUE_INT || node->node_type == FINSH_NODE_VALUE_LONG || node->node_type == FINSH_NODE_VALUE_STRING || node->node_type == FINSH_NODE_VALUE_NULL) { node->data_type = FINSH_DATA_TYPE_DWORD; } } return 0; }
static int finsh_compile(struct finsh_node* node) { if (node != NULL) { /* compile child node */ if (finsh_node_child(node) != NULL) finsh_compile(finsh_node_child(node)); /* compile current node */ switch (node->node_type) { case FINSH_NODE_ID: { /* identifier::syscall */ if (node->idtype & FINSH_IDTYPE_SYSCALL) { /* load address */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword((long)node->id.syscall->func); } /* identifier::sysvar */ else if (node->idtype & FINSH_IDTYPE_SYSVAR) { struct finsh_sysvar* sysvar; sysvar = node->id.sysvar; if (sysvar != NULL) { switch (sysvar->type) { case finsh_type_char: case finsh_type_uchar: if (node->idtype & FINSH_IDTYPE_ADDRESS) { /* load address */ finsh_code_byte(FINSH_OP_LD_DWORD); } else { /* load value */ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE); } finsh_code_dword((long)(sysvar->var)); break; case finsh_type_short: case finsh_type_ushort: if (node->idtype & FINSH_IDTYPE_ADDRESS) { /* load address */ finsh_code_byte(FINSH_OP_LD_DWORD); } else { /* load value */ finsh_code_byte(FINSH_OP_LD_VALUE_WORD); } finsh_code_dword((long)(sysvar->var)); break; case finsh_type_int: case finsh_type_uint: case finsh_type_long: case finsh_type_ulong: case finsh_type_charp: case finsh_type_shortp: case finsh_type_intp: case finsh_type_longp: if (node->idtype & FINSH_IDTYPE_ADDRESS) { /* load address */ finsh_code_byte(FINSH_OP_LD_DWORD); } else { /* load value */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD); } finsh_code_dword((long)(sysvar->var)); break; } } } /* identifier::var */ else { struct finsh_var* var; var = node->id.var; if (var != NULL) { switch (var->type) { case finsh_type_char: case finsh_type_uchar: if (node->idtype & FINSH_IDTYPE_ADDRESS) { /* load address */ finsh_code_byte(FINSH_OP_LD_DWORD); } else { /* load value */ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE); } finsh_code_dword((long)&(var->value.char_value)); break; case finsh_type_short: case finsh_type_ushort: if (node->idtype & FINSH_IDTYPE_ADDRESS) { /* load address */ finsh_code_byte(FINSH_OP_LD_DWORD); } else { /* load value */ finsh_code_byte(FINSH_OP_LD_VALUE_WORD); } finsh_code_dword((long)&(var->value.short_value)); break; case finsh_type_int: case finsh_type_uint: case finsh_type_long: case finsh_type_ulong: case finsh_type_charp: case finsh_type_shortp: case finsh_type_intp: case finsh_type_longp: if (node->idtype & FINSH_IDTYPE_ADDRESS) { /* load address */ finsh_code_byte(FINSH_OP_LD_DWORD); } else { /* load value */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD); } finsh_code_dword((long)&(var->value.long_value)); break; } } } } break; /* load const */ case FINSH_NODE_VALUE_CHAR: finsh_code_byte(FINSH_OP_LD_BYTE); finsh_code_byte(node->value.char_value); break; case FINSH_NODE_VALUE_INT: case FINSH_NODE_VALUE_LONG: finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword(node->value.long_value); break; case FINSH_NODE_VALUE_NULL: case FINSH_NODE_VALUE_STRING: finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword((u_long)node->value.ptr); break; /* arithmetic operation */ case FINSH_NODE_SYS_ADD: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_ADD_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_ADD_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_ADD_DWORD); break; case FINSH_NODE_SYS_SUB: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SUB_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SUB_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SUB_DWORD); break; case FINSH_NODE_SYS_MUL: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_MUL_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_MUL_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_MUL_DWORD); break; case FINSH_NODE_SYS_DIV: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_DIV_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_DIV_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_DIV_DWORD); break; case FINSH_NODE_SYS_MOD: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_MOD_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_MOD_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_MOD_DWORD); break; /* bit operation */ case FINSH_NODE_SYS_AND: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_AND_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_AND_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_AND_DWORD); break; case FINSH_NODE_SYS_OR: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_OR_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_OR_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_OR_DWORD); break; case FINSH_NODE_SYS_XOR: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_XOR_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_XOR_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_XOR_DWORD); break; case FINSH_NODE_SYS_BITWISE: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_BITWISE_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_BITWISE_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_BITWISE_DWORD); break; case FINSH_NODE_SYS_SHL: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SHL_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SHL_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SHL_DWORD); break; case FINSH_NODE_SYS_SHR: if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SHR_BYTE); else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SHR_WORD); else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SHR_DWORD); break; /* syscall */ case FINSH_NODE_SYS_FUNC: { int parameters; struct finsh_node* sibling; parameters = 0; if (finsh_node_child(node) != NULL) { sibling = finsh_node_sibling(finsh_node_child(node)); while (sibling != NULL) { parameters ++; sibling = finsh_node_sibling(sibling); } /* load address of function */ // finsh_code_dword((long)&(node->var->value.ptr)); /* syscall parameters */ finsh_code_byte(FINSH_OP_SYSCALL); finsh_code_byte(parameters); } } break; /* assign expression */ case FINSH_NODE_SYS_ASSIGN: if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID) { switch (finsh_node_child(node)->data_type) { case FINSH_DATA_TYPE_BYTE: finsh_code_byte(FINSH_OP_ST_BYTE); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK); break; case FINSH_DATA_TYPE_WORD: finsh_code_byte(FINSH_OP_ST_WORD); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK); break; case FINSH_DATA_TYPE_DWORD: finsh_code_byte(FINSH_OP_ST_DWORD); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; default: finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE); } } else if (finsh_node_child(node)->node_type == FINSH_NODE_SYS_GETVALUE) { switch ((finsh_node_child(node)->data_type) & 0x0F) { case FINSH_DATA_TYPE_BYTE: finsh_code_byte(FINSH_OP_ST_BYTE); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK); break; case FINSH_DATA_TYPE_WORD: finsh_code_byte(FINSH_OP_ST_WORD); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK); break; case FINSH_DATA_TYPE_DWORD: finsh_code_byte(FINSH_OP_ST_DWORD); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; default: finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE); } } break; /* pre-increase */ case FINSH_NODE_SYS_PREINC: if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID) { struct finsh_var* var; var = finsh_node_child(node)->id.var; /* ld_dword &id */ // finsh_code_byte(FINSH_OP_LD_DWORD); switch (node->data_type) { case FINSH_DATA_TYPE_BYTE: /* address */ // finsh_code_dword((long)&(var->value.char_value)); /* ld_value_byte &id */ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE); finsh_code_dword((long)&(var->value.char_value)); /* ld_byte 1 */ finsh_code_byte(FINSH_OP_LD_BYTE); finsh_code_byte(1); /* add_byte */ finsh_code_byte(FINSH_OP_ADD_BYTE); /* st_byte */ finsh_code_byte(FINSH_OP_ST_BYTE); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; case FINSH_DATA_TYPE_WORD: /* address */ // finsh_code_dword((long)&(var->value.short_value)); /* ld_value_word &id */ finsh_code_byte(FINSH_OP_LD_VALUE_WORD); finsh_code_dword((long)&(var->value.short_value)); /* ld_word 1 */ finsh_code_byte(FINSH_OP_LD_WORD); finsh_code_word(1); /* add_word */ finsh_code_byte(FINSH_OP_ADD_WORD); /* st_word */ finsh_code_byte(FINSH_OP_ST_WORD); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; case FINSH_DATA_TYPE_DWORD: /* address */ // finsh_code_dword((long)&(var->value.long_value)); /* ld_dword &id */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD); finsh_code_dword((long)&(var->value.long_value)); /* ld_dword 1 */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword(1); /* add_dword */ finsh_code_byte(FINSH_OP_ADD_DWORD); /* st_dword */ finsh_code_byte(FINSH_OP_ST_DWORD); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; } } break; /* pre-decrease */ case FINSH_NODE_SYS_PREDEC: if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID) { struct finsh_var* var; var = finsh_node_child(node)->id.var; /* ld_dword &id */ // finsh_code_byte(FINSH_OP_LD_DWORD); switch (node->data_type) { case FINSH_DATA_TYPE_BYTE: /* address */ // finsh_code_dword((long)&(var->value.char_value)); /* ld_value_byte &id */ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE); finsh_code_dword((long)&(var->value.char_value)); /* ld_byte 1 */ finsh_code_byte(FINSH_OP_LD_BYTE); finsh_code_byte(1); /* add_byte */ finsh_code_byte(FINSH_OP_SUB_BYTE); /* st_byte */ finsh_code_byte(FINSH_OP_ST_BYTE); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; case FINSH_DATA_TYPE_WORD: /* address */ // finsh_code_dword((long)&(var->value.short_value)); /* ld_value_word &id */ finsh_code_byte(FINSH_OP_LD_VALUE_WORD); finsh_code_dword((long)&(var->value.short_value)); /* ld_word 1 */ finsh_code_byte(FINSH_OP_LD_WORD); finsh_code_word(1); /* add_word */ finsh_code_byte(FINSH_OP_SUB_WORD); /* st_word */ finsh_code_byte(FINSH_OP_ST_WORD); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; case FINSH_DATA_TYPE_DWORD: /* address */ // finsh_code_dword((long)&(var->value.long_value)); /* ld_dword &id */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD); finsh_code_dword((long)&(var->value.long_value)); /* ld_dword 1 */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword(1); /* add_dword */ finsh_code_byte(FINSH_OP_SUB_DWORD); /* st_dword */ finsh_code_byte(FINSH_OP_ST_DWORD); /* load value again */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; } } break; /* increase */ case FINSH_NODE_SYS_INC: if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID) { struct finsh_var* var; var = finsh_node_child(node)->id.var; switch (node->data_type) { case FINSH_DATA_TYPE_BYTE: /* ld_value_byte &id */ // finsh_code_byte(FINSH_OP_LD_VALUE_BYTE); // finsh_code_dword((long)&(var->value.char_value)); /* ld_dword &id */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword((long)&(var->value.char_value)); /* ld_value_byte &id */ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE); finsh_code_dword((long)&(var->value.char_value)); /* ld_byte 1 */ finsh_code_byte(FINSH_OP_LD_BYTE); finsh_code_byte(1); /* add_byte */ finsh_code_byte(FINSH_OP_ADD_BYTE); /* get byte */ finsh_code_byte(FINSH_OP_ST_BYTE); /* pop */ finsh_code_byte(FINSH_OP_POP); break; case FINSH_DATA_TYPE_WORD: /* ld_value_word &id */ // finsh_code_byte(FINSH_OP_LD_VALUE_WORD); // finsh_code_dword((long)&(var->value.short_value)); /* ld_dword &id */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword((long)&(var->value.short_value)); /* ld_value_word &id */ finsh_code_byte(FINSH_OP_LD_VALUE_WORD); finsh_code_dword((long)&(var->value.short_value)); /* ld_word 1 */ finsh_code_byte(FINSH_OP_LD_WORD); finsh_code_word(1); /* add_byte */ finsh_code_byte(FINSH_OP_ADD_WORD); /* get byte */ finsh_code_byte(FINSH_OP_ST_WORD); /* pop */ finsh_code_byte(FINSH_OP_POP); break; case FINSH_DATA_TYPE_DWORD: /* ld_value_dword &id */ // finsh_code_byte(FINSH_OP_LD_VALUE_DWORD); // finsh_code_dword((long)&(var->value.long_value)); /* ld_dword &id */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword((long)&(var->value.long_value)); /* ld_value_dword &id */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD); finsh_code_dword((long)&(var->value.long_value)); /* ld_dword 1 */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword(1); /* add_byte */ finsh_code_byte(FINSH_OP_ADD_DWORD); /* get byte */ finsh_code_byte(FINSH_OP_ST_DWORD); /* pop */ finsh_code_byte(FINSH_OP_POP); break; } } break; /* decrease */ case FINSH_NODE_SYS_DEC: if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID) { struct finsh_var* var; var = finsh_node_child(node)->id.var; switch (node->data_type) { case FINSH_DATA_TYPE_BYTE: /* ld_value_byte &id */ // finsh_code_byte(FINSH_OP_LD_VALUE_BYTE); // finsh_code_dword((long)&(var->value.char_value)); /* ld_dword &id */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword((long)&(var->value.char_value)); /* ld_value_byte &id */ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE); finsh_code_dword((long)&(var->value.char_value)); /* ld_byte 1 */ finsh_code_byte(FINSH_OP_LD_BYTE); finsh_code_byte(1); /* add_byte */ finsh_code_byte(FINSH_OP_SUB_BYTE); /* get byte */ finsh_code_byte(FINSH_OP_ST_BYTE); /* pop */ finsh_code_byte(FINSH_OP_POP); break; case FINSH_DATA_TYPE_WORD: /* ld_value_word &id */ // finsh_code_byte(FINSH_OP_LD_VALUE_WORD); // finsh_code_dword((long)&(var->value.short_value)); /* ld_dword &id */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword((long)&(var->value.short_value)); /* ld_value_word &id */ finsh_code_byte(FINSH_OP_LD_VALUE_WORD); finsh_code_dword((long)&(var->value.short_value)); /* ld_word 1 */ finsh_code_byte(FINSH_OP_LD_WORD); finsh_code_word(1); /* add_byte */ finsh_code_byte(FINSH_OP_SUB_WORD); /* get byte */ finsh_code_byte(FINSH_OP_ST_WORD); /* pop */ finsh_code_byte(FINSH_OP_POP); break; case FINSH_DATA_TYPE_DWORD: /* ld_value_dword &id */ // finsh_code_byte(FINSH_OP_LD_VALUE_DWORD); // finsh_code_dword((long)&(var->value.long_value)); /* ld_dword &id */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword((long)&(var->value.long_value)); /* ld_value_dword &id */ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD); finsh_code_dword((long)&(var->value.long_value)); /* ld_dword 1 */ finsh_code_byte(FINSH_OP_LD_DWORD); finsh_code_dword(1); /* add_byte */ finsh_code_byte(FINSH_OP_SUB_DWORD); /* get byte */ finsh_code_byte(FINSH_OP_ST_DWORD); /* pop */ finsh_code_byte(FINSH_OP_POP); break; } } break; case FINSH_NODE_SYS_NULL: finsh_code_dword(0); break; case FINSH_NODE_SYS_GETVALUE: if (node->idtype & FINSH_IDTYPE_ADDRESS) { /* nothing will be generated */ } else { switch (node->data_type) { case FINSH_DATA_TYPE_BYTE: finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK); break; case FINSH_DATA_TYPE_WORD: finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK); break; case FINSH_DATA_TYPE_DWORD: finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK); break; default: break; } } break; case FINSH_NODE_SYS_GETADDR: /* nothing will be generated */ break; default: finsh_error_set(FINSH_ERROR_UNKNOWN_NODE); break; } /* compile sibling node */ if (finsh_node_sibling(node) != NULL) finsh_compile(finsh_node_sibling(node)); } return 0; }