int parse_db(struct _asm_context *asm_context, int null_term_flag) { char token[TOKENLEN]; int token_type; int data32; if (asm_context->segment == SEGMENT_BSS) { printf("Error: .bss segment doesn't support initialized data at %s:%d\n", asm_context->filename, asm_context->line); return -1; } while(1) { token_type = tokens_get(asm_context, token, TOKENLEN); if (token_type == TOKEN_EOL || token_type == TOKEN_EOF) break; if (token_type == TOKEN_QUOTED) { uint8_t *s = (uint8_t *)token; while(*s != 0) { if (*s == '\\') { int e = tokens_escape_char(asm_context, s); if (e == 0) { return -1; } s = s + e; } memory_write_inc(asm_context, *s, DL_DATA); asm_context->data_count++; s++; } if (null_term_flag == 1) { memory_write_inc(asm_context, 0, DL_DATA); asm_context->data_count++; } } else { tokens_push(asm_context, token, token_type); if (eval_expression(asm_context, &data32) != 0) { if (asm_context->pass == 2) { return -1; } eat_operand(asm_context); data32 = 0; } if (data32 < -128 || data32 > 0xff) { print_error_range("db", -128, 0xff, asm_context); return -1; } memory_write_inc(asm_context, (uint8_t)data32, DL_DATA); asm_context->data_count++; } token_type = tokens_get(asm_context, token, TOKENLEN); if (token_type == TOKEN_EOL || token_type == TOKEN_EOF) { break; } if (IS_NOT_TOKEN(token,',')) { print_error_expecting(",", token, asm_context); return -1; } } asm_context->line++; return 0; }
static int eval_expression_go(struct _asm_context *asm_context, struct _var *var, struct _operator *last_operator) { char token[TOKENLEN]; int token_type; struct _var var_stack[3]; int var_stack_ptr = 1; struct _operator operator; int last_token_was_op = -1; #ifdef DEBUG printf("Enter eval_expression_go, var=%d/%f/%d\n", var_get_int32(var), var_get_float(var), var_get_type(var)); #endif memcpy(&operator, last_operator, sizeof(struct _operator)); VAR_COPY(&var_stack[0], var); while(1) { #ifdef DEBUG printf("eval_expression> going to grab a token\n"); #endif token_type = tokens_get(asm_context, token, TOKENLEN); #ifdef DEBUG printf("eval_expression> token=%s var_stack_ptr=%d\n", token, var_stack_ptr); #endif // Issue 15: Return an error if a stack is full with noe operator. if (var_stack_ptr == 3 && operator.operation == OPER_UNSET) { return -1; } if (token_type == TOKEN_QUOTED) { if (token[0] == '\\') { int e = tokens_escape_char(asm_context, (unsigned char *)token); if (e == 0) return -1; if (token[e+1] != 0) { print_error("Quoted literal too long.", asm_context); return -1; } sprintf(token, "%d", token[e]); } else { if (token[1]!=0) { print_error("Quoted literal too long.", asm_context); return -1; } sprintf(token, "%d", token[0]); } token_type = TOKEN_NUMBER; } // Open and close parenthesis if (IS_TOKEN(token,'(')) { if (last_token_was_op == 0 && operator.operation != OPER_UNSET) { operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator); var_stack_ptr--; operator.operation = OPER_UNSET; VAR_COPY(var, &var_stack[var_stack_ptr-1]); tokens_push(asm_context, token, token_type); return 0; } if (operator.operation == OPER_UNSET && var_stack_ptr == 2) { // This is probably the x(r12) case.. so this is actually okay VAR_COPY(var, &var_stack[var_stack_ptr-1]); tokens_push(asm_context, token, token_type); return 0; } struct _var paren_var; struct _operator paren_operator; paren_operator.precedence = PREC_UNSET; paren_operator.operation = OPER_UNSET; memset(&paren_var, 0, sizeof(struct _var)); if (eval_expression_go(asm_context, &paren_var, &paren_operator) != 0) { return -1; } last_token_was_op = 0; #ifdef DEBUG printf("Paren got back %d/%f/%d\n", var_get_int32(&paren_var), var_get_float(&paren_var), var_get_type(&paren_var)); #endif VAR_COPY(&var_stack[var_stack_ptr++], &paren_var); token_type = tokens_get(asm_context, token, TOKENLEN); if (!(token[1] == 0 && token[0] == ')')) { print_error("No matching ')'", asm_context); return -1; } continue; } if (IS_TOKEN(token,')')) { tokens_push(asm_context, token, token_type); break; } // End of expression if (IS_TOKEN(token,',') || IS_TOKEN(token,']') || token_type == TOKEN_EOF || IS_TOKEN(token,'.')) { tokens_push(asm_context, token, token_type); break; } if (token_type == TOKEN_EOL) { //asm_context->tokens.line++; tokens_push(asm_context, token, token_type); break; } // Read number if (token_type == TOKEN_NUMBER) { last_token_was_op = 0; if (var_stack_ptr == 3) { print_error_unexp(token, asm_context); return -1; } var_set_int(&var_stack[var_stack_ptr++], atoll(token)); } else if (token_type == TOKEN_FLOAT) { if (var_stack_ptr == 3) { print_error_unexp(token, asm_context); return -1; } var_set_float(&var_stack[var_stack_ptr++], atof(token)); } else if (token_type == TOKEN_SYMBOL) { last_token_was_op = 1; struct _operator operator_prev; memcpy(&operator_prev, &operator, sizeof(struct _operator)); if (get_operator(token, &operator) == -1) { print_error_unexp(token, asm_context); return -1; } // Issue 15: 2015-July-21 mkohn - If operator is ~ then reverse // the next number. if (operator.operation == OPER_NOT) { int64_t num; if (parse_unary(asm_context, &num, OPER_NOT) != 0) { return -1; } if (var_stack_ptr == 3) { print_error_unexp(token, asm_context); return -1; } var_set_int(&var_stack[var_stack_ptr++], num); memcpy(&operator, &operator_prev, sizeof(struct _operator)); last_token_was_op = 0; continue; } // Stack pointer probably shouldn't be less than 2 if (var_stack_ptr == 0) { printf("Error: Unexpected operator '%s' at %s:%d\n", token, asm_context->tokens.filename, asm_context->tokens.line); return -1; } #ifdef DEBUG printf("TOKEN %s: precedence %d %d\n", token, last_operator->precedence, operator.precedence); #endif if (last_operator->precedence == PREC_UNSET) { memcpy(last_operator, &operator, sizeof(struct _operator)); } else if (last_operator->precedence > operator.precedence) { if (eval_expression_go(asm_context, &var_stack[var_stack_ptr-1], &operator) == -1) { return -1; } } else { operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator); var_stack_ptr--; memcpy(last_operator, &operator, sizeof(struct _operator)); } } else { if (asm_context->pass != 1) { print_error_unexp(token, asm_context); } return -1; } } #ifdef DEBUG printf("going to leave operation=%d\n", last_operator->operation); PRINT_STACK() #endif if (last_operator->operation != OPER_UNSET) { operate(&var_stack[var_stack_ptr-2], &var_stack[var_stack_ptr-1], last_operator); var_stack_ptr--; } VAR_COPY(var, &var_stack[var_stack_ptr-1]); return 0; }