/* expr_shift -> expr_additive | expr_shift '<<' expr_additive | expr_shift '>>' expr_additive */ static struct finsh_node* proc_shift_expr(struct finsh_parser* self) { enum finsh_token_type token; struct finsh_node* add; struct finsh_node* add_new; add = proc_additive_expr(self); next_token(token, &(self->token)); while ( token == finsh_token_type_shl || token == finsh_token_type_shr) { add_new = proc_additive_expr(self); if (add_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); else { switch (token) { case finsh_token_type_shl: add = make_sys_node(FINSH_NODE_SYS_SHL, add, add_new); break; case finsh_token_type_shr: add = make_sys_node(FINSH_NODE_SYS_SHR, add, add_new); break; default: finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); break; } } next_token(token, &(self->token)); } finsh_token_replay(&(self->token)); return add; }
struct finsh_node* finsh_node_new_id(char* id) { struct finsh_node* node; void* symbol; unsigned char type; symbol = NULL; type = 0; node = NULL; /* lookup variable firstly */ symbol = (void*)finsh_var_lookup(id); if (symbol == NULL) { /* then lookup system variable */ symbol = (void*)finsh_sysvar_lookup(id); if (symbol == NULL) { /* then lookup system call */ symbol = (void*)finsh_syscall_lookup(id); if (symbol != NULL) type = FINSH_IDTYPE_SYSCALL; } else type = FINSH_IDTYPE_SYSVAR; } else type = FINSH_IDTYPE_VAR; if (symbol != NULL) { /* allocate a new node */ node = finsh_node_allocate(FINSH_NODE_ID); /* allocate node error */ if (node == NULL) { finsh_error_set(FINSH_ERROR_MEMORY_FULL); return NULL; } /* fill node value according type */ switch (type) { case FINSH_IDTYPE_VAR: node->id.var = (struct finsh_var*)symbol; break; case FINSH_IDTYPE_SYSVAR: node->id.sysvar = (struct finsh_sysvar*)symbol; break; case FINSH_IDTYPE_SYSCALL: node->id.syscall = (struct finsh_syscall*)symbol; break; } /* fill identifier type */ node->idtype = type; } else finsh_error_set(FINSH_ERROR_UNKNOWN_SYMBOL); return node; }
/* expr_additive -> expr_multiplicative | expr_additive SUB expr_multiplicative | expr_additive ADD expr_multiplicative */ static struct finsh_node* proc_additive_expr(struct finsh_parser* self) { enum finsh_token_type token; struct finsh_node* mul; struct finsh_node* mul_new; mul = proc_multiplicative_expr(self); next_token(token, &(self->token)); while ( token == finsh_token_type_sub || token == finsh_token_type_add ) { mul_new = proc_multiplicative_expr(self); if (mul_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); else { switch (token) { case finsh_token_type_sub: mul = make_sys_node(FINSH_NODE_SYS_SUB, mul, mul_new); break; case finsh_token_type_add: mul = make_sys_node(FINSH_NODE_SYS_ADD, mul, mul_new); break; default: finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); break; } } next_token(token, &(self->token)); } finsh_token_replay(&(self->token)); return mul; }
static u_char* token_proc_string(struct finsh_token* self) { u_char* p; for ( p = &self->string[0]; p - &(self->string[0]) < FINSH_STRING_MAX; ) { char ch = token_next_char(self); if ( is_eof(self) ) { finsh_error_set(FINSH_ERROR_UNEXPECT_END); return NULL;; } if ( ch == '\\' ) { ch = token_proc_escape(self); } else if ( ch == '"' )/*end of string.*/ { *p = '\0'; return self->string; } *p++ = ch; } return NULL; }
/* expr_multiplicative -> expr_cast | expr_multiplicative '*' expr_cast | expr_multiplicative '/' expr_cast | expr_multiplicative '%' expr_cast */ static struct finsh_node* proc_multiplicative_expr(struct finsh_parser* self) { enum finsh_token_type token; struct finsh_node* cast; struct finsh_node* cast_new; cast = proc_cast_expr(self); next_token(token, &(self->token)); while (token == finsh_token_type_mul || token == finsh_token_type_div || token == finsh_token_type_mod ) { cast_new = proc_cast_expr(self); if (cast_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); else { switch (token) { case finsh_token_type_mul: cast = make_sys_node(FINSH_NODE_SYS_MUL, cast, cast_new); break; case finsh_token_type_div: cast = make_sys_node(FINSH_NODE_SYS_DIV, cast, cast_new); break; case finsh_token_type_mod: cast = make_sys_node(FINSH_NODE_SYS_MOD, cast, cast_new); break; default: finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); break; } } next_token(token, &(self->token)); } finsh_token_replay(&(self->token)); return cast; }
static char token_proc_char(struct finsh_token* self) { char ch; char buf[4], *p; p = buf; ch = token_next_char(self); if ( ch == '\\' ) { ch = token_next_char(self); switch ( ch ) { case 'n': ch = '\n'; break; case 't': ch = '\t'; break; case 'v': ch = '\v'; break; case 'b': ch = '\b'; break; case 'r': ch = '\r'; break; case '\\': ch = '\\'; break; case '\'': ch = '\''; break; default : while ( is_digit(ch) ) { /*for '\113' char*/ ch = token_next_char(self); *p++ = ch; } token_prev_char(self); *p = '\0'; ch = atoi(p); break; } } if ( token_next_char(self) != '\'' ) { token_prev_char(self); finsh_error_set(FINSH_ERROR_EXPECT_CHAR); return ch; } return ch; }
struct finsh_node* finsh_node_new_ptr(void* ptr) { struct finsh_node* node; node = finsh_node_allocate(FINSH_NODE_VALUE_NULL); if (node == NULL) { finsh_error_set(FINSH_ERROR_MEMORY_FULL); return NULL; } node->value.ptr = ptr; return node; }
struct finsh_node* finsh_node_new_long(long l) { struct finsh_node* node; node = finsh_node_allocate(FINSH_NODE_VALUE_LONG); if (node == NULL) { finsh_error_set(FINSH_ERROR_MEMORY_FULL); return NULL; } node->value.long_value = l; return node; }
struct finsh_node* finsh_node_new_int(int i) { struct finsh_node* node; node = finsh_node_allocate(FINSH_NODE_VALUE_INT); if (node == NULL) { finsh_error_set(FINSH_ERROR_MEMORY_FULL); return NULL; } node->value.int_value = i; return node; }
struct finsh_node* finsh_node_new_char(char c) { struct finsh_node* node; node = finsh_node_allocate(FINSH_NODE_VALUE_CHAR); if (node == NULL) { finsh_error_set(FINSH_ERROR_MEMORY_FULL); return NULL; } node->value.char_value = c; return node; }
/* 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; }
struct finsh_node* finsh_node_new_string(char* s) { struct finsh_node* node; node = finsh_node_allocate(FINSH_NODE_VALUE_STRING); if (node == NULL) { finsh_error_set(FINSH_ERROR_MEMORY_FULL); return NULL; } /* make string */ node->value.ptr = finsh_heap_allocate(strlen(s) + 1); strncpy(node->value.ptr, s, strlen(s)); ((u_char*)node->value.ptr)[strlen(s)] = '\0'; return node; }
/* expr_primary -> literal | '(' expr ')' | identifier */ static struct finsh_node* proc_primary_expr(struct finsh_parser* self) { enum finsh_token_type token; struct finsh_node* expr; next_token(token, &(self->token)); switch ( token ) { case finsh_token_type_identifier: { char id[FINSH_NAME_MAX + 1]; finsh_token_replay(&(self->token)); proc_identifier(self, id); return finsh_node_new_id(id); } case finsh_token_type_left_paren: expr = proc_expr(self); match_token(token, &(self->token), finsh_token_type_right_paren); return expr; case finsh_token_type_value_int: return finsh_node_new_int(self->token.value.int_value); case finsh_token_type_value_long: return finsh_node_new_long(self->token.value.long_value); case finsh_token_type_value_char: return finsh_node_new_char(self->token.value.char_value); case finsh_token_type_value_string: return finsh_node_new_string((char*)self->token.string); case finsh_token_type_value_null: return finsh_node_new_ptr(NULL); default: finsh_error_set(FINSH_ERROR_INVALID_TOKEN); break; } return NULL; }
/* expr_exclusive_or -> expr_and | expr_exclusive '^' expr_and */ static struct finsh_node* proc_exclusive_or_expr(struct finsh_parser* self) { enum finsh_token_type token; struct finsh_node* and; struct finsh_node* and_new; and = proc_and_expr(self); next_token(token, &(self->token)); while ( token == finsh_token_type_xor ) { and_new = proc_and_expr(self); if (and_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); else and = make_sys_node(FINSH_NODE_SYS_XOR, and, and_new); next_token(token, &(self->token)); } finsh_token_replay(&(self->token)); return and; }
/* expr_and -> expr_shift | expr_and '&' expr_shift */ static struct finsh_node* proc_and_expr(struct finsh_parser* self) { enum finsh_token_type token; struct finsh_node* shift; struct finsh_node* shift_new; shift = proc_shift_expr(self); next_token(token, &(self->token)); while ( token == finsh_token_type_and ) { shift_new = proc_shift_expr(self); if (shift_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); else shift = make_sys_node(FINSH_NODE_SYS_AND, shift, shift_new); next_token(token, &(self->token)); } finsh_token_replay(&(self->token)); return shift; }
/* expr_inclusive_or -> expr_exclusive_or | expr_inclusive_or '|' expr_exclusive_or */ static struct finsh_node* proc_inclusive_or_expr(struct finsh_parser* self) { enum finsh_token_type token; struct finsh_node* xor; struct finsh_node* xor_new; xor = proc_exclusive_or_expr(self); next_token(token, &(self->token)); while ( token == finsh_token_type_or ) { xor_new = proc_exclusive_or_expr(self); if (xor_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR); else xor = make_sys_node(FINSH_NODE_SYS_OR, xor, xor_new); next_token(token, &(self->token)); } finsh_token_replay(&(self->token)); return xor; }
/* 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; }
static void token_run(struct finsh_token* self) { char ch; token_trim_space(self); /* first trim space and tab. */ token_get_string(self, &(self->string[0])); if ( is_eof(self) ) { /*if it is eof, break;*/ self->current_token = finsh_token_type_eof; return ; } if (self->string[0] != '\0') { /*It is a key word or a identifier.*/ if ( !token_match_name(self, (char*)self->string) ) { self->current_token = finsh_token_type_identifier; } return; } else { /*It is a operator character.*/ ch = token_next_char(self); switch ( ch ) { case '(': self->current_token = finsh_token_type_left_paren; break; case ')': self->current_token = finsh_token_type_right_paren; break; case ',': self->current_token = finsh_token_type_comma; break; case ';': self->current_token = finsh_token_type_semicolon; break; case '&': self->current_token = finsh_token_type_and; break; case '*': self->current_token = finsh_token_type_mul; break; case '+': ch = token_next_char(self); if ( ch == '+' ) { self->current_token = finsh_token_type_inc; } else { token_prev_char(self); self->current_token = finsh_token_type_add; } break; case '-': ch = token_next_char(self); if ( ch == '-' ) { self->current_token = finsh_token_type_dec; } else { token_prev_char(self); self->current_token = finsh_token_type_sub; } break; case '/': ch = token_next_char(self); if (ch == '/') { /* line comments, set to end of file */ self->current_token = finsh_token_type_eof; } else { token_prev_char(self); self->current_token = finsh_token_type_div; } break; case '<': ch = token_next_char(self); if ( ch == '<' ) { self->current_token = finsh_token_type_shl; } else { token_prev_char(self); self->current_token = finsh_token_type_bad; } break; case '>': ch = token_next_char(self); if ( ch == '>' ) { self->current_token = finsh_token_type_shr; } else { token_prev_char(self); self->current_token = finsh_token_type_bad; } break; case '|': self->current_token = finsh_token_type_or; break; case '%': self->current_token = finsh_token_type_mod; break; case '~': self->current_token = finsh_token_type_bitwise; break; case '^': self->current_token = finsh_token_type_xor; break; case '=': self->current_token = finsh_token_type_assign; break; case '\'': self->value.char_value = token_proc_char(self); self->current_token = finsh_token_type_value_char; break; case '"': token_proc_string(self); self->current_token = finsh_token_type_value_string; break; default: if ( is_digit(ch) ) { token_prev_char(self); token_proc_number(self); break; } finsh_error_set(FINSH_ERROR_UNKNOWN_TOKEN); self->current_token = finsh_token_type_bad; break; } } }
/* type -> type_prefix type_basic | type_basic type_prefix -> UNSIGNED type_basic -> VOID | CHAR | SHORT | INT | STRING */ static enum finsh_type proc_type(struct finsh_parser* self) { enum finsh_type type; enum finsh_token_type token; /* set init type */ type = finsh_type_unknown; next_token(token, &(self->token)); if ( is_base_type(token) ) /* base_type */ { switch (token) { case finsh_token_type_void: type = finsh_type_void; break; case finsh_token_type_char: type = finsh_type_char; break; case finsh_token_type_short: type = finsh_type_short; break; case finsh_token_type_int: type = finsh_type_int; break; case finsh_token_type_long: type = finsh_type_long; break; default: goto __return; } } else if ( token == finsh_token_type_unsigned ) /* unsigned base_type */ { next_token(token, &(self->token)); if ( is_base_type(token) ) { switch (token) { case finsh_token_type_char: type = finsh_type_uchar; break; case finsh_token_type_short: type = finsh_type_ushort; break; case finsh_token_type_int: type = finsh_type_uint; break; case finsh_token_type_long: type = finsh_type_ulong; break; default: goto __return; } } else { finsh_token_replay(&(self->token)); finsh_error_set(FINSH_ERROR_EXPECT_TYPE); } } else { goto __return; } /* parse for pointer */ next_token(token, &(self->token)); if (token == finsh_token_type_mul) { switch (type) { case finsh_type_void: type = finsh_type_voidp; break; case finsh_type_char: case finsh_type_uchar: type = finsh_type_charp; break; case finsh_type_short: case finsh_type_ushort: type = finsh_type_shortp; break; case finsh_type_int: case finsh_type_uint: type = finsh_type_intp; break; case finsh_type_long: case finsh_type_ulong: type = finsh_type_longp; break; default: type = finsh_type_voidp; break; } } else finsh_token_replay(&(self->token)); return type; __return: finsh_token_replay(&(self->token)); finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE); return type; }
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; }
/* 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; } }
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; }