/*---------------------------------------------------------------------------*/ static int varfactor(void) { int r; DEBUG_PRINTF("varfactor: obtaining %d from variable %d\n", variables[tokenizer_variable_num()], tokenizer_variable_num()); r = ubasic_get_variable(tokenizer_variable_num()); accept(TOKENIZER_VARIABLE); return r; }
/*---------------------------------------------------------------------------*/ static void varfactor(struct typevalue *v) { var_t var = tokenizer_variable_num(); struct typevalue s[MAX_SUBSCRIPT]; int n = 0; /* Sinclair style A$(2 TO 5) would also need to be parsed here if added */ accept_either(TOKENIZER_INTVAR, TOKENIZER_STRINGVAR); if (current_token == TOKENIZER_LEFTPAREN) n = parse_subscripts(s); ubasic_get_variable(var, v, n, s); DEBUG_PRINTF("varfactor: obtaining %d from variable %d\n", v->d.i, tokenizer_variable_num()); }
//static void let_statement(void) void let_statement(void) { long var; long ix; ix = 0; var = tokenizer_variable_num(); if((var >= MAX_VARNUM)&&(var <(MAX_VARNUM+MAX_ARRYNUM))){ accept(TOKENIZER_VARIABLE); ix = tokenizer_num(); accept(TOKENIZER_ARRAY); }else{ accept(TOKENIZER_VARIABLE); } if(ptr[0] == '='){ accept(TOKENIZER_EQ); if(var < MAX_VARNUM){ ubasic_set_variable(var, expr()); }else if(var < (MAX_VARNUM+MAX_ARRYNUM)){ if(ix<MAX_ARRYLEN){ ubasic_set_array(var,ix, expr()); } }else if(var < (MAX_VARNUM+MAX_ARRYNUM+MAX_STRINGNUM)){ ubasic_set_variable(var, expr()); }else if(var < (MAX_VARNUM+MAX_ARRYNUM+MAX_STRINGNUM+MAX_BIGVARNUM)){ ubasic_set_variable(var, expr()); } } accept(TOKENIZER_CR); }
//static int varfactor(void) int varfactor(void) { long r; r = ubasic_get_variable(tokenizer_variable_num()); accept(TOKENIZER_VARIABLE); return r; }
/*---------------------------------------------------------------------------*/ static void for_statement(void) { int for_variable, to; accept(TOKENIZER_FOR); for_variable = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); accept(TOKENIZER_EQ); ubasic_set_variable(for_variable, expr()); accept(TOKENIZER_TO); to = expr(); accept(TOKENIZER_CR); if(for_stack_ptr < MAX_FOR_STACK_DEPTH) { for_stack[for_stack_ptr].line_after_for = tokenizer_num(); for_stack[for_stack_ptr].for_variable = for_variable; for_stack[for_stack_ptr].to = to; DEBUG_PRINTF("for_statement: new for, var %d to %d\n", for_stack[for_stack_ptr].for_variable, for_stack[for_stack_ptr].to); for_stack_ptr++; } else { DEBUG_PRINTF("for_statement: for stack depth exceeded\n"); } }
/*---------------------------------------------------------------------------*/ static void next_statement(void) { int var; struct for_state *fs; struct typevalue t; /* FIXME: support 'NEXT' on its own, also loop down the stack so if you GOTO out of a layer of NEXT the right thing occurs */ var = tokenizer_variable_num(); accept_tok(TOKENIZER_INTVAR); /* FIXME: make the for stack just use pointers so it compiles better */ fs = &for_stack[for_stack_ptr - 1]; if(for_stack_ptr > 0 && var == fs->for_variable) { ubasic_get_variable(var, &t, 0, NULL); t.d.i += fs->step; ubasic_set_variable(var, &t, 0,NULL); /* NEXT end depends upon sign of STEP */ if ((fs->step >= 0 && t.d.i <= fs->to) || (fs->step < 0 && t.d.i >= fs->to)) tokenizer_goto(fs->resume_token); else for_stack_ptr--; } else ubasic_error("Mismatched NEXT"); }
static void let_statement (void) { int var; var = tokenizer_variable_num(); accept(T_LETTER); accept(T_EQUAL); set_variable(var, expression()); accept(T_EOL); }
static void input_statement(void) { struct typevalue r; var_t v; char buf[129]; uint8_t t; uint8_t first = 1; int l; t = current_token; if (t == TOKENIZER_STRING) { tokenizer_string_func(charout, NULL); tokenizer_next(); t = current_token; accept_either(TOKENIZER_COMMA, TOKENIZER_SEMICOLON); } else { charout('?', NULL); charout(' ', NULL); } begin_input(); /* Consider the single var allowed version of INPUT - it's saner for strings by far ? */ do { int n = 0; struct typevalue s[MAX_SUBSCRIPT]; if (!first) accept_either(TOKENIZER_COMMA, TOKENIZER_SEMICOLON); first = 0; t = current_token; v = tokenizer_variable_num(); accept_either(TOKENIZER_INTVAR, TOKENIZER_STRINGVAR); if (current_token == TOKENIZER_LEFTPAREN) n = parse_subscripts(s); /* FIXME: this works for stdin but not files .. */ if ((l = read(0, buf + 1, 128)) <= 0) { write(2, "EOF\n", 4); exit(1); } charreset(); /* Newline input so move to left */ if (t == TOKENIZER_INTVAR) { r.type = TYPE_INTEGER; /* For now */ r.d.i = atoi(buf + 1); /* FIXME: error checking */ } else { /* Turn a C string into a BASIC one */ r.type = TYPE_STRING; if (buf[l-1] == '\n') l--; *((uint8_t *)buf) = l; r.d.p = (uint8_t *)buf; } ubasic_set_variable(v, &r, n, s); } while(!statement_end()); end_input(); }
//static void inr_statement(void) void inr_statement(void) { long var; accept(TOKENIZER_INR); var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); ubasic_set_variable(var, kgetc()); accept(TOKENIZER_CR); }
//static void ina_statement(void) void ina_statement(void) { long var; int ch; var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); accept(TOKENIZER_EQ); accept(TOKENIZER_INA); ch = tokenizer_num_or_variable_num(); accept(TOKENIZER_VARIABLE); ubasic_set_variable(var, ubasic_get_adc(ch)); accept(TOKENIZER_CR); }
/*---------------------------------------------------------------------------*/ static void let_statement(void) { int var; var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); accept(TOKENIZER_EQ); ubasic_set_variable(var, expr()); DEBUG_PRINTF("let_statement: assign %d to %d\n", variables[var], var); accept(TOKENIZER_CR); }
//static void input_statement(void) void input_statement(void) { long var; char c; accept(TOKENIZER_INPUT); var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); ubasic_clear_strig(var); while(c != '\n'){ if((c = kgetc()) != 0){ ubasic_set_string(var, c); } } accept(TOKENIZER_CR); }
/*---------------------------------------------------------------------------*/ static void peek_statement(void) { VARIABLE_TYPE peek_addr; int var; accept(TOKENIZER_PEEK); peek_addr = expr(); accept(TOKENIZER_COMMA); var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); accept(TOKENIZER_CR); ubasic_set_variable(var, peek_function(peek_addr)); }
//static void inp_statement(void) void inp_statement(void) { long var; char c; int flg = 0; accept(TOKENIZER_INP); var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); while(flg == 0){ if((c = kgetc()) != 0){ ubasic_set_variable(var, c); flg = 1; } } accept(TOKENIZER_CR); }
/*---------------------------------------------------------------------------*/ static void let_statement(void) { var_t var; struct typevalue v; struct typevalue s[MAX_SUBSCRIPT]; int n = 0; var = tokenizer_variable_num(); accept_either(TOKENIZER_INTVAR, TOKENIZER_STRINGVAR); if (current_token == TOKENIZER_LEFTPAREN) n = parse_subscripts(s); accept_tok(TOKENIZER_EQ); expr(&v); DEBUG_PRINTF("let_statement: assign %d to %d\n", var, v.d.i); ubasic_set_variable(var, &v, n, s); }
//static void next_statement(void) void next_statement(void) { long var; accept(TOKENIZER_NEXT); var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); if(for_stack_ptr > 0 && var == for_stack[for_stack_ptr - 1].for_variable) { ubasic_set_variable(var, ubasic_get_variable(var) + 1); if(ubasic_get_variable(var) <= for_stack[for_stack_ptr - 1].to) { jump_linenum(for_stack[for_stack_ptr - 1].line_after_for); }else{ for_stack_ptr--; accept(TOKENIZER_CR); } }else{ accept(TOKENIZER_CR); } }
//static void peek_statement(void) void peek_statement(void) { long var; long addr; var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); accept(TOKENIZER_EQ); accept(TOKENIZER_PEEK); addr = tokenizer_bignum_or_variable_bignum(); if(current_token == TOKENIZER_VARIABLE){ accept(TOKENIZER_VARIABLE); }else{ accept(TOKENIZER_NUMBER); } #if TEST #else // ubasic_set_variable(var, *((uint32_t *)addr)); #endif accept(TOKENIZER_CR); }
//static void for_statement(void) void for_statement(void) { long for_variable, to; accept(TOKENIZER_FOR); for_variable = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); accept(TOKENIZER_EQ); ubasic_set_variable(for_variable, expr()); accept(TOKENIZER_TO); to = expr(); accept(TOKENIZER_CR); if(for_stack_ptr < MAX_FOR_STACK_DEPTH) { for_stack[for_stack_ptr].line_after_for = tokenizer_num(); for_stack[for_stack_ptr].for_variable = for_variable; for_stack[for_stack_ptr].to = to; for_stack_ptr++; }else{ } }
/*---------------------------------------------------------------------------*/ void dim_statement(void) { var_t v = tokenizer_variable_num(); value_t s1,s2 = 1; int n = 1; accept_either(TOKENIZER_STRINGVAR, TOKENIZER_INTVAR); /* For now A-Z/A-Z$ only */ if ((v & ~STRINGFLAG) > 25) ubasic_error("invalid array name"); accept_tok(TOKENIZER_LEFTPAREN); s1 = intexpr(); if (accept_either(TOKENIZER_RIGHTPAREN, TOKENIZER_COMMA) == TOKENIZER_COMMA) { s2 = intexpr(); n = 2; accept_tok(TOKENIZER_RIGHTPAREN); } if (v & STRINGFLAG) { uint8_t **p; v &= ~STRINGFLAG; if (stringsubs[v] || strings[v] != nullstr) ubasic_error(redimension); stringsubs[v] = n; stringdim[v][0] = s1; stringdim[v][1] = s2; p = calloc(s1 * s2, sizeof(uint8_t *)); strings[v] = (uint8_t *)p; for (n = 0; n < s1 * s2; n++) *p++ = nullstr; } else { if (variablesubs[v]) ubasic_error(redimension); variablesubs[v] = n; vardim[v][0] = s1; vardim[v][1] = s2; vararrays[v] = calloc(s1 * s2, sizeof(uint8_t *)); } }
/*---------------------------------------------------------------------------*/ static void for_statement(void) { var_t for_variable; value_t to, step = 1; struct typevalue t; for_variable = tokenizer_variable_num(); accept_tok(TOKENIZER_INTVAR); accept_tok(TOKENIZER_EQ); expr(&t); typecheck_int(&t); /* The set also typechecks the variable */ ubasic_set_variable(for_variable, &t, 0, NULL); accept_tok(TOKENIZER_TO); to = intexpr(); if (current_token == TOKENIZER_STEP) { accept_tok(TOKENIZER_STEP); step = intexpr(); } if (!statement_end()) syntax_error(); /* Save a pointer to the : or CR, when we return to statements it will do the right thing */ if(for_stack_ptr < MAX_FOR_STACK_DEPTH) { struct for_state *fs = &for_stack[for_stack_ptr]; fs->resume_token = tokenizer_pos(); fs->for_variable = for_variable; fs->to = to; fs->step = step; DEBUG_PRINTF("for_statement: new for, var %d to %d step %d\n", fs->for_variable, fs->to, fs->step); for_stack_ptr++; } else { DEBUG_PRINTF("for_statement: for stack depth exceeded\n"); } }
static int factor (void) { int r; switch (tokenizer_token()) { case T_NUMBER: r = tokenizer_num(); accept(T_NUMBER); break; case T_LEFT_PAREN: accept(T_LEFT_PAREN); r = expression(); accept(T_RIGHT_PAREN); break; default: r = get_variable( tokenizer_variable_num()); accept(T_LETTER); break; } return r; }
/*---------------------------------------------------------------------------*/ static void next_statement(void) { int var; accept(TOKENIZER_NEXT); var = tokenizer_variable_num(); accept(TOKENIZER_VARIABLE); if(for_stack_ptr > 0 && var == for_stack[for_stack_ptr - 1].for_variable) { ubasic_set_variable(var, ubasic_get_variable(var) + 1); if(ubasic_get_variable(var) <= for_stack[for_stack_ptr - 1].to) { jump_linenum(for_stack[for_stack_ptr - 1].line_after_for); } else { for_stack_ptr--; accept(TOKENIZER_CR); } } else { DEBUG_PRINTF("next_statement: non-matching next (expected %d, found %d)\n", for_stack[for_stack_ptr - 1].for_variable, var); accept(TOKENIZER_CR); } }