|
|
|
@ -52,23 +52,24 @@ enum fh_error { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const char *errornames[] = { |
|
|
|
|
[FH_OK] = "OK", |
|
|
|
|
[FH_ERR_CS_OVERFLOW] = "CS_OVERFLOW", |
|
|
|
|
[FH_ERR_DS_OVERFLOW] = "DS_OVERFLOW", |
|
|
|
|
[FH_ERR_RS_OVERFLOW] = "RS_OVERFLOW", |
|
|
|
|
[FH_ERR_CS_UNDERFLOW] = "CS_UNDERFLOW", |
|
|
|
|
[FH_ERR_DS_UNDERFLOW] = "DS_UNDERFLOW", |
|
|
|
|
[FH_ERR_RS_UNDERFLOW] = "RS_UNDERFLOW", |
|
|
|
|
[FH_ERR_HEAP_FULL] = "HEAP_FULL", |
|
|
|
|
[FH_ERR_DICT_FULL] = "DICT_FULL", |
|
|
|
|
[FH_ERR_COMPILE_FULL] = "COMPILE_FULL", |
|
|
|
|
[FH_ERR_NAME_TOO_LONG] = "NAME_TOO_LONG", |
|
|
|
|
[FH_ERR_INVALID_STATE] = "INVALID_STATE", |
|
|
|
|
[FH_ERR_INTERNAL] = "INTERNAL", |
|
|
|
|
[FH_ERR_UNKNOWN_WORD] = "UNKNOWN_WORD", |
|
|
|
|
[FH_OK] = "OK", |
|
|
|
|
[FH_ERR_CS_OVERFLOW] = "CS_OVERFLOW", |
|
|
|
|
[FH_ERR_DS_OVERFLOW] = "DS_OVERFLOW", |
|
|
|
|
[FH_ERR_RS_OVERFLOW] = "RS_OVERFLOW", |
|
|
|
|
[FH_ERR_CS_UNDERFLOW] = "CS_UNDERFLOW", |
|
|
|
|
[FH_ERR_DS_UNDERFLOW] = "DS_UNDERFLOW", |
|
|
|
|
[FH_ERR_RS_UNDERFLOW] = "RS_UNDERFLOW", |
|
|
|
|
[FH_ERR_HEAP_FULL] = "HEAP_FULL", |
|
|
|
|
[FH_ERR_DICT_FULL] = "DICT_FULL", |
|
|
|
|
[FH_ERR_COMPILE_FULL] = "COMPILE_FULL", |
|
|
|
|
[FH_ERR_NAME_TOO_LONG] = "NAME_TOO_LONG", |
|
|
|
|
[FH_ERR_INVALID_STATE] = "INVALID_STATE", |
|
|
|
|
[FH_ERR_INTERNAL] = "INTERNAL", |
|
|
|
|
[FH_ERR_UNKNOWN_WORD] = "UNKNOWN_WORD", |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const char *fherr_name(enum fh_error e) { |
|
|
|
|
const char *fherr_name(enum fh_error e) |
|
|
|
|
{ |
|
|
|
|
if (e >= FH_ERR_MAX) { |
|
|
|
|
return "Unknown"; |
|
|
|
|
} |
|
|
|
@ -112,6 +113,13 @@ enum fh_state { |
|
|
|
|
FH_STATE_INTERPRET = 0, |
|
|
|
|
FH_STATE_COMPILE, |
|
|
|
|
FH_STATE_SHUTDOWN, |
|
|
|
|
FH_STATE_MAX, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const char *statenames[] = { |
|
|
|
|
[FH_STATE_INTERPRET] = "INTERPRET", |
|
|
|
|
[FH_STATE_COMPILE] = "COMPILE", |
|
|
|
|
[FH_STATE_SHUTDOWN] = "SHUTDOWN", |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
enum fh_substate { |
|
|
|
@ -121,6 +129,16 @@ enum fh_substate { |
|
|
|
|
FH_SUBSTATE_DOTQUOTE, |
|
|
|
|
FH_SUBSTATE_PARENCOMMENT, |
|
|
|
|
FH_SUBSTATE_LINECOMMENT, |
|
|
|
|
FH_SUBSTATE_MAX, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const char *substatenames[] = { |
|
|
|
|
[FH_SUBSTATE_NONE] = "NONE", |
|
|
|
|
[FH_SUBSTATE_COLONNAME] = "COLONNAME", |
|
|
|
|
[FH_SUBSTATE_SQUOTE] = "SQUOTE", |
|
|
|
|
[FH_SUBSTATE_DOTQUOTE] = "DOTQUOTE", |
|
|
|
|
[FH_SUBSTATE_PARENCOMMENT] = "PARENCOMMENT", |
|
|
|
|
[FH_SUBSTATE_LINECOMMENT] = "LINECOMMENT", |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct fh_thread_s { |
|
|
|
@ -246,6 +264,26 @@ static inline enum fh_error cs_push(struct fh_thread_s *fh, uint32_t in) |
|
|
|
|
|
|
|
|
|
//endregion Push & Pop
|
|
|
|
|
|
|
|
|
|
static void showstate(const struct fh_thread_s *fh) { |
|
|
|
|
if(fh->substate==0) { |
|
|
|
|
LOG("state = %s", statenames[fh->state]); |
|
|
|
|
} else { |
|
|
|
|
LOG("state = %s.%s", statenames[fh->state], substatenames[fh->substate]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void fh_setstate(struct fh_thread_s *fh, enum fh_state state, enum fh_substate substate) |
|
|
|
|
{ |
|
|
|
|
fh->state = state; |
|
|
|
|
fh->substate = substate; |
|
|
|
|
showstate(fh); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void fh_setsubstate(struct fh_thread_s *fh, enum fh_substate substate) |
|
|
|
|
{ |
|
|
|
|
fh->substate = substate; |
|
|
|
|
showstate(fh); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum fh_error fh_allot( |
|
|
|
|
struct fh_thread_s *fh, |
|
|
|
@ -406,9 +444,7 @@ enum fh_error w_colon(struct fh_thread_s *fh) |
|
|
|
|
return FH_ERR_INVALID_STATE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LOG("state=COMPILE"); |
|
|
|
|
fh->state = FH_STATE_COMPILE; |
|
|
|
|
fh->substate = FH_SUBSTATE_COLONNAME; |
|
|
|
|
fh_setstate(fh, FH_STATE_COMPILE, FH_SUBSTATE_COLONNAME); |
|
|
|
|
|
|
|
|
|
if (fh->dict_top >= DICT_SIZE) { |
|
|
|
|
return FH_ERR_DICT_FULL; |
|
|
|
@ -434,8 +470,7 @@ enum fh_error w_semicolon(struct fh_thread_s *fh) |
|
|
|
|
memcpy(&fh->compile[addr], &instr, sizeof(struct fh_instruction_s)); |
|
|
|
|
|
|
|
|
|
/* Return to interpret state */ |
|
|
|
|
LOG("state=INTERPRET"); |
|
|
|
|
fh->state = FH_STATE_INTERPRET; |
|
|
|
|
fh_setstate(fh, FH_STATE_INTERPRET, 0); |
|
|
|
|
fh->dict[fh->dict_top].end = fh->compile_top; /* one past the end cell */ |
|
|
|
|
fh->dict_top++; |
|
|
|
|
return FH_OK; |
|
|
|
@ -476,32 +511,32 @@ enum fh_error w_space(struct fh_thread_s *fh) |
|
|
|
|
|
|
|
|
|
enum fh_error w_s_quote(struct fh_thread_s *fh) |
|
|
|
|
{ |
|
|
|
|
fh->substate = FH_SUBSTATE_SQUOTE; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_SQUOTE); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum fh_error w_dot_quote(struct fh_thread_s *fh) |
|
|
|
|
{ |
|
|
|
|
fh->substate = FH_SUBSTATE_DOTQUOTE; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_DOTQUOTE); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum fh_error w_backslash(struct fh_thread_s *fh) |
|
|
|
|
{ |
|
|
|
|
fh->substate = FH_SUBSTATE_LINECOMMENT; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_LINECOMMENT); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum fh_error w_paren(struct fh_thread_s *fh) |
|
|
|
|
{ |
|
|
|
|
fh->substate = FH_SUBSTATE_PARENCOMMENT; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_PARENCOMMENT); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum fh_error w_bye(struct fh_thread_s *fh) |
|
|
|
|
{ |
|
|
|
|
LOG("state=SHUTDOWN"); |
|
|
|
|
fh->state = FH_STATE_SHUTDOWN; |
|
|
|
|
fh_setstate(fh, FH_STATE_SHUTDOWN, 0); |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -629,7 +664,7 @@ enum fh_error fh_handle_word( |
|
|
|
|
uint32_t addr = 0; |
|
|
|
|
enum fh_error rv; |
|
|
|
|
while (w->handler) { |
|
|
|
|
if (0 == strncasecmp(start, w->name, len) && w->name[len]==0) { |
|
|
|
|
if (0 == strncasecmp(start, w->name, len) && w->name[len] == 0) { |
|
|
|
|
// word found!
|
|
|
|
|
if (fh->state == FH_STATE_COMPILE && !w->immediate) { |
|
|
|
|
LOG("Compile word call: %s", w->name); |
|
|
|
@ -654,7 +689,7 @@ enum fh_error fh_handle_word( |
|
|
|
|
char *endptr; |
|
|
|
|
long v = strtol(start, &endptr, 0); |
|
|
|
|
if (errno != 0 || endptr == start) { |
|
|
|
|
LOGE("Unknown word and fail to parse as number: %.*s", (int)len, start); |
|
|
|
|
LOGE("Unknown word and fail to parse as number: %.*s", (int) len, start); |
|
|
|
|
return FH_ERR_UNKNOWN_WORD; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -667,7 +702,7 @@ enum fh_error fh_handle_word( |
|
|
|
|
} else { |
|
|
|
|
/* interpret */ |
|
|
|
|
LOG("Interpret number: %d", v); |
|
|
|
|
TRY(ds_push(fh, (uint32_t)v)); |
|
|
|
|
TRY(ds_push(fh, (uint32_t) v)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return FH_OK; |
|
|
|
@ -717,13 +752,13 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, char *linebuf) |
|
|
|
|
|
|
|
|
|
if (fh->substate == FH_SUBSTATE_NONE) { |
|
|
|
|
/* eval a word */ |
|
|
|
|
LOG("Handle \"%.*s\"", (int)length, rp); |
|
|
|
|
LOG("Handle \"%.*s\"", (int) length, rp); |
|
|
|
|
TRY(fh_handle_word(fh, rp, length)); |
|
|
|
|
} else { |
|
|
|
|
/* new word's name is found */ |
|
|
|
|
LOG("New word name = \"%.*s\"", (int)length, rp); |
|
|
|
|
LOG("New word name = \"%.*s\"", (int) length, rp); |
|
|
|
|
strncpy(fh->dict[fh->dict_top].name, rp, length); |
|
|
|
|
fh->substate = FH_SUBSTATE_NONE; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_NONE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (end) { |
|
|
|
@ -738,9 +773,9 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, char *linebuf) |
|
|
|
|
end = strchr(rp, '"'); |
|
|
|
|
if (end) { |
|
|
|
|
length = end - rp - 1; |
|
|
|
|
LOG("Quoted string: \"%.*s\"", (int)length, rp); |
|
|
|
|
LOG("Quoted string: \"%.*s\"", (int) length, rp); |
|
|
|
|
TRY(fh_handle_quoted_string(fh, rp, length)); |
|
|
|
|
fh->substate = FH_SUBSTATE_NONE; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_NONE); |
|
|
|
|
rp = end + 1; |
|
|
|
|
} else { |
|
|
|
|
/* no end. this is weird. */ |
|
|
|
@ -753,7 +788,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, char *linebuf) |
|
|
|
|
end = strchr(rp, ')'); |
|
|
|
|
if (end) { |
|
|
|
|
LOG("Discard inline comment"); |
|
|
|
|
fh->substate = FH_SUBSTATE_NONE; |
|
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_NONE); |
|
|
|
|
rp = end + 1; |
|
|
|
|
} else { |
|
|
|
|
/* no end, discard all */ |
|
|
|
@ -807,7 +842,7 @@ int main(int argc, char *argv[]) |
|
|
|
|
linecnt++; |
|
|
|
|
|
|
|
|
|
// trim
|
|
|
|
|
size_t end = strlen(linebuf) -1 ; |
|
|
|
|
size_t end = strlen(linebuf) - 1; |
|
|
|
|
while (iswhite(linebuf[end])) { |
|
|
|
|
linebuf[end] = 0; |
|
|
|
|
} |
|
|
|
|