implement C"
This commit is contained in:
@@ -35,6 +35,11 @@ enum fh_instruction_kind {
|
||||
/** This is the `s"` instruction, the length (u32) and string data immediately follow */
|
||||
FH_INSTR_ALLOCSTR,
|
||||
|
||||
/** This is the `c"` instruction, the length (u32) and string data immediately follow.
|
||||
* The string data already contains the length prefix.
|
||||
*/
|
||||
FH_INSTR_ALLOCSTR_C,
|
||||
|
||||
/** This is the `."` instruction, same format as above. */
|
||||
FH_INSTR_TYPESTR,
|
||||
|
||||
|
||||
@@ -209,6 +209,39 @@ static enum fh_error w_s_quote(struct fh_thread_s *fh, const struct fh_word_s *w
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_c_quote(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
size_t len;
|
||||
uint32_t addr = fh->here + (fh->state == FH_STATE_INTERPRET ? 0 : INSTR_SIZE);
|
||||
|
||||
/* read the string straight into HEAP */
|
||||
|
||||
fh_input_consume_spaces(fh);
|
||||
char *start = ((char *) &fh->heap[addr]) + 1; // space for the counter
|
||||
uint32_t maxlen = HEAP_END - addr;
|
||||
if (maxlen > 255) {
|
||||
maxlen = 255;
|
||||
}
|
||||
TRY(fh_input_read_quotedstring(fh, w->param == 1, start, maxlen, &len));
|
||||
fh->here = WORDALIGNED(addr + len + 1);
|
||||
fh->heap[addr] = (uint8_t) len; // char count
|
||||
|
||||
struct fh_instruction_s instr;
|
||||
if (fh->state == FH_STATE_INTERPRET) {
|
||||
LOG("Interpret a c-string alloc: \"%.*s\"", len, start);
|
||||
TRY(ds_push(fh, addr));
|
||||
} else {
|
||||
LOG("Compile a c-string: \"%.*s\"", len, start);
|
||||
instr.kind = FH_INSTR_ALLOCSTR_C;
|
||||
instr.data = WORDALIGNED(len + 1);
|
||||
fh_heap_write(fh, addr - INSTR_SIZE, &instr, INSTR_SIZE);
|
||||
}
|
||||
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static bool chartest_equals_or_end(char c, void *param)
|
||||
{
|
||||
char cc = *(char*)param;
|
||||
@@ -443,6 +476,7 @@ static enum fh_error w_to_number(struct fh_thread_s *fh, const struct fh_word_s
|
||||
|
||||
const struct name_and_handler fh_builtins_text[] = {
|
||||
{"s\"", w_s_quote, 1, 0},
|
||||
{"c\"", w_c_quote, 1, 0},
|
||||
{"s\\\"", w_s_quote, 1, 1}, // escaped
|
||||
{".\"", w_dot_quote, 1, '"'},
|
||||
{".(", w_dot_quote, 1, ')'},
|
||||
|
||||
+15
-9
@@ -344,18 +344,24 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
|
||||
TRY(ds_pop(fh, &val)); // discard the tested value
|
||||
goto instr;
|
||||
|
||||
/* special case for strings stored in compile memory */
|
||||
case FH_INSTR_ALLOCSTR:
|
||||
strl = instr->data;
|
||||
LOG("\x1b[35mExec: alloc-str\x1b[m \"%.*s\"", strl, fh_str_at(fh, fh->execptr));
|
||||
TRY(ds_push(fh, fh->execptr)); // give pointer directly into the definition
|
||||
TRY(ds_push(fh, strl));
|
||||
fh->execptr += strl;
|
||||
goto instr;
|
||||
|
||||
case FH_INSTR_ALLOCSTR_C:
|
||||
LOG("\x1b[35mExec: alloc-str-c\x1b[m \"%.*s\"", fh->heap[fh->execptr], fh_str_at(fh, fh->execptr+1));
|
||||
TRY(ds_push(fh, fh->execptr));
|
||||
fh->execptr += instr->data;
|
||||
goto instr;
|
||||
|
||||
case FH_INSTR_TYPESTR:
|
||||
strl = instr->data;
|
||||
if (instr->kind == FH_INSTR_ALLOCSTR) {
|
||||
LOG("\x1b[35mExec: alloc-str\x1b[m \"%.*s\"", strl, fh_str_at(fh, fh->execptr));
|
||||
TRY(ds_push(fh, fh->execptr)); // give pointer directly into the definition
|
||||
TRY(ds_push(fh, strl));
|
||||
} else {
|
||||
LOG("\x1b[35mExec: type-str\x1b[m \"%.*s\"", strl, fh_str_at(fh, fh->execptr));
|
||||
FHPRINT("%.*s", (int) strl, fh_str_at(fh, fh->execptr));
|
||||
}
|
||||
LOG("\x1b[35mExec: type-str\x1b[m \"%.*s\"", strl, fh_str_at(fh, fh->execptr));
|
||||
FHPRINT("%.*s", (int) strl, fh_str_at(fh, fh->execptr));
|
||||
fh->execptr += strl;
|
||||
goto instr;
|
||||
|
||||
|
||||
+13
-7
@@ -100,15 +100,21 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
|
||||
/* special case for strings stored in compile memory */
|
||||
case FH_INSTR_ALLOCSTR:
|
||||
strl = instr->data;
|
||||
FHPRINT("AllocStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr));
|
||||
execptr += strl;
|
||||
break;
|
||||
|
||||
case FH_INSTR_TYPESTR:
|
||||
strl = instr->data;
|
||||
if (instr->kind == FH_INSTR_ALLOCSTR) {
|
||||
FHPRINT("AllocStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr));
|
||||
execptr += strl;
|
||||
} else {
|
||||
FHPRINT("PrintStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr));
|
||||
execptr += strl;
|
||||
}
|
||||
FHPRINT("PrintStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr));
|
||||
execptr += strl;
|
||||
break;
|
||||
|
||||
case FH_INSTR_ALLOCSTR_C:
|
||||
strl = instr->data;
|
||||
FHPRINT("AllocStrC(%d, \"%.*s\")\n", fh->heap[execptr], fh->heap[execptr], fh_str_at(fh, execptr + 1));
|
||||
execptr += strl;
|
||||
break;
|
||||
|
||||
case FH_INSTR_ENDWORD:
|
||||
|
||||
Reference in New Issue
Block a user