/* register */ static int _register(State * state) /* "%" WORD */ { AsmArchOperand * p; char const * string; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(%%%s) %d\n", __func__, token_get_string( state->token), state->address); #endif p = &state->call.operands[state->call.operands_cnt]; string = token_get_string(state->token); /* XXX may be null or empty? */ if(state->address == 2) { p->definition = AO_DREGISTER2(0, 0, 0, 0); p->value.dregister2.name = p->value.dregister.name; p->value.dregister2.name2 = strdup(string); } else if(state->address == 1) { p->definition = AO_DREGISTER(0, 0, 0, 0); p->value.dregister.name = strdup(string); } else if(state->address == 0) { p->definition = AO_REGISTER(0, 0, 0); p->value._register.name = strdup(string); } return _parser_scan(state); }
/* section_name */ static int _section_name(State * state) /* WORD */ { int ret = 0; char const * string = NULL; size_t len; char * section = NULL; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif if(state->token == NULL || (string = token_get_string(state->token)) == NULL || (len = strlen(token_get_string(state->token))) == 0) return error_set_code(1, "%s", "Sections with empty names are not allowed"); if((section = malloc(len + 2)) == NULL) return ret | error_set_code(1, "%s", strerror(errno)); snprintf(section, len + 2, ".%s", string); ret |= _parser_scan(state); #ifdef DEBUG fprintf(stderr, "%s\"%s\"\n", "DEBUG: section ", section); #endif if(asmcode_section(state->code, section) != 0) ret |= _parser_error(state, "%s", error_get()); free(section); return ret; }
static int _parser_scan(State * state) { int ret; TokenCode code; char const * string; if(state->token != NULL) token_delete(state->token); if((ret = _scan_skip_meta(state)) != 0 || state->token == NULL) return ret; code = token_get_code(state->token); string = token_get_string(state->token); if(code == AS_CODE_WORD) { if(string != NULL && string[0] == '$') token_set_code(state->token, AS_CODE_IMMEDIATE); } else if(code == AS_CODE_OPERATOR_MODULO) { /* FIXME ugly workaround */ if((ret = _scan_skip_meta(state)) != 0) return ret; if(_parser_is_code(state, AS_CODE_WORD)) token_set_code(state->token, AS_CODE_REGISTER); } return 0; }
/* immediate */ static int _immediate(State * state) /* [ sign ] "$" NUMBER */ { int ret = 0; AsmArchOperand * p; char const * string; uint64_t value = 0; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif /* [ sign ] */ if(_parser_in_set(state, TS_SIGN)) ret |= _sign(state); else state->negative = 0; /* "$" NUMBER */ p = &state->call.operands[state->call.operands_cnt]; if((string = token_get_string(state->token)) != NULL || strlen(string) == 0) value = strtoul(string + 1, NULL, 0); else ret = _parser_error(state, "%s", "Empty values are not" " allowed"); if(state->address > 0) p->value.dregister.offset = value; else { p->value.immediate.value = strtoul(string + 1, NULL, 0); p->definition = AO_IMMEDIATE(0, 0, 0); p->value.immediate.negative = state->negative; } return ret | _parser_scan(state); }
static void _do_print_token(FILE * fp, Token * token) { CppCode code; code = token_get_code(token); #ifdef DEBUG fprintf(stderr, "DEBUG: \"%s\" (%d)\n", token_get_string(token), code); #else if(code != CPP_CODE_META_ERROR && code != CPP_CODE_META_WARNING) { fputs(token_get_string(token), fp); return; } fprintf(stderr, "%s%s%s%s%u%s%s\n", code == CPP_CODE_META_ERROR ? "Error" : "Warning", " in ", token_get_filename(token), ":", token_get_line(token), ": ", token_get_string(token)); #endif }
static int _scan_skip_meta(State * state) { int ret = 0; TokenCode code; while(cpp_scan(state->cpp, &state->token) == 0) { if(state->token == NULL) return ret; if((code = token_get_code(state->token)) < AS_CODE_META_FIRST || code > AS_CODE_META_LAST) return ret; if(code == AS_CODE_META_ERROR) ret |= _parser_error(state, "%s", token_get_string( state->token)); else if(code == AS_CODE_META_WARNING) _parser_warning(state, "%s", token_get_string( state->token)); token_delete(state->token); } return 1; }
/* function_name */ static int _function_name(State * state) /* WORD */ { int ret; char const * string; char * function = NULL; if((string = token_get_string(state->token)) == NULL) return _parser_error(state, "%s", "Empty function names are" " not allowed"); if((function = strdup(string)) == NULL) return error_set_code(1, "%s", strerror(errno)); ret = _parser_check(state, AS_CODE_WORD); #ifdef DEBUG fprintf(stderr, "DEBUG: %s \"%s\"\n", "function", function); #endif if(asmcode_function(state->code, function) != 0) ret |= _parser_error(state, "%s", error_get()); free(function); return ret; }
/* instruction_name */ static int _instruction_name(State * state) /* WORD */ { char const * string; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif if((string = token_get_string(state->token)) == NULL) { _parser_scan(state); return _parser_error(state, "%s", "Empty instructions are not" " allowed"); } if((state->call.name = strdup(string)) == NULL) return error_set_code(1, "%s", strerror(errno)); /* optimized free(state->operator); out */ #ifdef DEBUG fprintf(stderr, "DEBUG: %s() %s \"%s\"\n", __func__, "instruction ", string); #endif return _parser_scan(state); }
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; } } }