|
|
@ -18,6 +18,11 @@ struct fh_thread_s; |
|
|
|
struct fh_word_s; |
|
|
|
struct fh_word_s; |
|
|
|
struct fh_instruction_s; |
|
|
|
struct fh_instruction_s; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct fh_global_s { |
|
|
|
|
|
|
|
bool verbose; |
|
|
|
|
|
|
|
bool interactive; |
|
|
|
|
|
|
|
} fh_globals = {}; |
|
|
|
|
|
|
|
|
|
|
|
/* if the return address is this, we should drop back to interactive mode */ |
|
|
|
/* if the return address is this, we should drop back to interactive mode */ |
|
|
|
#define MAGICADDR_INTERACTIVE 0xFFFFFFFFULL |
|
|
|
#define MAGICADDR_INTERACTIVE 0xFFFFFFFFULL |
|
|
|
|
|
|
|
|
|
|
@ -27,11 +32,12 @@ struct fh_instruction_s; |
|
|
|
} while (0) |
|
|
|
} while (0) |
|
|
|
|
|
|
|
|
|
|
|
/* logging, TODO make levels configurable */ |
|
|
|
/* logging, TODO make levels configurable */ |
|
|
|
#define LOG(format, ...) fprintf(stderr, format "\r\n", ##__VA_ARGS__) |
|
|
|
#define LOG(format, ...) do { if(fh_globals.verbose) { fprintf(stderr, format "\r\n", ##__VA_ARGS__); } } while (0) |
|
|
|
#define LOGI(format, ...) fprintf(stderr, "\x1b[32m" format "\x1b[m\r\n", ##__VA_ARGS__) |
|
|
|
#define LOGI(format, ...) fprintf(stderr, "\x1b[32m" format "\x1b[m\r\n", ##__VA_ARGS__) |
|
|
|
#define LOGE(format, ...) fprintf(stderr, "\x1b[31;1m" format "\x1b[m\r\n", ##__VA_ARGS__) |
|
|
|
#define LOGE(format, ...) fprintf(stderr, "\x1b[31;1m" format "\x1b[m\r\n", ##__VA_ARGS__) |
|
|
|
/* Forth standard output. XXX should be stdout, but then colors get mangled */ |
|
|
|
/* Forth standard output. XXX should be stdout, but then colors get mangled */ |
|
|
|
#define FHPRINT(format, ...) fprintf(stderr, "\x1b[33;1m" format "\x1b[m", ##__VA_ARGS__) |
|
|
|
#define FHPRINT(format, ...) fprintf(stderr, "\x1b[33;1m" format "\x1b[m", ##__VA_ARGS__) |
|
|
|
|
|
|
|
#define FHPRINT_SVC(format, ...) fprintf(stderr, "" format "", ##__VA_ARGS__) |
|
|
|
|
|
|
|
|
|
|
|
enum fh_error { |
|
|
|
enum fh_error { |
|
|
|
FH_OK = 0, |
|
|
|
FH_OK = 0, |
|
|
@ -627,7 +633,7 @@ enum fh_error fh_handle_quoted_string( |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
|
LOGE("Bad substate in interpret mode: %d", fh->substate); |
|
|
|
LOGE("Bad substate in interpret mode: %s", substatenames[fh->substate]); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
/* compile */ |
|
|
|
/* compile */ |
|
|
@ -772,7 +778,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, char *linebuf) |
|
|
|
case FH_SUBSTATE_DOTQUOTE: |
|
|
|
case FH_SUBSTATE_DOTQUOTE: |
|
|
|
end = strchr(rp, '"'); |
|
|
|
end = strchr(rp, '"'); |
|
|
|
if (end) { |
|
|
|
if (end) { |
|
|
|
length = end - rp - 1; |
|
|
|
length = end - rp; |
|
|
|
LOG("Quoted string: \"%.*s\"", (int) length, rp); |
|
|
|
LOG("Quoted string: \"%.*s\"", (int) length, rp); |
|
|
|
TRY(fh_handle_quoted_string(fh, rp, length)); |
|
|
|
TRY(fh_handle_quoted_string(fh, rp, length)); |
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_NONE); |
|
|
|
fh_setsubstate(fh, FH_SUBSTATE_NONE); |
|
|
@ -818,16 +824,30 @@ int main(int argc, char *argv[]) |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool interactive = true; |
|
|
|
fh_globals.verbose = false; |
|
|
|
|
|
|
|
fh_globals.interactive = false; |
|
|
|
|
|
|
|
|
|
|
|
FILE *infile = stdin; |
|
|
|
FILE *infile = stdin; |
|
|
|
|
|
|
|
|
|
|
|
// TODO use getopt?
|
|
|
|
// TODO use getopt
|
|
|
|
for (int a = 1; a < argc; a++) { |
|
|
|
for (int a = 1; a < argc; a++) { |
|
|
|
if (argv[a][0] == '-') { |
|
|
|
if (argv[a][0] == '-' && argv[a][1] != '-') { |
|
|
|
// opt
|
|
|
|
// opt
|
|
|
|
|
|
|
|
char *cc = argv[a] + 1; |
|
|
|
|
|
|
|
char c; |
|
|
|
|
|
|
|
while(0 != (c = *cc++)) { |
|
|
|
|
|
|
|
switch (c) { |
|
|
|
|
|
|
|
case 'v': |
|
|
|
|
|
|
|
fh_globals.verbose = 1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
LOGE("Unknown flag: %c", c); |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
infile = fopen(argv[a], "r"); |
|
|
|
infile = fopen(argv[a], "r"); |
|
|
|
interactive = false; |
|
|
|
fh_globals.interactive = false; |
|
|
|
if (!infile) { |
|
|
|
if (!infile) { |
|
|
|
LOGE("Error opening infile: %s", argv[a]); |
|
|
|
LOGE("Error opening infile: %s", argv[a]); |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
@ -853,13 +873,13 @@ int main(int argc, char *argv[]) |
|
|
|
|
|
|
|
|
|
|
|
rv = fh_process_line(&fh, linebuf); |
|
|
|
rv = fh_process_line(&fh, linebuf); |
|
|
|
if (rv == FH_OK) { |
|
|
|
if (rv == FH_OK) { |
|
|
|
FHPRINT("ok\r\n"); |
|
|
|
FHPRINT_SVC(" ok\r\n"); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
LOGE("ERROR %s on line %d", fherr_name(rv), linecnt); |
|
|
|
LOGE("ERROR %s on line %d", fherr_name(rv), linecnt); |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
FHPRINT("Bye.\r\n"); |
|
|
|
FHPRINT_SVC("Bye.\r\n"); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|