postpone works now

master
Ondřej Hruška 3 years ago
parent 1be97e4f0e
commit 2f0f1877fe
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 4
      if.forth
  2. 28
      include/fh_runtime.h
  3. 9
      postpone.forth
  4. 55
      src/fh_builtins.c
  5. 202
      src/fh_runtime.c

@ -0,0 +1,4 @@
: yesno IF ." yes" ELSE ." no" THEN ;
1 yesno
0 yesno

@ -43,6 +43,9 @@ enum fb_instruction_kind {
/* Jump if zero */ /* Jump if zero */
FH_INSTR_JUMPZERO, FH_INSTR_JUMPZERO,
/* Postponed word */
FH_INSTR_POSTPONED_WORD,
}; };
/** One instruction in bytecode */ /** One instruction in bytecode */
@ -65,9 +68,13 @@ _Static_assert(sizeof(struct fh_instruction_s) % 4 == 0, "Instruction struct is
/** Forth runtime major state */ /** Forth runtime major state */
enum fh_state { enum fh_state {
/** Interactive interpret mode */
FH_STATE_INTERPRET = 0, FH_STATE_INTERPRET = 0,
/** Compiling */
FH_STATE_COMPILE, FH_STATE_COMPILE,
/** Quit from RUN to interpret */
FH_STATE_QUIT, FH_STATE_QUIT,
/** Shutting down the runtime */
FH_STATE_SHUTDOWN, FH_STATE_SHUTDOWN,
FH_STATE_MAX, FH_STATE_MAX,
}; };
@ -75,18 +82,20 @@ enum fh_state {
/** Forth runtime minor state */ /** Forth runtime minor state */
enum fh_substate { enum fh_substate {
FH_SUBSTATE_NONE = 0, FH_SUBSTATE_NONE = 0,
FH_SUBSTATE_COLONNAME, FH_SUBSTATE_COLON_NAME,
FH_SUBSTATE_SQUOTE, FH_SUBSTATE_S_QUOTE,
FH_SUBSTATE_DOTQUOTE, FH_SUBSTATE_DOT_QUOTE,
FH_SUBSTATE_PARENCOMMENT, FH_SUBSTATE_PAREN_COMMENT,
FH_SUBSTATE_LINECOMMENT, FH_SUBSTATE_LINE_COMMENT,
FH_SUBSTATE_EXIT, FH_SUBSTATE_EXIT,
FH_SUBSTATE_SEENAME, FH_SUBSTATE_SEE_NAME,
FH_SUBSTATE_POSTPONE_NAME,
FH_SUBSTATE_MAX, FH_SUBSTATE_MAX,
}; };
/** Word struct as they are stored in the dictionary */ /** Word struct as they are stored in the dictionary */
struct fh_word_s { struct fh_word_s {
uint32_t index;
/** Word name */ /** Word name */
char name[MAX_NAME_LEN]; char name[MAX_NAME_LEN];
/** /**
@ -185,5 +194,12 @@ _Static_assert(WORDALIGNED(1024) == 1024, "word align");
if (FH_OK != (rv = (x))) return rv; \ if (FH_OK != (rv = (x))) return rv; \
} while (0) } while (0)
enum fh_error fh_handle_ascii_word(
struct fh_thread_s *fh,
const char *name,
size_t wordlen
);
enum fh_error fh_handle_word(struct fh_thread_s *fh, const struct fh_word_s *w);
#endif //FORTH_FH_RUNTIME_H #endif //FORTH_FH_RUNTIME_H

@ -0,0 +1,9 @@
: ENDIF POSTPONE THEN ; IMMEDIATE
: yesno IF ." yes" ELSE ." no" ENDIF ;
see ENDIF
see yesno
1 yesno
0 yesno

@ -293,13 +293,25 @@ static enum fh_error w_colon(struct fh_thread_s *fh, const struct fh_word_s *w)
(void) w; (void) w;
ENSURE_STATE(FH_STATE_INTERPRET); ENSURE_STATE(FH_STATE_INTERPRET);
fh_setstate(fh, FH_STATE_COMPILE, FH_SUBSTATE_COLONNAME); fh_setstate(fh, FH_STATE_COMPILE, FH_SUBSTATE_COLON_NAME);
if (fh->dict_top >= DICT_SIZE) { if (fh->dict_top >= DICT_SIZE) {
return FH_ERR_DICT_FULL; return FH_ERR_DICT_FULL;
} }
fh->dict[fh->dict_top].start = fh->compile_top; struct fh_word_s *new_word = &fh->dict[fh->dict_top];
fh->dict[fh->dict_top].handler = w_user_word; new_word->index = fh->dict_top;
new_word->start = fh->compile_top;
new_word->handler = w_user_word;
return FH_OK;
}
static enum fh_error w_postpone(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
ENSURE_STATE(FH_STATE_COMPILE);
fh_setsubstate(fh, FH_SUBSTATE_POSTPONE_NAME);
return FH_OK; return FH_OK;
} }
@ -337,6 +349,21 @@ static enum fh_error w_semicolon(struct fh_thread_s *fh, const struct fh_word_s
return FH_OK; return FH_OK;
} }
static enum fh_error w_immediate(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
enum fh_error rv;
if (fh->dict_top == 0) {
LOGE("Dict is empty, cannot modify previous word!");
return FH_ERR_INVALID_STATE;
}
fh->dict[fh->dict_top - 1].immediate = 1;
return FH_OK;
}
static enum fh_error w_recurse(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_recurse(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
@ -669,28 +696,36 @@ static enum fh_error w_exit(struct fh_thread_s *fh, const struct fh_word_s *w)
static enum fh_error w_s_quote(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_s_quote(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
fh_setsubstate(fh, FH_SUBSTATE_SQUOTE); fh_setsubstate(fh, FH_SUBSTATE_S_QUOTE);
return FH_OK;
}
static enum fh_error w_error_word0(struct fh_thread_s *fh, const struct fh_word_s *w)
{
(void) w;
LOGE("Invocation of word #0 (illegal)");
fh_setstate(fh, FH_STATE_QUIT, 0);
return FH_OK; return FH_OK;
} }
static enum fh_error w_dot_quote(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_dot_quote(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
fh_setsubstate(fh, FH_SUBSTATE_DOTQUOTE); fh_setsubstate(fh, FH_SUBSTATE_DOT_QUOTE);
return FH_OK; return FH_OK;
} }
static enum fh_error w_backslash(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_backslash(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
fh_setsubstate(fh, FH_SUBSTATE_LINECOMMENT); fh_setsubstate(fh, FH_SUBSTATE_LINE_COMMENT);
return FH_OK; return FH_OK;
} }
static enum fh_error w_paren(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_paren(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
fh_setsubstate(fh, FH_SUBSTATE_PARENCOMMENT); fh_setsubstate(fh, FH_SUBSTATE_PAREN_COMMENT);
return FH_OK; return FH_OK;
} }
@ -781,7 +816,7 @@ static enum fh_error w_emit(struct fh_thread_s *fh, const struct fh_word_s *w)
static enum fh_error w_see(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_see(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
enum fh_error rv; enum fh_error rv;
fh_setsubstate(fh, FH_SUBSTATE_SEENAME); fh_setsubstate(fh, FH_SUBSTATE_SEE_NAME);
return FH_OK; return FH_OK;
} }
@ -877,6 +912,7 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
}; };
const struct name_and_handler builtins[] = { const struct name_and_handler builtins[] = {
{"", w_error_word0, 1, 0},
{"s\"", w_s_quote, 1, 0}, {"s\"", w_s_quote, 1, 0},
{".\"", w_dot_quote, 1, 0}, {".\"", w_dot_quote, 1, 0},
/* Compiler control words */ /* Compiler control words */
@ -969,6 +1005,8 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
{"(", w_paren, 1, 0}, // enclosed comment {"(", w_paren, 1, 0}, // enclosed comment
{"recurse", w_recurse, 1, 0}, {"recurse", w_recurse, 1, 0},
{"reset", w_reset, 1, 0}, {"reset", w_reset, 1, 0},
{"immediate", w_immediate, 1, 0},
{"postpone", w_postpone, 1, 0},
{"see", w_see, 0, 0}, {"see", w_see, 0, 0},
{ /* end marker */ } { /* end marker */ }
@ -980,6 +1018,7 @@ enum fh_error register_builtin_words(struct fh_thread_s *fh)
enum fh_error rv; enum fh_error rv;
while (p->handler) { while (p->handler) {
strcpy(w.name, p->name); strcpy(w.name, p->name);
w.index = fh->dict_top;
w.handler = p->handler; w.handler = p->handler;
w.builtin = 1; w.builtin = 1;
w.immediate = p->immediate; w.immediate = p->immediate;

@ -16,19 +16,21 @@ struct fh_global_s fh_globals = {};
static const char *statenames[FH_STATE_MAX] = { static const char *statenames[FH_STATE_MAX] = {
[FH_STATE_INTERPRET] = "INTERPRET", [FH_STATE_INTERPRET] = "INTERPRET",
[FH_STATE_COMPILE] = "COMPILE", [FH_STATE_COMPILE] = "COMPILE",
[FH_STATE_QUIT] = "RUN",
[FH_STATE_SHUTDOWN] = "SHUTDOWN", [FH_STATE_SHUTDOWN] = "SHUTDOWN",
}; };
/** Sub-state names */ /** Sub-state names */
static const char *substatenames[FH_SUBSTATE_MAX] = { static const char *substatenames[FH_SUBSTATE_MAX] = {
[FH_SUBSTATE_NONE] = "NONE", [FH_SUBSTATE_NONE] = "NONE",
[FH_SUBSTATE_COLONNAME] = "COLONNAME", [FH_SUBSTATE_COLON_NAME] = "COLON_NAME",
[FH_SUBSTATE_SQUOTE] = "SQUOTE", [FH_SUBSTATE_S_QUOTE] = "S_QUOTE",
[FH_SUBSTATE_DOTQUOTE] = "DOTQUOTE", [FH_SUBSTATE_DOT_QUOTE] = "DOT_QUOTE",
[FH_SUBSTATE_PARENCOMMENT] = "PARENCOMMENT", [FH_SUBSTATE_PAREN_COMMENT] = "PAREN_COMMENT",
[FH_SUBSTATE_LINECOMMENT] = "LINECOMMENT", [FH_SUBSTATE_LINE_COMMENT] = "LINE_COMMENT",
[FH_SUBSTATE_EXIT] = "EXIT", [FH_SUBSTATE_EXIT] = "EXIT",
[FH_SUBSTATE_SEENAME] = "SEENAME", [FH_SUBSTATE_SEE_NAME] = "SEE_NAME",
[FH_SUBSTATE_POSTPONE_NAME] = "POSTPONE_NAME",
}; };
/** Add a word to the dictionary. */ /** Add a word to the dictionary. */
@ -96,15 +98,34 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
uint32_t strl; uint32_t strl;
uint32_t val; uint32_t val;
uint32_t addr = 0; uint32_t addr = 0;
struct fh_instruction_s instr2;
switch (instr->kind) { switch (instr->kind) {
case FH_INSTR_NUMBER: case FH_INSTR_NUMBER:
TRY(ds_push(fh, instr->data)); TRY(ds_push(fh, instr->data));
goto instr; goto instr;
case FH_INSTR_POSTPONED_WORD:
if (fh->state == FH_STATE_COMPILE) {
w2 = &fh->dict[instr->data];
if (w2->immediate) {
LOG("Call immediate postponed word: %s", w2->name);
TRY(w2->handler(fh, w2));
} else {
LOG("Add postponed word: %s", w2->name);
instr_init(&instr2, FH_INSTR_WORD, instr->data);
TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
}
} else {
LOGE("Postpone in interpret mode!");
goto end;
}
goto instr;
case FH_INSTR_WORD: case FH_INSTR_WORD:
w2 = &fh->dict[instr->data]; w2 = &fh->dict[instr->data];
if (w2->builtin) { if (w2->builtin) {
LOG("Exec: builtin-word %s", w2->name); LOG("Exec: builtin-word \"%s\"", w2->name);
w2->handler(fh, w2); w2->handler(fh, w2);
if (fh->substate == FH_SUBSTATE_EXIT) { if (fh->substate == FH_SUBSTATE_EXIT) {
fh_setsubstate(fh, 0); fh_setsubstate(fh, 0);
@ -122,6 +143,11 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
} }
case FH_INSTR_JUMPZERO: case FH_INSTR_JUMPZERO:
if (instr->data == MAGICADDR_UNRESOLVED) {
LOGE("Encountered unresolved jump!");
goto end;
}
TRY(ds_pop(fh, &val)); TRY(ds_pop(fh, &val));
if (0 == val) { if (0 == val) {
fh->execptr = instr->data; fh->execptr = instr->data;
@ -129,6 +155,10 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
goto instr; goto instr;
case FH_INSTR_JUMP: case FH_INSTR_JUMP:
if (instr->data == MAGICADDR_UNRESOLVED) {
LOGE("Encountered unresolved jump!");
goto end;
}
fh->execptr = instr->data; fh->execptr = instr->data;
goto instr; goto instr;
@ -191,12 +221,12 @@ static enum fh_error fh_handle_quoted_string(
if (fh->state == FH_STATE_INTERPRET) { if (fh->state == FH_STATE_INTERPRET) {
switch (fh->substate) { switch (fh->substate) {
case FH_SUBSTATE_SQUOTE: case FH_SUBSTATE_S_QUOTE:
TRY(fh_heap_put(fh, start, len)); TRY(fh_heap_put(fh, start, len));
TRY(ds_push(fh, addr)); TRY(ds_push(fh, addr));
TRY(ds_push(fh, len)); TRY(ds_push(fh, len));
break; break;
case FH_SUBSTATE_DOTQUOTE: case FH_SUBSTATE_DOT_QUOTE:
FHPRINT("%.*s", (int) len, start); FHPRINT("%.*s", (int) len, start);
break; break;
@ -206,7 +236,7 @@ static enum fh_error fh_handle_quoted_string(
} else { } else {
LOG("Compile a string"); LOG("Compile a string");
/* compile */ /* compile */
if (fh->substate == FH_SUBSTATE_SQUOTE) { if (fh->substate == FH_SUBSTATE_S_QUOTE) {
instr_init(&instr, FH_INSTR_ALLOCSTR, len); instr_init(&instr, FH_INSTR_ALLOCSTR, len);
} else { } else {
instr_init(&instr, FH_INSTR_TYPESTR, len); instr_init(&instr, FH_INSTR_TYPESTR, len);
@ -217,40 +247,55 @@ static enum fh_error fh_handle_quoted_string(
return FH_OK; return FH_OK;
} }
/** Process a word read from input */ enum fh_error fh_handle_word(struct fh_thread_s *fh, const struct fh_word_s *w)
static enum fh_error fh_handle_word(
struct fh_thread_s *fh,
const char *start,
const size_t wordlen
)
{ {
if (wordlen >= MAX_NAME_LEN) {
return FH_ERR_NAME_TOO_LONG;
}
/* First, try if it's a known word */
// TODO we could use binary search if the dict was ordered
struct fh_word_s *w = &fh->dict[0];
struct fh_instruction_s instr; struct fh_instruction_s instr;
uint32_t cnt = 0;
enum fh_error rv; enum fh_error rv;
while (w->handler) {
if (0 == strncasecmp(start, w->name, wordlen) && w->name[wordlen] == 0) {
// word found!
if (fh->state == FH_STATE_COMPILE && !w->immediate) { if (fh->state == FH_STATE_COMPILE && !w->immediate) {
LOG("Compile word call: %s", w->name); LOG("Compile word call: %s", w->name);
instr_init(&instr, FH_INSTR_WORD, cnt); instr_init(&instr, FH_INSTR_WORD, w->index);
TRY(fh_compile_put(fh, &instr, INSTR_SIZE)); TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
} else { } else {
/* interpret */ /* interpret or immediate in compiled code */
LOG("Interpret word: %s", w->name); LOG("Run word: %s", w->name);
TRY(w->handler(fh, w)); TRY(w->handler(fh, w));
} }
return FH_OK; return FH_OK;
} }
static struct fh_word_s *find_word(struct fh_thread_s *fh, const char *name, const size_t wordlen)
{
struct fh_word_s *w = &fh->dict[0];
uint32_t cnt = 0;
while (w->handler) {
if (0 == strncasecmp(name, w->name, wordlen) && w->name[wordlen] == 0) {
return w;
}
w++; w++;
cnt++; cnt++;
} }
return NULL;
}
/** Process a word read from input */
enum fh_error fh_handle_ascii_word(
struct fh_thread_s *fh,
const char *name,
const size_t wordlen
)
{
enum fh_error rv;
if (wordlen >= MAX_NAME_LEN) {
return FH_ERR_NAME_TOO_LONG;
}
/* First, try if it's a known word */
struct fh_word_s *w = find_word(fh, name, wordlen);
if (w) {// word found!
TRY(fh_handle_word(fh, w));
return FH_OK;
}
/* word not found, try parsing as number */ /* word not found, try parsing as number */
errno = 0; errno = 0;
@ -258,22 +303,23 @@ static enum fh_error fh_handle_word(
int base = (int) fh->base; int base = (int) fh->base;
// prefix can override BASE - this is a syntax extension // prefix can override BASE - this is a syntax extension
if (start[0] == '0') { if (name[0] == '0') {
if (start[1] == 'x') { if (name[1] == 'x') {
base = 16; base = 16;
} else if (start[1] == 'b') { } else if (name[1] == 'b') {
base = 2; base = 2;
} else if (start[1] == 'o') { } else if (name[1] == 'o') {
base = 8; base = 8;
} }
} }
long v = strtol(start, &endptr, base); // XXX if base is 0, this will use auto-detection long v = strtol(name, &endptr, base); // XXX if base is 0, this will use auto-detection
if (errno != 0 || (endptr - start) != wordlen) { if (errno != 0 || (endptr - name) != wordlen) {
LOGE("Unknown word and fail to parse as number: %.*s", (int) wordlen, start); LOGE("Unknown word and fail to parse as number: %.*s", (int) wordlen, name);
return FH_ERR_UNKNOWN_WORD; return FH_ERR_UNKNOWN_WORD;
} }
struct fh_instruction_s instr;
if (fh->state == FH_STATE_COMPILE) { if (fh->state == FH_STATE_COMPILE) {
LOG("Compile number: %ld", v); LOG("Compile number: %ld", v);
instr_init(&instr, FH_INSTR_NUMBER, (uint32_t) v); instr_init(&instr, FH_INSTR_NUMBER, (uint32_t) v);
@ -287,7 +333,8 @@ static enum fh_error fh_handle_word(
return FH_OK; return FH_OK;
} }
static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w) { static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w)
{
if (w->handler == w_user_word) { if (w->handler == w_user_word) {
uint32_t execptr = w->start; uint32_t execptr = w->start;
@ -307,9 +354,21 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w) {
goto instr; goto instr;
case FH_INSTR_WORD: case FH_INSTR_WORD:
wn = instr->data;
w2 = &fh->dict[instr->data]; w2 = &fh->dict[instr->data];
FHPRINT("Call(%s, 0x%08x)\n", w2->name, instr->data); if (w2->name[0]) {
FHPRINT("Call(%s)\n", w2->name);
} else {
FHPRINT("Call(0x%08x)\n", instr->data);
}
goto instr;
case FH_INSTR_POSTPONED_WORD:
w2 = &fh->dict[instr->data];
if (w2->name[0]) {
FHPRINT("Postpone(%s)\n", w2->name);
} else {
FHPRINT("Postpone(0x%08x)\n", instr->data);
}
goto instr; goto instr;
case FH_INSTR_JUMPZERO: case FH_INSTR_JUMPZERO:
@ -346,25 +405,39 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w) {
/** Decompile a word */ /** Decompile a word */
static enum fh_error fh_see_word( static enum fh_error fh_see_word(
struct fh_thread_s *fh, struct fh_thread_s *fh,
const char *start, const char *name,
const size_t wordlen const size_t wordlen
) )
{ {
struct fh_word_s *w = &fh->dict[0]; struct fh_word_s *w = find_word(fh, name, wordlen);
uint32_t cnt = 0; if (!w) {
enum fh_error rv; return FH_ERR_UNKNOWN_WORD;
while (w->handler) { }
if (0 == strncasecmp(start, w->name, wordlen) && w->name[wordlen] == 0) {
// word found!
show_word(fh, w); show_word(fh, w);
return FH_OK; return FH_OK;
} }
w++;
cnt++; /** Postpone a word */
} static enum fh_error fh_postpone_word(
struct fh_thread_s *fh,
const char *name,
const size_t wordlen
)
{
struct fh_word_s *w = find_word(fh, name, wordlen);
if (!w) {
return FH_ERR_UNKNOWN_WORD; return FH_ERR_UNKNOWN_WORD;
} }
enum fh_error rv;
struct fh_instruction_s instr;
LOG("Postpone %s", w->name);
instr_init(&instr, FH_INSTR_POSTPONED_WORD, w->index);
TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
return FH_OK;
}
/** True if the character is CR or LF */ /** True if the character is CR or LF */
static inline bool isnl(char c) static inline bool isnl(char c)
{ {
@ -397,8 +470,9 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf)
size_t length; size_t length;
switch (fh->substate) { switch (fh->substate) {
case FH_SUBSTATE_NONE: case FH_SUBSTATE_NONE:
case FH_SUBSTATE_COLONNAME: case FH_SUBSTATE_COLON_NAME:
case FH_SUBSTATE_SEENAME: case FH_SUBSTATE_SEE_NAME:
case FH_SUBSTATE_POSTPONE_NAME:
/* try to read a word */ /* try to read a word */
end = strchr(rp, ' '); end = strchr(rp, ' ');
if (end) { if (end) {
@ -407,18 +481,26 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf)
length = strlen(rp); length = strlen(rp);
} }
if (fh->substate == FH_SUBSTATE_NONE) { switch (fh->substate) {
case FH_SUBSTATE_NONE:
/* eval a word */ /* eval a word */
LOG("Handle \"%.*s\"", (int) length, rp); LOG("Handle \"%.*s\"", (int) length, rp);
TRY(fh_handle_word(fh, rp, length)); TRY(fh_handle_ascii_word(fh, rp, length));
} else if (fh->substate == FH_SUBSTATE_COLONNAME) { break;
case FH_SUBSTATE_COLON_NAME:
/* new word's name is found */ /* 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); strncpy(fh->dict[fh->dict_top].name, rp, length);
fh_setsubstate(fh, FH_SUBSTATE_NONE); fh_setsubstate(fh, FH_SUBSTATE_NONE);
} else if (fh->substate == FH_SUBSTATE_SEENAME) { break;
case FH_SUBSTATE_SEE_NAME:
TRY(fh_see_word(fh, rp, length)); TRY(fh_see_word(fh, rp, length));
fh_setsubstate(fh, FH_SUBSTATE_NONE); fh_setsubstate(fh, FH_SUBSTATE_NONE);
break;
case FH_SUBSTATE_POSTPONE_NAME:
TRY(fh_postpone_word(fh, rp, length));
fh_setsubstate(fh, FH_SUBSTATE_NONE);
break;
} }
if (end) { if (end) {
@ -428,8 +510,8 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf)
} }
break; break;
case FH_SUBSTATE_SQUOTE: case FH_SUBSTATE_S_QUOTE:
case FH_SUBSTATE_DOTQUOTE: case FH_SUBSTATE_DOT_QUOTE:
end = strchr(rp, '"'); end = strchr(rp, '"');
if (end) { if (end) {
length = end - rp; length = end - rp;
@ -444,7 +526,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf)
} }
break; break;
case FH_SUBSTATE_PARENCOMMENT: case FH_SUBSTATE_PAREN_COMMENT:
end = strchr(rp, ')'); end = strchr(rp, ')');
if (end) { if (end) {
LOG("Discard inline comment"); LOG("Discard inline comment");
@ -457,7 +539,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf)
} }
break; break;
case FH_SUBSTATE_LINECOMMENT: case FH_SUBSTATE_LINE_COMMENT:
LOG("Discard line comment"); LOG("Discard line comment");
goto done; // just discard the rest goto done; // just discard the rest

Loading…
Cancel
Save