#include #include #include #include #include // Standard words: // arithmetic // + - / * =: byte arithmetic // ^ & |: bitwise boolean arithmetic // p pop // d dup // s swap // b push next byte // w push next 2 bytes // l push next 4 bytes // $ pop N, push N bytes, push N // ? if // , else // # end // : start def/special // ; end def/return // if upper case, call word // . print #define BFORTH_PGM_SIZE (1024) #define BFORTH_STACK_SIZE (64) #define BFORTH_RSTACK_SIZE (32) const uint8_t * bf_prog = NULL; const uint8_t * bfdict[26]; uint8_t bfvars[26]; uint8_t bf_stack[BFORTH_STACK_SIZE]; const uint8_t * bf_linkstack[BFORTH_RSTACK_SIZE]; uint8_t * bf_stacktop; const uint8_t ** bf_linkstacktop; const uint8_t * bf_pc; static void BF_Scan(uint8_t word) { while(*bf_pc != word) ++bf_pc; ++bf_pc; } #define DSTKPUSH(x) (*(bf_stacktop++) = x) #define DSTKPOP (*(--bf_stacktop)) #define DSTKTOP (*(bf_stacktop - 1)) #define DSTKIDX(i) (*(bf_stacktop - 1 - i)) void BF_Step(void) { if(*bf_pc == '\0') return; uint8_t tmp = *bf_pc++; if(isupper(tmp)) { *bf_linkstacktop++ = bf_pc; bf_pc = bfdict[tmp - 'A']; } else { switch(tmp) { case '+': tmp = DSTKPOP; DSTKTOP += tmp; break; case '-': tmp = DSTKPOP; DSTKTOP -= tmp; break; case '*': tmp = DSTKPOP; DSTKTOP *= tmp; break; case '/': tmp = DSTKPOP; DSTKTOP /= tmp; break; case '^': tmp = DSTKPOP; DSTKTOP ^= tmp; break; case '&': tmp = DSTKPOP; DSTKTOP &= tmp; break; case '|': tmp = DSTKPOP; DSTKTOP |= tmp; break; case 'b': DSTKPUSH(*bf_pc++); break; case 'p': DSTKPOP; break; case 'd': tmp = DSTKTOP; DSTKPUSH(tmp); break; case 's': tmp = DSTKIDX(0); DSTKIDX(0) = DSTKIDX(1); DSTKIDX(1) = tmp; break; case '~':// Reset state bf_stacktop = bf_stack; bf_linkstacktop = bf_linkstack; bf_pc = bf_prog; break; case '?':// if if(!DSTKPOP) { // Scan to first word following else (nested ifs not supported) BF_Scan(','); } // else continue break; case ',':// else // Scan past else clause to end. BF_Scan('#'); break; case '#':// end (do nothing) break; case ':':// Start definition/escape special tmp = *bf_pc; if(isupper(tmp)) { printf("defining word %c\n", tmp); bfdict[tmp - 'A'] = bf_pc + 1; BF_Scan(';'); } // else // { // if(tmp == 'x') // // } break; case ';':// End definition/return bf_pc = *(--bf_linkstacktop); break; case '.': printf("0x%02X\n", DSTKPOP); break; // case '.': printf("%d\n", DSTKPOP); break; // case '.': printf("%c", DSTKPOP); break; } } } void BF_Run(const char * src) { bf_prog = src; bf_stacktop = bf_stack; bf_linkstacktop = bf_linkstack; bf_pc = src; while(*bf_pc) { BF_Step(); printf("pc: %d ", (int)(bf_pc - bf_prog)); printf("stk: %d ", (int)(bf_stacktop - bf_stack)); printf("lstk: %d\n", (int)(bf_linkstacktop - bf_linkstack)); } } int main(int argc, const char * argv[]) { // strcpy(bf_prog, ":Ab\x40""b\x02+.;:Bb\x55""b\x11*.;ABA"); // strcpy(bf_prog, "b\x42+."); // if(argc >= 2) // strcpy(bf_prog, argv[1]); BF_Run(":Ab\x40""b\x02+.;"); BF_Run(":Bb\x55""b\x11*.;"); BF_Run("ABA"); }