Compare commits
4 Commits
de2a747e36
...
0140f768cf
| Author | SHA1 | Date | |
|---|---|---|---|
| 0140f768cf | |||
| 6f71b85522 | |||
| 21c7092752 | |||
| 3ace32a95b |
+1
-1
@@ -15,7 +15,7 @@ if (NOT DEFINED bshell_enable_floating_point)
|
||||
set(bshell_enable_floating_point 1)
|
||||
endif ()
|
||||
|
||||
set(required_fx_assemblies fx.runtime fx.collections fx.io fx.diagnostics)
|
||||
set(required_fx_assemblies fx.runtime fx.collections fx.io fx.diagnostics fx.cmdline)
|
||||
|
||||
if (bshell_interactive)
|
||||
set(required_fx_assemblies ${required_fx_assemblies} fx.term)
|
||||
|
||||
@@ -91,7 +91,6 @@ static enum bshell_status begin_processing(
|
||||
{
|
||||
struct bshell_native_command_p *cmd_p
|
||||
= fx_object_get_private(cmd, BSHELL_TYPE_NATIVE_COMMAND);
|
||||
printf("begin processing '%s'\n", fx_string_get_cstr(cmd_p->cmd_path));
|
||||
int flags = 0;
|
||||
switch (position) {
|
||||
case BSHELL_COMMAND_POSITION_BEGINNING:
|
||||
@@ -117,7 +116,6 @@ static enum bshell_status process_record(
|
||||
{
|
||||
struct bshell_native_command_p *cmd_p
|
||||
= fx_object_get_private(cmd, BSHELL_TYPE_NATIVE_COMMAND);
|
||||
printf("process record '%s'\n", fx_string_get_cstr(cmd_p->cmd_path));
|
||||
|
||||
if (cmd_p->cmd_flags & F_REDIRECT_STDIN) {
|
||||
fx_value in = bshell_pipeline_read_value(pipeline);
|
||||
@@ -161,7 +159,6 @@ static enum bshell_status end_processing(bshell_command *cmd)
|
||||
{
|
||||
struct bshell_native_command_p *cmd_p
|
||||
= fx_object_get_private(cmd, BSHELL_TYPE_NATIVE_COMMAND);
|
||||
printf("end processing '%s'\n", fx_string_get_cstr(cmd_p->cmd_path));
|
||||
if (cmd_p->cmd_writer_init) {
|
||||
bshell_value_writer_cleanup(&cmd_p->cmd_writer);
|
||||
cmd_p->cmd_writer_init = false;
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
#include "scope.h"
|
||||
|
||||
#include <bshell/runtime/runtime.h>
|
||||
#include <bshell/verb.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static fx_once global_once = FX_ONCE_INIT;
|
||||
|
||||
static void cleanup_globals(void)
|
||||
{
|
||||
bshell_cleanup_all_verbs();
|
||||
}
|
||||
|
||||
static void init_globals(void)
|
||||
{
|
||||
bshell_init_all_verbs();
|
||||
bshell_table_init();
|
||||
}
|
||||
|
||||
struct bshell_runtime *bshell_runtime_create(void)
|
||||
{
|
||||
struct bshell_runtime *out = malloc(sizeof *out);
|
||||
@@ -16,6 +30,11 @@ struct bshell_runtime *bshell_runtime_create(void)
|
||||
out->rt_global = runtime_push_scope(out, RUNTIME_SCOPE_GLOBAL, NULL);
|
||||
out->rt_aliases = fx_hashtable_create();
|
||||
|
||||
if (fx_init_once(&global_once)) {
|
||||
init_globals();
|
||||
atexit(cleanup_globals);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ add_executable(bshell ${bshell_sources})
|
||||
|
||||
target_link_libraries(bshell
|
||||
bshell.core bshell.runtime
|
||||
FX::Runtime FX::Collections)
|
||||
FX::Runtime FX::Collections FX::Cmdline)
|
||||
|
||||
if (bshell_interactive)
|
||||
target_link_libraries(bshell FX::Term)
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
#include "frontend.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <bshell/ast.h>
|
||||
#include <bshell/compile.h>
|
||||
#include <bshell/file.h>
|
||||
#include <bshell/runtime/runtime.h>
|
||||
#include <fx/io/path.h>
|
||||
#include <fx/reflection/assembly.h>
|
||||
|
||||
#if BSHELL_INTERACTIVE == 1
|
||||
#include "line-ed/line-ed.h"
|
||||
#endif
|
||||
|
||||
#define FRONTEND_FLAG_SET(f, flag) \
|
||||
(((f)->ctx_flags & (FRONTEND_F_##flag)) == (FRONTEND_F_##flag))
|
||||
|
||||
enum eval_flags {
|
||||
EVAL_PRINT_RESULT = 0x01u,
|
||||
};
|
||||
|
||||
extern const fx_assembly *bshell_assembly_get(void);
|
||||
extern const fx_assembly *bshell_runtime_assembly_get(void);
|
||||
extern const fx_assembly *bshell_core_assembly_get(void);
|
||||
|
||||
static void lex_token_scanned(
|
||||
struct bshell_lex_ctx *ctx,
|
||||
struct bshell_lex_token *tok)
|
||||
{
|
||||
print_lex_token(tok);
|
||||
}
|
||||
|
||||
void frontend_init(struct frontend_ctx *ctx, enum frontend_flags flags)
|
||||
{
|
||||
memset(ctx, 0x0, sizeof *ctx);
|
||||
|
||||
bshell_assembly_get();
|
||||
bshell_runtime_assembly_get();
|
||||
bshell_core_assembly_get();
|
||||
|
||||
ctx->ctx_flags = flags;
|
||||
ctx->ctx_block = bshell_scriptblock_create();
|
||||
ctx->ctx_rt = bshell_runtime_create();
|
||||
}
|
||||
|
||||
static enum bshell_status lex_only(
|
||||
struct frontend_ctx *ctx,
|
||||
struct bshell_line_source *linesrc,
|
||||
enum eval_flags flags)
|
||||
{
|
||||
while (1) {
|
||||
struct bshell_lex_token *tok
|
||||
= bshell_lex_ctx_peek(&ctx->ctx_lex);
|
||||
|
||||
if (!tok) {
|
||||
break;
|
||||
}
|
||||
|
||||
bshell_lex_ctx_discard(&ctx->ctx_lex);
|
||||
}
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status parse_only(
|
||||
struct frontend_ctx *ctx,
|
||||
struct bshell_line_source *linesrc,
|
||||
enum eval_flags flags)
|
||||
{
|
||||
while (1) {
|
||||
struct bshell_ast_node *node
|
||||
= bshell_parse_ctx_read_node(&ctx->ctx_parse);
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (FRONTEND_FLAG_SET(ctx, PRINT_AST)) {
|
||||
print_ast_node_recursive(node);
|
||||
}
|
||||
|
||||
bshell_ast_node_destroy(node);
|
||||
}
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static enum bshell_status eval(
|
||||
struct frontend_ctx *ctx,
|
||||
struct bshell_line_source *linesrc,
|
||||
enum eval_flags flags)
|
||||
{
|
||||
enum bshell_status status = BSHELL_SUCCESS;
|
||||
|
||||
bshell_lex_ctx_init(&ctx->ctx_lex, 0, linesrc);
|
||||
if (FRONTEND_FLAG_SET(ctx, PRINT_LEX)) {
|
||||
ctx->ctx_lex.lex_token_scanned = lex_token_scanned;
|
||||
}
|
||||
|
||||
if (!FRONTEND_FLAG_SET(ctx, ENABLE_PARSE)) {
|
||||
status = lex_only(ctx, linesrc, flags);
|
||||
bshell_lex_ctx_cleanup(&ctx->ctx_lex);
|
||||
return status;
|
||||
}
|
||||
|
||||
bshell_parse_ctx_init(&ctx->ctx_parse, &ctx->ctx_lex);
|
||||
if (!FRONTEND_FLAG_SET(ctx, ENABLE_EVAL)) {
|
||||
status = parse_only(ctx, linesrc, flags);
|
||||
bshell_parse_ctx_cleanup(&ctx->ctx_parse);
|
||||
bshell_lex_ctx_cleanup(&ctx->ctx_lex);
|
||||
return status;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
struct bshell_ast_node *node
|
||||
= bshell_parse_ctx_read_node(&ctx->ctx_parse);
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (FRONTEND_FLAG_SET(ctx, PRINT_AST)) {
|
||||
print_ast_node_recursive(node);
|
||||
printf("----\n");
|
||||
}
|
||||
|
||||
bshell_scriptblock_clear_text(ctx->ctx_block);
|
||||
switch (node->n_type) {
|
||||
case BSHELL_AST_FUNC: {
|
||||
bshell_function *func = NULL;
|
||||
bshell_compile_function(node, &func);
|
||||
if (FRONTEND_FLAG_SET(ctx, PRINT_BYTECODE)) {
|
||||
print_function(func);
|
||||
}
|
||||
bshell_runtime_define_function(ctx->ctx_rt, func);
|
||||
bshell_function_unref(func);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
bshell_compile(node, ctx->ctx_block);
|
||||
if (FRONTEND_FLAG_SET(ctx, PRINT_BYTECODE)) {
|
||||
print_scriptblock(ctx->ctx_block, 0);
|
||||
}
|
||||
|
||||
fx_value result = bshell_runtime_eval_global(
|
||||
ctx->ctx_rt,
|
||||
ctx->ctx_block);
|
||||
|
||||
bool print_result = flags & EVAL_PRINT_RESULT
|
||||
&& result.v_type != NULL;
|
||||
if (print_result) {
|
||||
bshell_runtime_begin_output(ctx->ctx_rt);
|
||||
bshell_runtime_output_value(
|
||||
ctx->ctx_rt,
|
||||
&result);
|
||||
bshell_runtime_end_output(ctx->ctx_rt);
|
||||
}
|
||||
|
||||
fx_value_unset(&result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bshell_ast_node_destroy(node);
|
||||
}
|
||||
|
||||
bshell_parse_ctx_cleanup(&ctx->ctx_parse);
|
||||
bshell_lex_ctx_cleanup(&ctx->ctx_lex);
|
||||
|
||||
return BSHELL_SUCCESS;
|
||||
}
|
||||
|
||||
static fx_path *create_path(const char *dir_path, const char *script_path)
|
||||
{
|
||||
if (!script_path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fx_path *paths[2] = {0};
|
||||
|
||||
if (dir_path) {
|
||||
paths[0] = fx_path_create_from_cstr(dir_path);
|
||||
}
|
||||
|
||||
if (script_path) {
|
||||
paths[1] = fx_path_create_from_cstr(script_path);
|
||||
}
|
||||
|
||||
if (!dir_path) {
|
||||
return paths[1];
|
||||
}
|
||||
|
||||
fx_path *result = fx_path_join(
|
||||
(const fx_path **)paths,
|
||||
sizeof paths / sizeof paths[0]);
|
||||
fx_path_unref(paths[0]);
|
||||
fx_path_unref(paths[1]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
enum bshell_status frontend_eval_file(
|
||||
struct frontend_ctx *ctx,
|
||||
const char *dir_path,
|
||||
const char *script_path)
|
||||
{
|
||||
fx_path *path = create_path(dir_path, script_path);
|
||||
if (!path) {
|
||||
return BSHELL_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
struct bshell_file *file = NULL;
|
||||
ctx->ctx_status = bshell_file_open(fx_path_ptr(path), &file);
|
||||
fx_path_unref(path);
|
||||
|
||||
if (!FX_OK(ctx->ctx_status)) {
|
||||
return ctx->ctx_status;
|
||||
}
|
||||
|
||||
struct bshell_line_source *linesrc = &file->f_base;
|
||||
|
||||
ctx->ctx_status = eval(ctx, linesrc, 0);
|
||||
|
||||
bshell_file_close(file);
|
||||
|
||||
return ctx->ctx_status;
|
||||
}
|
||||
|
||||
enum bshell_status frontend_repl(struct frontend_ctx *ctx)
|
||||
{
|
||||
#if BSHELL_INTERACTIVE
|
||||
struct line_ed *ed = line_ed_create();
|
||||
|
||||
struct bshell_line_source *linesrc = line_ed_to_line_source(ed);
|
||||
|
||||
ctx->ctx_status = eval(ctx, linesrc, EVAL_PRINT_RESULT);
|
||||
|
||||
line_ed_destroy(ed);
|
||||
|
||||
return ctx->ctx_status;
|
||||
#else
|
||||
return BSHELL_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
void frontend_cleanup(struct frontend_ctx *ctx)
|
||||
{
|
||||
bshell_runtime_destroy(ctx->ctx_rt);
|
||||
bshell_scriptblock_unref(ctx->ctx_block);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef FRONTEND_H_
|
||||
#define FRONTEND_H_
|
||||
|
||||
#include <bshell/parse/lex.h>
|
||||
#include <bshell/parse/parse.h>
|
||||
#include <bshell/runtime/script-block.h>
|
||||
#include <bshell/status.h>
|
||||
|
||||
struct line_ed;
|
||||
struct bshell_file;
|
||||
struct bshell_runtime;
|
||||
|
||||
#define FRONTEND_DEFAULT_FLAGS (FRONTEND_F_ENABLE_EVAL)
|
||||
|
||||
enum frontend_flags {
|
||||
FRONTEND_F_ENABLE_LEX = 0x01u,
|
||||
FRONTEND_F_ENABLE_PARSE = 0x03u,
|
||||
FRONTEND_F_ENABLE_EVAL = 0x07u,
|
||||
|
||||
FRONTEND_F_PRINT_LEX = 0x10u,
|
||||
FRONTEND_F_PRINT_AST = 0x20u,
|
||||
FRONTEND_F_PRINT_BYTECODE = 0x40u,
|
||||
|
||||
FRONTEND_F_INTERACTIVE = 0x80u,
|
||||
};
|
||||
|
||||
struct frontend_ctx {
|
||||
enum bshell_status ctx_status;
|
||||
enum frontend_flags ctx_flags;
|
||||
|
||||
struct bshell_lex_ctx ctx_lex;
|
||||
struct bshell_parse_ctx ctx_parse;
|
||||
|
||||
struct bshell_runtime *ctx_rt;
|
||||
bshell_scriptblock *ctx_block;
|
||||
};
|
||||
|
||||
extern void frontend_init(struct frontend_ctx *ctx, enum frontend_flags flags);
|
||||
|
||||
extern enum bshell_status frontend_eval_file(
|
||||
struct frontend_ctx *ctx,
|
||||
const char *dir_path,
|
||||
const char *script_path);
|
||||
extern enum bshell_status frontend_repl(struct frontend_ctx *ctx);
|
||||
|
||||
extern void frontend_cleanup(struct frontend_ctx *ctx);
|
||||
|
||||
#endif
|
||||
+160
-154
@@ -1,4 +1,4 @@
|
||||
#include "debug.h"
|
||||
#include "frontend.h"
|
||||
|
||||
#include <bshell/ast.h>
|
||||
#include <bshell/compile.h>
|
||||
@@ -7,177 +7,183 @@
|
||||
#include <bshell/parse/lex.h>
|
||||
#include <bshell/parse/parse.h>
|
||||
#include <bshell/parse/token.h>
|
||||
#include <bshell/runtime/runtime.h>
|
||||
#include <bshell/verb.h>
|
||||
#include <fx/cmdline/cmd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if BSHELL_INTERACTIVE == 1
|
||||
#include "line-ed/line-ed.h"
|
||||
#endif
|
||||
enum {
|
||||
CMD_ROOT,
|
||||
OPT_LEX,
|
||||
OPT_PARSE,
|
||||
OPT_EVAL,
|
||||
OPT_PRINT_LEX,
|
||||
OPT_PRINT_AST,
|
||||
OPT_PRINT_BYTECODE,
|
||||
ARG_SCRIPT_FILE,
|
||||
};
|
||||
|
||||
extern const fx_assembly *bshell_assembly_get(void);
|
||||
extern const fx_assembly *bshell_runtime_assembly_get(void);
|
||||
extern const fx_assembly *bshell_core_assembly_get(void);
|
||||
#define FEATURE_FLAGS \
|
||||
(FRONTEND_F_ENABLE_LEX | FRONTEND_F_ENABLE_PARSE \
|
||||
| FRONTEND_F_ENABLE_EVAL)
|
||||
#define PRINT_FLAGS \
|
||||
(FRONTEND_F_PRINT_LEX | FRONTEND_F_PRINT_AST \
|
||||
| FRONTEND_F_PRINT_BYTECODE)
|
||||
|
||||
static void print_token_queue(fx_queue *q)
|
||||
const char *exec_name = NULL;
|
||||
|
||||
static enum frontend_flags collect_frontend_flags(const fx_arglist *opt)
|
||||
{
|
||||
fx_queue_entry *cur = fx_queue_first(q);
|
||||
while (cur) {
|
||||
struct bshell_lex_token *tok
|
||||
= fx_unbox(struct bshell_lex_token, cur, tok_entry);
|
||||
print_lex_token(tok);
|
||||
cur = fx_queue_next(cur);
|
||||
}
|
||||
}
|
||||
enum frontend_flags result = 0;
|
||||
#define OPTION_IS_SET(id) \
|
||||
fx_arglist_get_count(opt, id, FX_COMMAND_INVALID_ID) > 0
|
||||
|
||||
static void lex_only(struct bshell_lex_ctx *lex)
|
||||
{
|
||||
while (1) {
|
||||
struct bshell_lex_token *tok = bshell_lex_ctx_peek(lex);
|
||||
if (!tok) {
|
||||
break;
|
||||
if (OPTION_IS_SET(OPT_LEX)) {
|
||||
result |= FRONTEND_F_ENABLE_LEX;
|
||||
}
|
||||
|
||||
bshell_lex_ctx_discard(lex);
|
||||
if (OPTION_IS_SET(OPT_PARSE)) {
|
||||
result |= FRONTEND_F_ENABLE_PARSE;
|
||||
}
|
||||
|
||||
if (OPTION_IS_SET(OPT_EVAL)) {
|
||||
result |= FRONTEND_F_ENABLE_EVAL;
|
||||
}
|
||||
|
||||
if (OPTION_IS_SET(OPT_PRINT_LEX)) {
|
||||
result |= FRONTEND_F_PRINT_LEX;
|
||||
}
|
||||
|
||||
if (OPTION_IS_SET(OPT_PRINT_AST)) {
|
||||
result |= FRONTEND_F_PRINT_AST;
|
||||
}
|
||||
|
||||
if (OPTION_IS_SET(OPT_PRINT_BYTECODE)) {
|
||||
result |= FRONTEND_F_PRINT_BYTECODE;
|
||||
}
|
||||
|
||||
if ((result & PRINT_FLAGS) && !(result & FEATURE_FLAGS)) {
|
||||
result |= FRONTEND_F_ENABLE_EVAL;
|
||||
}
|
||||
|
||||
#undef OPTION_IS_SET
|
||||
return result;
|
||||
}
|
||||
|
||||
static void lex_and_parse(struct bshell_parse_ctx *parse)
|
||||
static int bshell(
|
||||
const fx_command *self,
|
||||
const fx_arglist *opt,
|
||||
const fx_array *args)
|
||||
{
|
||||
enum frontend_flags flags = collect_frontend_flags(opt);
|
||||
if (flags == 0) {
|
||||
flags = FRONTEND_DEFAULT_FLAGS;
|
||||
}
|
||||
|
||||
struct frontend_ctx ctx;
|
||||
frontend_init(&ctx, flags);
|
||||
enum bshell_status status = BSHELL_SUCCESS;
|
||||
|
||||
size_t nr_input_files = fx_arglist_get_count(
|
||||
opt,
|
||||
FX_COMMAND_INVALID_ID,
|
||||
ARG_SCRIPT_FILE);
|
||||
|
||||
if (nr_input_files == 0) {
|
||||
printf("B Shell " BSHELL_VERSION "\n");
|
||||
frontend_repl(&ctx);
|
||||
frontend_cleanup(&ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fx_arglist_iterator it;
|
||||
fx_arglist_iterator_begin(
|
||||
opt,
|
||||
FX_COMMAND_INVALID_ID,
|
||||
ARG_SCRIPT_FILE,
|
||||
&it);
|
||||
|
||||
while (fx_arglist_iterator_is_valid(&it)) {
|
||||
const char *script_path = it.value->val_str;
|
||||
status = frontend_eval_file(&ctx, NULL, script_path);
|
||||
|
||||
if (status != BSHELL_SUCCESS) {
|
||||
fprintf(stderr,
|
||||
"%s: cannot open '%s': %s\n",
|
||||
exec_name,
|
||||
script_path,
|
||||
bshell_status_get_description(status));
|
||||
}
|
||||
|
||||
fx_arglist_iterator_next(&it);
|
||||
}
|
||||
|
||||
frontend_cleanup(&ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if BSHELL_VERBOSE == 1
|
||||
static void lex_token_scanned(
|
||||
struct bshell_lex_ctx *ctx,
|
||||
struct bshell_lex_token *tok)
|
||||
FX_COMMAND(CMD_ROOT, FX_COMMAND_INVALID_ID)
|
||||
{
|
||||
print_lex_token(tok);
|
||||
}
|
||||
#endif
|
||||
FX_COMMAND_NAME("bshell");
|
||||
FX_COMMAND_DESC("B Shell script interpreter.");
|
||||
FX_COMMAND_FUNCTION(bshell);
|
||||
|
||||
extern int compare_token_types(unsigned int a, unsigned int b);
|
||||
FX_COMMAND_OPTION(OPT_LEX)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("lex");
|
||||
FX_OPTION_SHORT_NAME('l');
|
||||
FX_OPTION_DESC("Enable lexing of shell input.");
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_PARSE)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("parse");
|
||||
FX_OPTION_SHORT_NAME('a');
|
||||
FX_OPTION_DESC(
|
||||
"Enable parsing and ast generation of shell input.");
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_EVAL)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("eval");
|
||||
FX_OPTION_SHORT_NAME('b');
|
||||
FX_OPTION_DESC(
|
||||
"Enable evaluation and bytecode generation of shell "
|
||||
"input. This option is the default if no 'enable' "
|
||||
"flags are specified.");
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_PRINT_LEX)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("print-lex");
|
||||
FX_OPTION_SHORT_NAME('L');
|
||||
FX_OPTION_DESC("Print lex tokens generated from shell input.");
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_PRINT_AST)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("print-ast");
|
||||
FX_OPTION_SHORT_NAME('A');
|
||||
FX_OPTION_DESC("Print ast nodes generated from shell input.");
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_PRINT_BYTECODE)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("print-bytecode");
|
||||
FX_OPTION_SHORT_NAME('B');
|
||||
FX_OPTION_DESC("Print bytecode generated from shell input.");
|
||||
}
|
||||
|
||||
FX_COMMAND_ARG(ARG_SCRIPT_FILE)
|
||||
{
|
||||
FX_ARG_DESC("Script file to evaluate.");
|
||||
FX_ARG_NR_VALUES(FX_ARG_0_OR_MORE_VALUES);
|
||||
}
|
||||
|
||||
FX_COMMAND_HELP_OPTION();
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
bshell_assembly_get();
|
||||
bshell_runtime_assembly_get();
|
||||
bshell_core_assembly_get();
|
||||
|
||||
bshell_init_all_verbs();
|
||||
bshell_table_init();
|
||||
|
||||
struct bshell_file *file = NULL;
|
||||
struct line_ed *ed = NULL;
|
||||
struct bshell_line_source *linesrc = NULL;
|
||||
|
||||
enum bshell_status status = BSHELL_SUCCESS;
|
||||
bool interactive = true;
|
||||
|
||||
if (argc > 1) {
|
||||
status = bshell_file_open(argv[1], &file);
|
||||
linesrc = &file->f_base;
|
||||
interactive = false;
|
||||
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr,
|
||||
"%s: cannot open '%s': %s\n",
|
||||
argv[0],
|
||||
argv[1],
|
||||
bshell_status_get_description(status));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
#if BSHELL_INTERACTIVE == 1
|
||||
ed = line_ed_create();
|
||||
linesrc = line_ed_to_line_source(ed);
|
||||
#else
|
||||
fprintf(stderr, "Interactive mode is not supported.\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct bshell_lex_ctx lex = {0};
|
||||
bshell_lex_ctx_init(&lex, 0, linesrc);
|
||||
#if BSHELL_VERBOSE == 1
|
||||
lex.lex_token_scanned = lex_token_scanned;
|
||||
#endif
|
||||
struct bshell_parse_ctx parse = {0};
|
||||
bshell_parse_ctx_init(&parse, &lex);
|
||||
|
||||
#if 0
|
||||
lex_only(&lex);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (interactive) {
|
||||
printf("B Shell " BSHELL_VERSION "\n");
|
||||
}
|
||||
|
||||
bshell_scriptblock *block = bshell_scriptblock_create();
|
||||
struct bshell_runtime *rt = bshell_runtime_create();
|
||||
|
||||
while (1) {
|
||||
struct bshell_ast_node *node
|
||||
= bshell_parse_ctx_read_node(&parse);
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
|
||||
#if BSHELL_VERBOSE == 1
|
||||
print_ast_node_recursive(node);
|
||||
printf("----\n");
|
||||
#endif
|
||||
|
||||
bshell_scriptblock_clear_text(block);
|
||||
switch (node->n_type) {
|
||||
case BSHELL_AST_FUNC: {
|
||||
bshell_function *func = NULL;
|
||||
bshell_compile_function(node, &func);
|
||||
#if BSHELL_VERBOSE == 1
|
||||
print_function(func);
|
||||
#endif
|
||||
bshell_runtime_define_function(rt, func);
|
||||
bshell_function_unref(func);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
bshell_compile(node, block);
|
||||
#if BSHELL_VERBOSE == 1
|
||||
print_scriptblock(block, 0);
|
||||
#endif
|
||||
|
||||
fx_value result = bshell_runtime_eval_global(rt, block);
|
||||
|
||||
if (interactive && result.v_type != NULL) {
|
||||
format_value_default(&result, fx_stdout);
|
||||
}
|
||||
|
||||
fx_value_unset(&result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bshell_ast_node_destroy(node);
|
||||
}
|
||||
|
||||
bshell_runtime_destroy(rt);
|
||||
bshell_scriptblock_unref(block);
|
||||
|
||||
bshell_parse_ctx_cleanup(&parse);
|
||||
bshell_lex_ctx_cleanup(&lex);
|
||||
|
||||
#if BSHELL_INTERACTIVE == 1
|
||||
if (ed) {
|
||||
line_ed_destroy(ed);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (file) {
|
||||
bshell_file_close(file);
|
||||
}
|
||||
|
||||
bshell_cleanup_all_verbs();
|
||||
|
||||
return 0;
|
||||
exec_name = argv[0];
|
||||
return fx_command_dispatch(CMD_ROOT, argc, argv);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user