Compare commits

..

58 Commits

Author SHA1 Message Date
wash f189643cf4 build: add support for disabling native command support 2026-07-19 13:34:09 +01:00
wash 422416e99b frontend: replace builtin line-ed with bshell-line-editor 2026-06-20 15:18:51 +01:00
wash 9e6c3bb431 core: foreach-object: update variable definition api usage 2026-06-20 15:17:15 +01:00
wash ad8b284869 runtime: implement an extensible line editor
the line editor supports custom keybinds and data storage, allowing for
a wide range of functionality to be implemented via plugins.

included plugins include:
* core: basic input and cursor movement.
* history: input history storage and retrieval (unfinished)
* highlight: support for colour-highlighting the line buffer (unfinished)
* syntax: parses the line buffer and uses `highlight` to apply syntax highlighting (unfinished).
* shell-integration:
  - allows a `prompt` function to be defined, which will be called to get the text to
    be used for the prompt
  - exposes key properties of the line editor to the shell environment, allowing line editor
    functionality to be extended via shell scripts.
2026-06-20 15:13:34 +01:00
wash f622c2eba3 runtime: adjust formatting 2026-06-20 15:13:17 +01:00
wash f62713872f runtime: cmdcall: resolve() can now re-resolve an already-resolved cmdcall 2026-06-20 15:13:03 +01:00
wash 8b18421f63 runtime: parse: fix parsing of linefeed after last statement in block 2026-06-20 15:11:02 +01:00
wash 4a567a1bb9 runtime: format: add truncation and single-line support to value_writer 2026-06-20 15:10:15 +01:00
wash c262b53eab runtime: move variable definition from runtime to individual scopes 2026-06-20 15:09:10 +01:00
wash c2d3e05430 runtime: command: handle commants that don't have a source assembly 2026-06-20 15:07:20 +01:00
wash 4e6493da58 runtime: lex: fix incorrect state-transition when scanning func keyword 2026-06-20 15:06:04 +01:00
wash 907e0c1832 frontend: evaluate <config>/profile.bshell on startup 2026-06-15 17:41:41 +01:00
wash b8a5bd7338 frontend: update fx api usage 2026-06-15 17:41:26 +01:00
wash c68b1d2b26 runtime: update fx api usage 2026-06-15 17:41:08 +01:00
wash 0140f768cf frontend: re-organise frontend functionality; add feature and logging switches 2026-06-14 20:28:50 +01:00
wash 6f71b85522 cmake: find fx.cmdline assembly 2026-06-14 20:28:27 +01:00
wash 21c7092752 runtime: initialise global data when the first bshell_runtime is created 2026-06-14 20:28:07 +01:00
wash 3ace32a95b runtime: native-command: remove logging from record processing 2026-06-14 20:27:46 +01:00
wash de2a747e36 runtime: format: only add trailing newline to string if one isn't already present 2026-06-14 19:40:27 +01:00
wash b3440fe231 runtime: cmdcall: implement resolution of native commands 2026-06-14 19:39:49 +01:00
wash e8ddb0b75f cmake: find fx.io and fx.diagnostics 2026-06-13 13:50:14 +01:00
wash 97a83addc8 core: write-output now writes args and input values to the pipeline rather than stdout
the runtime will handle writing any output values to the terminal if necessary. instead,
write-output can now be used to write arbitrary values into the pipeline for later commands
to use.
2026-06-13 13:49:00 +01:00
wash 8c926acd9d core: update begin_processing() cmdlet signature 2026-06-13 13:48:19 +01:00
wash fba7987d78 runtime: implement a bshell_command sub-class for calling native commands 2026-06-13 13:47:34 +01:00
wash 2332d48b0c runtime: adjust formatting 2026-06-13 13:47:16 +01:00
wash 73519eb7aa runtime: move value formatting functionality to a dedicated api 2026-06-13 13:47:06 +01:00
wash 4c04ca6de8 runtime: command: add an arg to begin_processing() to indicate pipeline position 2026-06-13 13:45:41 +01:00
wash de5058e045 cmake: link to fx.diagnostics and fx.io 2026-06-13 13:36:20 +01:00
wash 8843f2d2a9 frontend: print an error message when the specified script file cannot be opened 2026-05-31 17:34:28 +01:00
wash 187296ca62 runtime: status: add descriptive messages for status codes 2026-05-31 17:34:12 +01:00
wash b9a3caf033 runtime: lex: formatting cleanup 2026-05-31 17:33:43 +01:00
wash 8e2eec973a core: add a compiler option for disabling floating-point usage 2026-05-31 17:33:20 +01:00
wash 6548c3283b cmake: build-id: specify current working directory 2026-05-31 17:33:02 +01:00
wash 4a087d1000 cmake: update FindFX module 2026-05-31 17:32:44 +01:00
wash da2777717c frontend: add a compiler option for disabling floating-point usage 2026-05-31 17:32:26 +01:00
wash 290caf7aef frontend: disable all fx.term includes when interactive mode is disabled 2026-05-31 17:32:06 +01:00
wash 73ff8ba6aa bshell.runtime: disable all fx.term includes when interactive mode is disabled 2026-05-31 17:31:37 +01:00
wash ee6fdfbc48 bshell.runtime: add a compiler option for disabling floating-point usage 2026-05-31 17:30:53 +01:00
wash 1a311b3796 doc: sample: make the simple sample script actually simple 2026-05-30 21:10:04 +01:00
wash 338c0356ca multi: completely remove fx.term dependency when interactive support is disabled 2026-05-30 21:09:43 +01:00
wash ca33228e0e runtime: scriptblock: fix use of uninitialised memory 2026-05-30 20:18:41 +01:00
wash 09f64aaaba runtime: scope: fix scope_set_block not handling NULL argument properly 2026-05-30 20:18:24 +01:00
wash 74695e8593 cmake: remove debug messages 2026-05-30 20:17:52 +01:00
wash afab5343c4 doc: sample: add simple function example script 2026-05-30 19:54:06 +01:00
wash 0697d889c5 frontend: implement function compilation 2026-05-30 19:53:49 +01:00
wash 28abb4d2d3 frontend: implement debug printing for functions 2026-05-30 19:53:39 +01:00
wash 531191ab52 core: update pipeline api usage 2026-05-30 19:53:15 +01:00
wash 1710f705e9 command: implement callable bytecode functions 2026-05-30 19:52:50 +01:00
wash 96bf76aabc runtime: fix memory leaks 2026-05-30 19:52:36 +01:00
wash 26b368a512 compile: fix memory leaks 2026-05-30 19:52:24 +01:00
wash a30e76e525 scriptblock: fix memory leaks 2026-05-30 19:51:52 +01:00
wash 3b39f794f9 verb: fix memory leaks 2026-05-30 19:51:29 +01:00
wash 5d6f2a5ce8 parse: lex: fix memory leaks 2026-05-30 19:50:38 +01:00
wash fec3be2140 ast: implement cleanup callbacks 2026-05-30 19:50:13 +01:00
wash f2e1d89313 runtime: update iterator usage 2026-05-25 19:14:52 +01:00
wash 6bfe3f0a6e core: update iterator usage 2026-05-25 19:14:45 +01:00
wash edfb3e24a3 bshell: re-organise build into three separate components
bshell: the front-end binary
bshell.runtime: contains the parser, compiler, and classes needed to run bshell scripts
bshell.core: contains the builtin commandlets and aliases
2026-05-25 10:33:29 +01:00
wash 58c76a1f57 meta: update clang-format config 2026-05-25 10:33:10 +01:00
221 changed files with 9606 additions and 7111 deletions
+2 -2
View File
@@ -45,9 +45,9 @@ SpacesBeforeTrailingComments: 3
TabWidth: 8 TabWidth: 8
UseTab: AlignWithSpaces UseTab: AlignWithSpaces
BreakAfterReturnType: Automatic BreakAfterReturnType: Automatic
PenaltyBreakAssignment: 1000000 PenaltyBreakAssignment: 0
PenaltyReturnTypeOnItsOwnLine: 100000000 PenaltyReturnTypeOnItsOwnLine: 100000000
PenaltyExcessCharacter: 10000000 PenaltyExcessCharacter: 10000
PenaltyBreakOpenParenthesis: 0 PenaltyBreakOpenParenthesis: 0
PenaltyBreakBeforeFirstCallParameter: 0 PenaltyBreakBeforeFirstCallParameter: 0
PenaltyIndentedWhitespace: 0 PenaltyIndentedWhitespace: 0
+27 -33
View File
@@ -7,44 +7,38 @@ if (NOT DEFINED bshell_interactive)
set(bshell_interactive 1) set(bshell_interactive 1)
endif () endif ()
if (NOT DEFINED bshell_enable_native_commands)
set(bshell_enable_native_commands 1)
endif ()
if (NOT DEFINED bshell_verbose)
set(bshell_verbose 0)
endif ()
if (NOT DEFINED bshell_enable_floating_point)
set(bshell_enable_floating_point 1)
endif ()
set(required_fx_assemblies fx.runtime fx.collections fx.cmdline fx.io)
if (bshell_interactive)
set(required_fx_assemblies ${required_fx_assemblies} fx.term)
endif ()
if (bshell_enable_native_commands)
set(required_fx_assemblies ${required_fx_assemblies} fx.diagnostics)
endif ()
find_package(Python COMPONENTS Interpreter REQUIRED) find_package(Python COMPONENTS Interpreter REQUIRED)
find_package(FX REQUIRED COMPONENTS find_package(FX REQUIRED COMPONENTS ${required_fx_assemblies})
fx.runtime
fx.collections
fx.term)
execute_process( execute_process(
COMMAND ${Python_EXECUTABLE} COMMAND ${Python_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/tools/build-id.py ${CMAKE_CURRENT_SOURCE_DIR}/tools/build-id.py
--source-dir "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE bshell_version) OUTPUT_VARIABLE bshell_version)
set(source_dirs
ast compile parse parse/lex parse/syntax
runtime format command cmdlets aliases)
if (bshell_interactive EQUAL 1)
message(STATUS "Interactive support: Enabled")
set(source_dirs ${source_dirs} line-ed)
else ()
message(STATUS "Interactive support: Disabled")
endif ()
file(GLOB bshell_sources
bshell/*.c
bshell/*.h)
foreach (d ${source_dirs})
file(GLOB sources
bshell/${d}/*.c
bshell/${d}/*.h)
set(bshell_sources ${bshell_sources} ${sources})
endforeach (d)
message(STATUS "B Shell version: ${bshell_version}") message(STATUS "B Shell version: ${bshell_version}")
add_executable(bshell ${bshell_sources}) add_subdirectory(bshell)
add_subdirectory(bshell.runtime)
target_link_libraries(bshell FX::Runtime FX::Collections FX::Term) add_subdirectory(bshell.core)
target_compile_definitions(bshell PUBLIC
BSHELL_VERSION="${bshell_version}"
BSHELL_INTERACTIVE=${bshell_interactive})
+22
View File
@@ -0,0 +1,22 @@
set(source_dirs aliases cmdlets)
file(GLOB sources
*.c
*.h)
foreach (d ${source_dirs})
file(GLOB d_sources
${d}/*.c
${d}/*.h)
set(sources ${sources} ${d_sources})
endforeach (d)
add_library(bshell.core SHARED ${sources})
target_link_libraries(bshell.core bshell.runtime FX::Runtime FX::Collections)
target_include_directories(bshell.core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_definitions(bshell.core PUBLIC
BSHELL_ENABLE_FLOATING_POINT=${bshell_enable_floating_point}
BSHELL_VERSION="${bshell_version}")
install(TARGETS bshell.core)
@@ -1,6 +1,5 @@
#include "../command/alias.h" #include <bshell/command/alias.h>
#include "../command/command.h" #include <bshell/command/command.h>
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/string.h> #include <fx/string.h>
#include <fx/vector.h> #include <fx/vector.h>
@@ -1,6 +1,5 @@
#include "../command/alias.h" #include <bshell/command/alias.h>
#include "../command/command.h" #include <bshell/command/command.h>
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/string.h> #include <fx/string.h>
#include <fx/vector.h> #include <fx/vector.h>
+22
View File
@@ -0,0 +1,22 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN(bshell_core)
FX_ASSEMBLY_NAME("bshell.core");
FX_ASSEMBLY_VERSION(0, 1, 0, 0);
FX_ASSEMBLY_EXPORT_TYPE("bshell.core", "get_verb", bshell_get_verb);
FX_ASSEMBLY_EXPORT_TYPE(
"bshell.core",
"write_output",
bshell_write_output);
FX_ASSEMBLY_EXPORT_TYPE(
"bshell.core",
"foreach_object",
bshell_foreach_object);
FX_ASSEMBLY_EXPORT_TYPE(
"bshell.core",
"get_command",
bshell_get_command);
FX_ASSEMBLY_EXPORT_TYPE("bshell.core", "percent", bshell_percent);
FX_ASSEMBLY_EXPORT_TYPE("bshell.core", "echo", bshell_echo);
FX_ASSEMBLY_END(bshell_core)
@@ -1,10 +1,10 @@
#include "../command/cmdlet.h" #include <bshell/command/cmdlet.h>
#include "../command/command.h" #include <bshell/command/command.h>
#include "../runtime/pipeline.h" #include <bshell/runtime/pipeline.h>
#include "../runtime/runtime.h" #include <bshell/runtime/runtime.h>
#include "../script-block.h" #include <bshell/runtime/scope.h>
#include "../status.h" #include <bshell/runtime/script-block.h>
#include <bshell/status.h>
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/string.h> #include <fx/string.h>
#include <fx/vector.h> #include <fx/vector.h>
@@ -22,11 +22,12 @@ struct bshell_foreach_object_p {
bshell_scriptblock *f_block; bshell_scriptblock *f_block;
}; };
static enum bshell_status begin_processing(bshell_cmdlet *cmdlet) static enum bshell_status begin_processing(
bshell_cmdlet *cmdlet,
enum bshell_command_position position)
{ {
struct bshell_foreach_object_p *p = fx_object_get_private( struct bshell_foreach_object_p *p
cmdlet, = fx_object_get_private(cmdlet, BSHELL_TYPE_FOREACH_OBJECT);
BSHELL_TYPE_FOREACH_OBJECT);
const fx_value *block_v = bshell_command_get_arg(cmdlet, 1); const fx_value *block_v = bshell_command_get_arg(cmdlet, 1);
if (!block_v) { if (!block_v) {
@@ -42,9 +43,8 @@ static enum bshell_status process_record(
bshell_pipeline *pipeline, bshell_pipeline *pipeline,
struct bshell_runtime *rt) struct bshell_runtime *rt)
{ {
struct bshell_foreach_object_p *p = fx_object_get_private( struct bshell_foreach_object_p *p
cmdlet, = fx_object_get_private(cmdlet, BSHELL_TYPE_FOREACH_OBJECT);
BSHELL_TYPE_FOREACH_OBJECT);
fx_value in = bshell_pipeline_read_value(pipeline); fx_value in = bshell_pipeline_read_value(pipeline);
if (!fx_value_is_set(&in)) { if (!fx_value_is_set(&in)) {
@@ -52,8 +52,10 @@ static enum bshell_status process_record(
} }
bshell_runtime_push_scope(rt, p->f_block); bshell_runtime_push_scope(rt, p->f_block);
bshell_variable *item = bshell_runtime_define_var(rt, "_"); bshell_variable *item = bshell_runtime_scope_define_variable(
bshell_variable_set_value(item, &in); bshell_runtime_get_current_scope(rt),
"_");
bshell_variable_set_value(item, in);
fx_value out = bshell_runtime_eval(rt); fx_value out = bshell_runtime_eval(rt);
bshell_runtime_pop_scope(rt); bshell_runtime_pop_scope(rt);
fx_value_unset(&in); fx_value_unset(&in);
@@ -65,9 +67,8 @@ static enum bshell_status process_record(
static enum bshell_status end_processing(bshell_cmdlet *cmdlet) static enum bshell_status end_processing(bshell_cmdlet *cmdlet)
{ {
struct bshell_foreach_object_p *p = fx_object_get_private( struct bshell_foreach_object_p *p
cmdlet, = fx_object_get_private(cmdlet, BSHELL_TYPE_FOREACH_OBJECT);
BSHELL_TYPE_FOREACH_OBJECT);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -1,5 +1,4 @@
#include "../status.h" #include <bshell/status.h>
#include <fx/object.h> #include <fx/object.h>
#include <fx/stream.h> #include <fx/stream.h>
+148
View File
@@ -0,0 +1,148 @@
#include <bshell/command/cmdlet.h>
#include <bshell/command/command.h>
#include <bshell/runtime/pipeline.h>
#include <bshell/runtime/runtime.h>
#include <bshell/runtime/scope.h>
#include <bshell/status.h>
#include <fx/reflection/assembly.h>
#include <fx/reflection/function.h>
#include <fx/string.h>
#include <fx/vector.h>
#define BSHELL_TYPE_GET_COMMAND (bshell_get_command_get_type())
fx_type_id bshell_get_command_get_type(void);
FX_DECLARE_TYPE(bshell_get_command);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_get_command)
FX_TYPE_CLASS_DECLARATION_END(bshell_get_command)
struct bshell_get_command_p {
bool c_eof;
};
static enum bshell_status begin_processing(
bshell_cmdlet *cmdlet,
enum bshell_command_position position)
{
struct bshell_get_command_p *p
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_COMMAND);
return BSHELL_SUCCESS;
}
static enum bshell_status process_record(
bshell_cmdlet *cmdlet,
bshell_pipeline *pipeline,
struct bshell_runtime *rt)
{
struct bshell_get_command_p *p
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_COMMAND);
if (p->c_eof) {
return BSHELL_SUCCESS;
}
const fx_iterator *aliases = fx_iterator_begin(rt->rt_aliases);
fx_foreach(item_v, aliases)
{
fx_hashtable_item *item;
fx_value_get_object(item_v, &item);
const fx_value *alias_v = fx_hashtable_item_get_value(item);
bshell_pipeline_write_value(pipeline, *alias_v, false);
}
fx_iterator_unref(aliases);
struct bshell_runtime_scope *scope
= bshell_runtime_get_current_scope(rt);
while (scope) {
fx_hashtable *function_map
= bshell_runtime_scope_get_functions(scope);
const fx_iterator *functions = fx_iterator_begin(function_map);
fx_foreach(item_v, functions)
{
fx_hashtable_item *item;
fx_value_get_object(item_v, &item);
const fx_value *func_v
= fx_hashtable_item_get_value(item);
bshell_pipeline_write_value(pipeline, *func_v, false);
}
fx_iterator_unref(functions);
scope = bshell_runtime_get_parent_scope(rt, scope);
}
fx_iterator *assemblies = fx_assembly_get_all();
fx_foreach(asm_v, assemblies)
{
fx_assembly *assembly = NULL;
fx_value_get_object(asm_v, &assembly);
fx_iterator *types = fx_assembly_get_types(assembly);
fx_foreach(v, types)
{
fx_type *ty = NULL;
fx_value_get_object(v, &ty);
fx_type_flags ty_flags = fx_type_get_flags(ty);
bool is_abstract = (ty_flags & FX_TYPE_F_ABSTRACT) != 0;
if (is_abstract) {
continue;
}
bshell_command_class *cmd = fx_type_get_interface(
ty,
BSHELL_TYPE_COMMAND);
if (!cmd) {
continue;
}
fx_value callable = FX_VALUE_OBJECT(
fx_object_create(fx_type_get_id(ty)));
bshell_pipeline_write_value(pipeline, callable, false);
fx_value_unset(&callable);
}
fx_iterator_unref(types);
}
fx_iterator_unref(assemblies);
p->c_eof = true;
return BSHELL_SUCCESS;
}
static enum bshell_status end_processing(bshell_cmdlet *cmdlet)
{
struct bshell_get_command_p *p
= fx_object_get_private(cmdlet, BSHELL_TYPE_GET_COMMAND);
return BSHELL_SUCCESS;
}
static void init(fx_object *obj, void *priv)
{
}
FX_TYPE_CLASS_BEGIN(bshell_get_command)
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
FX_INTERFACE_ENTRY(to_string) = NULL;
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_cmdlet, BSHELL_TYPE_CMDLET)
FX_INTERFACE_ENTRY(c_verb) = BSHELL_VERB_GET;
FX_INTERFACE_ENTRY(c_noun) = "Command";
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing;
FX_INTERFACE_ENTRY(c_process_record) = process_record;
FX_INTERFACE_ENTRY(c_end_processing) = end_processing;
FX_TYPE_VTABLE_INTERFACE_END(bshell_cmdlet, BSHELL_TYPE_CMDLET)
FX_TYPE_CLASS_END(bshell_get_command)
FX_TYPE_DEFINITION_BEGIN(bshell_get_command)
FX_TYPE_ID(0x4f862cc3, 0xf3d3, 0x4f04, 0xb68e, 0x8764079f03c4);
FX_TYPE_NAME("bshell.core.get_command");
FX_TYPE_EXTENDS(BSHELL_TYPE_CMDLET);
FX_TYPE_CLASS(bshell_get_command_class);
FX_TYPE_INSTANCE_INIT(init);
FX_TYPE_INSTANCE_PRIVATE(struct bshell_get_command_p);
FX_TYPE_DEFINITION_END(bshell_get_command)
@@ -1,8 +1,7 @@
#include "../command/cmdlet.h" #include <bshell/command/cmdlet.h>
#include "../command/command.h" #include <bshell/command/command.h>
#include "../runtime/pipeline.h" #include <bshell/runtime/pipeline.h>
#include "../status.h" #include <bshell/status.h>
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/string.h> #include <fx/string.h>
#include <fx/vector.h> #include <fx/vector.h>
@@ -18,14 +17,15 @@ FX_TYPE_CLASS_DECLARATION_END(bshell_get_verb)
struct bshell_get_verb_p { struct bshell_get_verb_p {
fx_hashtable *c_verbs; fx_hashtable *c_verbs;
fx_iterator *c_it; const fx_iterator *c_it;
}; };
static enum bshell_status begin_processing(bshell_cmdlet *cmdlet) static enum bshell_status begin_processing(
bshell_cmdlet *cmdlet,
enum bshell_command_position position)
{ {
struct bshell_get_verb_p *p = fx_object_get_private( struct bshell_get_verb_p *p
cmdlet, = fx_object_get_private(cmdlet, BSHELL_TYPE_GET_VERB);
BSHELL_TYPE_GET_VERB);
p->c_verbs = bshell_get_all_verbs(); p->c_verbs = bshell_get_all_verbs();
p->c_it = fx_iterator_begin(p->c_verbs); p->c_it = fx_iterator_begin(p->c_verbs);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
@@ -36,34 +36,29 @@ static enum bshell_status process_record(
bshell_pipeline *pipeline, bshell_pipeline *pipeline,
struct bshell_runtime *rt) struct bshell_runtime *rt)
{ {
struct bshell_get_verb_p *p = fx_object_get_private( struct bshell_get_verb_p *p
cmdlet, = fx_object_get_private(cmdlet, BSHELL_TYPE_GET_VERB);
BSHELL_TYPE_GET_VERB);
do { do {
fx_value v = fx_iterator_get_value(p->c_it); const fx_value *v = fx_iterator_get_value(p->c_it);
if (!v.v_type) { if (!v) {
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
fx_hashtable_item *item = NULL; fx_hashtable_item *item = NULL;
fx_value_get_object(&v, &item); fx_value_get_object(v, &item);
v = fx_hashtable_item_get_value(item); v = fx_hashtable_item_get_value(item);
bshell_verb *verb = NULL; bshell_verb *verb = NULL;
fx_value_get_object(&v, &verb); fx_value_get_object(v, &verb);
fx_iterator_move_next(p->c_it); fx_iterator_move_next(p->c_it);
if (bshell_verb_is_reserved(verb)) { if (bshell_verb_is_reserved(verb)) {
continue; continue;
} }
bshell_verb_ref(verb); bshell_pipeline_write_value(pipeline, *v, false);
bshell_pipeline_write_value(
pipeline,
fx_value_copy_return(fx_hashtable_item_get_value(item)),
false);
break; break;
} while (1); } while (1);
@@ -72,9 +67,8 @@ static enum bshell_status process_record(
static enum bshell_status end_processing(bshell_cmdlet *cmdlet) static enum bshell_status end_processing(bshell_cmdlet *cmdlet)
{ {
struct bshell_get_verb_p *p = fx_object_get_private( struct bshell_get_verb_p *p
cmdlet, = fx_object_get_private(cmdlet, BSHELL_TYPE_GET_VERB);
BSHELL_TYPE_GET_VERB);
if (p->c_it) { if (p->c_it) {
fx_iterator_unref(p->c_it); fx_iterator_unref(p->c_it);
p->c_it = NULL; p->c_it = NULL;
@@ -1,9 +1,7 @@
#include "../command/cmdlet.h" #include <bshell/command/cmdlet.h>
#include "../command/command.h" #include <bshell/command/command.h>
#include "../format/format.h" #include <bshell/runtime/pipeline.h>
#include "../runtime/pipeline.h" #include <bshell/status.h>
#include "../status.h"
#include <fx/collections/array.h> #include <fx/collections/array.h>
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/string.h> #include <fx/string.h>
@@ -20,68 +18,18 @@ FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_write_output)
FX_TYPE_CLASS_DECLARATION_END(bshell_write_output) FX_TYPE_CLASS_DECLARATION_END(bshell_write_output)
struct bshell_write_output_p { struct bshell_write_output_p {
struct table_format_ctx w_table_ctx; size_t w_arg_count;
bool w_table_initialised; size_t w_arg_index;
}; };
static void initialise_table( static enum bshell_status begin_processing(
struct bshell_write_output_p *cmd, bshell_cmdlet *cmdlet,
const fx_value *first_record) enum bshell_command_position position)
{ {
table_format_ctx_init(&cmd->w_table_ctx, fx_stdout); struct bshell_write_output_p *p
const fx_type *ty = fx_type_get_by_id(first_record->v_type); = fx_object_get_private(cmdlet, BSHELL_TYPE_WRITE_OUTPUT);
table_format_ctx_prepare_columns_from_format( p->w_arg_index = 1;
&cmd->w_table_ctx, p->w_arg_count = bshell_command_get_arg_count(cmdlet);
ty,
NULL);
table_format_ctx_print_headers(&cmd->w_table_ctx);
cmd->w_table_initialised = true;
}
static bool value_requires_table(const fx_value *value)
{
if (fx_type_is_value_type(value->v_type)) {
return false;
}
if (fx_value_is_type(value, FX_TYPE_STRING)
|| fx_value_is_type(value, FX_TYPE_ARRAY)) {
return false;
}
return true;
}
static void write_value(
struct bshell_write_output_p *cmd,
const fx_value *value)
{
if (!value_requires_table(value)) {
fx_value_to_string(value, fx_stdout, NULL);
fx_stream_write_char(fx_stdout, '\n');
return;
}
if (!cmd->w_table_initialised) {
initialise_table(cmd, value);
}
table_format_ctx_print_record(&cmd->w_table_ctx, value);
}
static enum bshell_status begin_processing(bshell_cmdlet *cmdlet)
{
struct bshell_write_output_p *p = fx_object_get_private(
cmdlet,
BSHELL_TYPE_WRITE_OUTPUT);
for (size_t i = 1;; i++) {
const fx_value *v = bshell_command_get_arg(cmdlet, i);
if (!v) {
break;
}
write_value(p, v);
}
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -91,13 +39,19 @@ static enum bshell_status process_record(
bshell_pipeline *pipeline, bshell_pipeline *pipeline,
struct bshell_runtime *rt) struct bshell_runtime *rt)
{ {
struct bshell_write_output_p *p = fx_object_get_private( struct bshell_write_output_p *p
cmdlet, = fx_object_get_private(cmdlet, BSHELL_TYPE_WRITE_OUTPUT);
BSHELL_TYPE_WRITE_OUTPUT);
if (p->w_arg_index < p->w_arg_count) {
const fx_value *arg
= bshell_command_get_arg(cmdlet, p->w_arg_index++);
bshell_pipeline_write_value(pipeline, *arg, false);
return BSHELL_SUCCESS;
}
fx_value in = bshell_pipeline_read_value(pipeline); fx_value in = bshell_pipeline_read_value(pipeline);
if (fx_value_is_set(&in)) { if (fx_value_is_set(&in)) {
write_value(p, &in); bshell_pipeline_write_value(pipeline, in, false);
fx_value_unset(&in); fx_value_unset(&in);
} }
@@ -106,9 +60,8 @@ static enum bshell_status process_record(
static enum bshell_status end_processing(bshell_cmdlet *cmdlet) static enum bshell_status end_processing(bshell_cmdlet *cmdlet)
{ {
struct bshell_write_output_p *p = fx_object_get_private( struct bshell_write_output_p *p
cmdlet, = fx_object_get_private(cmdlet, BSHELL_TYPE_WRITE_OUTPUT);
BSHELL_TYPE_WRITE_OUTPUT);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
+40
View File
@@ -0,0 +1,40 @@
set(source_dirs
ast compile parse parse/lex parse/syntax
format runtime command)
if (bshell_interactive)
set(source_dirs ${source_dirs} line-editor)
endif ()
file(GLOB sources
*.c
*.h)
foreach (d ${source_dirs})
file(GLOB d_sources
${d}/*.c
${d}/*.h)
set(sources ${sources} ${d_sources})
endforeach (d)
add_library(bshell.runtime SHARED ${sources})
target_link_libraries(bshell.runtime FX::Runtime FX::Collections FX::Io)
if (bshell_interactive)
target_link_libraries(bshell.runtime FX::Term)
endif ()
if (bshell_enable_native_commands)
target_link_libraries(bshell.runtime FX::Diagnostics)
endif ()
target_include_directories(bshell.runtime PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_definitions(bshell.runtime PUBLIC
BSHELL_VERSION="${bshell_version}"
BSHELL_ENABLE_FLOATING_POINT=${bshell_enable_floating_point}
BSHELL_ENABLE_NATIVE_COMMANDS=${bshell_enable_native_commands}
BSHELL_INTERACTIVE=${bshell_interactive}
BSHELL_VERBOSE=${bshell_verbose})
install(TARGETS bshell.runtime)
+16
View File
@@ -0,0 +1,16 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN(bshell_runtime)
FX_ASSEMBLY_NAME("bshell.runtime");
FX_ASSEMBLY_VERSION(0, 1, 0, 0);
FX_ASSEMBLY_EXPORT_TYPE("bshell.runtime", "command", bshell_command);
FX_ASSEMBLY_EXPORT_TYPE("bshell.runtime", "alias", bshell_alias);
// FX_ASSEMBLY_EXPORT_TYPE("bshell.runtime", "function",
// bshell_function);
FX_ASSEMBLY_EXPORT_TYPE("bshell.runtime", "cmdlet", bshell_cmdlet);
FX_ASSEMBLY_EXPORT_TYPE(
"bshell.runtime",
"scriptblock",
bshell_scriptblock);
FX_ASSEMBLY_END(bshell_runtime)
+28
View File
@@ -0,0 +1,28 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_array_ast_node *array = (struct bshell_array_ast_node *)
node;
fx_queue_entry *cur = fx_queue_first(&array->n_items);
while (cur) {
struct bshell_ast_node *child = fx_unbox(
struct bshell_ast_node,
cur,
n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition array_bshell_ast_node = {
.def_id = BSHELL_AST_ARRAY,
.def_node_size = sizeof(struct bshell_array_ast_node),
.def_collect_children = collect_children,
};
+267
View File
@@ -0,0 +1,267 @@
#include <assert.h>
#include <bshell/ast.h>
#include <bshell/status.h>
#include <stdlib.h>
#include <string.h>
extern struct bshell_ast_node_definition null_bshell_ast_node;
extern struct bshell_ast_node_definition int_bshell_ast_node;
extern struct bshell_ast_node_definition double_bshell_ast_node;
extern struct bshell_ast_node_definition word_bshell_ast_node;
extern struct bshell_ast_node_definition var_bshell_ast_node;
extern struct bshell_ast_node_definition string_bshell_ast_node;
extern struct bshell_ast_node_definition fstring_bshell_ast_node;
extern struct bshell_ast_node_definition cmdcall_bshell_ast_node;
extern struct bshell_ast_node_definition pipeline_bshell_ast_node;
extern struct bshell_ast_node_definition redirection_bshell_ast_node;
extern struct bshell_ast_node_definition block_bshell_ast_node;
extern struct bshell_ast_node_definition stmt_list_bshell_ast_node;
extern struct bshell_ast_node_definition func_bshell_ast_node;
extern struct bshell_ast_node_definition array_bshell_ast_node;
extern struct bshell_ast_node_definition hashtable_bshell_ast_node;
extern struct bshell_ast_node_definition hashtable_item_bshell_ast_node;
extern struct bshell_ast_node_definition if_bshell_ast_node;
extern struct bshell_ast_node_definition if_branch_bshell_ast_node;
extern struct bshell_ast_node_definition op_bshell_ast_node;
static const struct bshell_ast_node_definition *bshell_ast_node_definitions[]
= {
[BSHELL_AST_NULL] = &null_bshell_ast_node,
[BSHELL_AST_INT] = &int_bshell_ast_node,
[BSHELL_AST_DOUBLE] = &double_bshell_ast_node,
[BSHELL_AST_WORD] = &word_bshell_ast_node,
[BSHELL_AST_VAR] = &var_bshell_ast_node,
[BSHELL_AST_STRING] = &string_bshell_ast_node,
[BSHELL_AST_FSTRING] = &fstring_bshell_ast_node,
[BSHELL_AST_CMDCALL] = &cmdcall_bshell_ast_node,
[BSHELL_AST_PIPELINE] = &pipeline_bshell_ast_node,
[BSHELL_AST_REDIRECTION] = &redirection_bshell_ast_node,
[BSHELL_AST_BLOCK] = &block_bshell_ast_node,
[BSHELL_AST_STMT_LIST] = &stmt_list_bshell_ast_node,
[BSHELL_AST_FUNC] = &func_bshell_ast_node,
[BSHELL_AST_ARRAY] = &array_bshell_ast_node,
[BSHELL_AST_IF] = &if_bshell_ast_node,
[BSHELL_AST_IF_BRANCH] = &if_branch_bshell_ast_node,
[BSHELL_AST_HASHTABLE] = &hashtable_bshell_ast_node,
[BSHELL_AST_HASHTABLE_ITEM] = &hashtable_item_bshell_ast_node,
[BSHELL_AST_OP] = &op_bshell_ast_node,
};
static const size_t nr_bshell_ast_node_definitions
= sizeof bshell_ast_node_definitions
/ sizeof bshell_ast_node_definitions[0];
struct bshell_ast_node *bshell_ast_node_create(enum bshell_ast_node_type type)
{
assert(type < nr_bshell_ast_node_definitions);
const struct bshell_ast_node_definition *def
= bshell_ast_node_definitions[type];
struct bshell_ast_node *out = malloc(def->def_node_size);
if (!out) {
return NULL;
}
memset(out, 0x0, def->def_node_size);
out->n_type = type;
return out;
}
void bshell_ast_node_destroy(struct bshell_ast_node *node)
{
assert(node->n_type < nr_bshell_ast_node_definitions);
struct bshell_ast_iterator it = {0};
bshell_ast_iterator_enqueue(&it, node);
while (1) {
node = bshell_ast_iterator_peek(&it);
if (!node) {
break;
}
const struct bshell_ast_node_definition *def
= bshell_ast_node_definitions[node->n_type];
if (def->def_cleanup) {
def->def_cleanup(node);
}
bshell_ast_iterator_dequeue(&it);
free(node);
}
}
void bshell_ast_node_to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
const struct bshell_ast_node_definition *def
= bshell_ast_node_definitions[node->n_type];
if (def->def_to_string) {
def->def_to_string(node, out);
}
}
#define ENUM_STR(x) \
case x: \
return #x
const char *bshell_ast_node_type_to_string(enum bshell_ast_node_type type)
{
switch (type) {
ENUM_STR(BSHELL_AST_NONE);
ENUM_STR(BSHELL_AST_NULL);
ENUM_STR(BSHELL_AST_STMT_LIST);
ENUM_STR(BSHELL_AST_INT);
ENUM_STR(BSHELL_AST_DOUBLE);
ENUM_STR(BSHELL_AST_WORD);
ENUM_STR(BSHELL_AST_STRING);
ENUM_STR(BSHELL_AST_FSTRING);
ENUM_STR(BSHELL_AST_VAR);
ENUM_STR(BSHELL_AST_VAR_SPLAT);
ENUM_STR(BSHELL_AST_FLAG);
ENUM_STR(BSHELL_AST_CMDCALL);
ENUM_STR(BSHELL_AST_PIPELINE);
ENUM_STR(BSHELL_AST_REDIRECTION);
ENUM_STR(BSHELL_AST_BLOCK);
ENUM_STR(BSHELL_AST_FUNC);
ENUM_STR(BSHELL_AST_IF);
ENUM_STR(BSHELL_AST_IF_BRANCH);
ENUM_STR(BSHELL_AST_OP);
ENUM_STR(BSHELL_AST_ARRAY);
ENUM_STR(BSHELL_AST_HASHTABLE);
ENUM_STR(BSHELL_AST_HASHTABLE_ITEM);
default:
return "<unknown>";
}
}
struct bshell_ast_node *bshell_ast_iterator_peek(struct bshell_ast_iterator *it)
{
fx_queue_entry *cur = fx_queue_first(&it->it_queue);
if (!cur) {
return NULL;
}
return fx_unbox(struct bshell_ast_node, cur, n_it.e_entry);
}
struct bshell_ast_node *bshell_ast_iterator_dequeue(
struct bshell_ast_iterator *it)
{
fx_queue_entry *cur = fx_queue_first(&it->it_queue);
if (!cur) {
return NULL;
}
struct bshell_ast_node *node
= fx_unbox(struct bshell_ast_node, cur, n_it.e_entry);
const struct bshell_ast_node_definition *def
= bshell_ast_node_definitions[node->n_type];
it->it_insert_after = cur;
if (def->def_collect_children) {
def->def_collect_children(node, it);
}
fx_queue_pop_front(&it->it_queue);
return fx_unbox(struct bshell_ast_node, cur, n_it.e_entry);
}
void bshell_ast_iterator_enqueue(
struct bshell_ast_iterator *it,
struct bshell_ast_node *node)
{
unsigned long new_depth = 0;
fx_queue_entry *cur = fx_queue_first(&it->it_queue);
if (cur) {
struct bshell_ast_node *cur_node
= fx_unbox(struct bshell_ast_node, cur, n_it.e_entry);
new_depth = cur_node->n_it.e_depth + 1;
}
node->n_it.e_depth = new_depth;
if (!it->it_insert_after) {
fx_queue_push_back(&it->it_queue, &node->n_it.e_entry);
return;
}
fx_queue_insert_after(
&it->it_queue,
&node->n_it.e_entry,
it->it_insert_after);
it->it_insert_after = &node->n_it.e_entry;
}
enum bshell_status bshell_ast_node_iterate(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it,
bshell_ast_iterator_callback callback,
void *arg)
{
fx_queue_push_back(&it->it_queue, &node->n_it.e_entry);
node->n_it.e_depth = 0;
fx_queue_entry *entry = fx_queue_first(&it->it_queue);
while (entry) {
struct bshell_ast_iterator_entry *it_entry = fx_unbox(
struct bshell_ast_iterator_entry,
entry,
e_entry);
node = fx_unbox(struct bshell_ast_node, it_entry, n_it);
if (!node) {
/* this should never happen. */
return BSHELL_ERR_INTERNAL_FAILURE;
}
struct bshell_ast_iterate_result result
= callback(node, BSHELL_AST_ITERATION_PRE, it, arg);
if (result.r_status != BSHELL_SUCCESS
|| result.r_flags & BSHELL_AST_ITERATE_STOP) {
return result.r_status;
}
const struct bshell_ast_node_definition *type
= bshell_ast_node_definitions[node->n_type];
if (type->def_collect_children
&& result.r_flags & BSHELL_AST_ITERATE_ADD_CHILDREN) {
it->it_insert_after = entry;
type->def_collect_children(node, it);
}
if (!(result.r_flags & BSHELL_AST_ITERATE_REPEAT)) {
entry = fx_queue_next(entry);
}
}
while (!fx_queue_empty(&it->it_queue)) {
fx_queue_entry *entry = fx_queue_last(&it->it_queue);
if (!entry) {
break;
}
node = fx_unbox(struct bshell_ast_node, entry, n_it);
if (!node) {
/* this should never happen. */
return BSHELL_ERR_INTERNAL_FAILURE;
}
struct bshell_ast_iterate_result result
= callback(node, BSHELL_AST_ITERATION_POST, it, arg);
if (result.r_status != BSHELL_SUCCESS
|| result.r_flags & BSHELL_AST_ITERATE_STOP) {
return result.r_status;
}
if (!(result.r_flags & BSHELL_AST_ITERATE_REPEAT)) {
fx_queue_pop_back(&it->it_queue);
}
}
return BSHELL_SUCCESS;
}
+26
View File
@@ -0,0 +1,26 @@
#include <bshell/ast.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_block_ast_node *block = (struct bshell_block_ast_node *)
node;
fx_queue_entry *cur = fx_queue_first(&block->n_statements);
while (cur) {
struct bshell_ast_node *child = fx_unbox(
struct bshell_ast_node,
cur,
n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition block_bshell_ast_node = {
.def_id = BSHELL_AST_BLOCK,
.def_node_size = sizeof(struct bshell_block_ast_node),
.def_collect_children = collect_children,
};
+37
View File
@@ -0,0 +1,37 @@
#include <bshell/ast.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_cmdcall_ast_node *cmdcall = (struct
bshell_cmdcall_ast_node *)
node;
fx_queue_entry *cur = fx_queue_first(&cmdcall->n_args);
while (cur) {
struct bshell_ast_node *child = fx_unbox(
struct bshell_ast_node,
cur,
n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
cur = fx_queue_first(&cmdcall->n_redirect);
while (cur) {
struct bshell_ast_node *child = fx_unbox(
struct bshell_ast_node,
cur,
n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition cmdcall_bshell_ast_node = {
.def_id = BSHELL_AST_CMDCALL,
.def_node_size = sizeof(struct bshell_cmdcall_ast_node),
.def_collect_children = collect_children,
};
+25
View File
@@ -0,0 +1,25 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
#include <fx/stream.h>
static void to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
struct bshell_double_ast_node *i
= (struct bshell_double_ast_node *)node;
fx_value_to_string(&i->n_value->tok_number, (fx_stream *)out, NULL);
}
static enum bshell_status cleanup(struct bshell_ast_node *node)
{
struct bshell_double_ast_node *d
= (struct bshell_double_ast_node *)node;
bshell_lex_token_destroy(d->n_value);
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition double_bshell_ast_node = {
.def_id = BSHELL_AST_DOUBLE,
.def_node_size = sizeof(struct bshell_double_ast_node),
.def_to_string = to_string,
.def_cleanup = cleanup,
};
+26
View File
@@ -0,0 +1,26 @@
#include <bshell/ast.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_fstring_ast_node *fstring;
fstring = (struct bshell_fstring_ast_node *)node;
fx_queue_entry *cur = fx_queue_first(&fstring->n_elements);
while (cur) {
struct bshell_ast_node *child = fx_unbox(
struct bshell_ast_node,
cur,
n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition fstring_bshell_ast_node = {
.def_id = BSHELL_AST_FSTRING,
.def_node_size = sizeof(struct bshell_fstring_ast_node),
.def_collect_children = collect_children,
};
+45
View File
@@ -0,0 +1,45 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_func_ast_node *func = (struct bshell_func_ast_node *)node;
fx_queue_entry *cur = fx_queue_first(&func->n_params);
while (cur) {
struct bshell_ast_node *child
= fx_unbox(struct bshell_ast_node, cur, n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
if (func->n_body) {
bshell_ast_iterator_enqueue(it, func->n_body);
}
return BSHELL_SUCCESS;
}
static void to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
const struct bshell_func_ast_node *func
= (const struct bshell_func_ast_node *)node;
fx_bstr_write_fmt(out, NULL, "%s", func->n_name->tok_str);
}
static enum bshell_status cleanup(struct bshell_ast_node *node)
{
struct bshell_func_ast_node *d = (struct bshell_func_ast_node *)node;
bshell_lex_token_destroy(d->n_name);
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition func_bshell_ast_node = {
.def_id = BSHELL_AST_FUNC,
.def_node_size = sizeof(struct bshell_func_ast_node),
.def_collect_children = collect_children,
.def_to_string = to_string,
.def_cleanup = cleanup,
};
+26
View File
@@ -0,0 +1,26 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_hashtable_item_ast_node *item
= (struct bshell_hashtable_item_ast_node *)node;
if (item->n_key) {
bshell_ast_iterator_enqueue(it, item->n_key);
}
if (item->n_value) {
bshell_ast_iterator_enqueue(it, item->n_value);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition hashtable_item_bshell_ast_node = {
.def_id = BSHELL_AST_HASHTABLE_ITEM,
.def_node_size = sizeof(struct bshell_hashtable_item_ast_node),
.def_collect_children = collect_children,
};
+24
View File
@@ -0,0 +1,24 @@
#include <bshell/ast.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_hashtable_ast_node *hashtable
= (struct bshell_hashtable_ast_node *)node;
fx_queue_entry *cur = fx_queue_first(&hashtable->n_items);
while (cur) {
struct bshell_ast_node *child
= fx_unbox(struct bshell_ast_node, cur, n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition hashtable_bshell_ast_node = {
.def_id = BSHELL_AST_HASHTABLE,
.def_node_size = sizeof(struct bshell_hashtable_ast_node),
.def_collect_children = collect_children,
};
+24
View File
@@ -0,0 +1,24 @@
#include <bshell/ast.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_if_branch_ast_node *if_branch
= (struct bshell_if_branch_ast_node *)node;
if (if_branch->n_cond) {
bshell_ast_iterator_enqueue(it, if_branch->n_cond);
}
if (if_branch->n_body) {
bshell_ast_iterator_enqueue(it, if_branch->n_body);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition if_branch_bshell_ast_node = {
.def_id = BSHELL_AST_IF_BRANCH,
.def_node_size = sizeof(struct bshell_if_branch_ast_node),
.def_collect_children = collect_children,
};
+23
View File
@@ -0,0 +1,23 @@
#include <bshell/ast.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_if_ast_node *if_group = (struct bshell_if_ast_node *)node;
fx_queue_entry *cur = fx_queue_first(&if_group->n_branches);
while (cur) {
struct bshell_ast_node *child
= fx_unbox(struct bshell_ast_node, cur, n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition if_bshell_ast_node = {
.def_id = BSHELL_AST_IF,
.def_node_size = sizeof(struct bshell_if_ast_node),
.def_collect_children = collect_children,
};
+23
View File
@@ -0,0 +1,23 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
#include <fx/stream.h>
static void to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
struct bshell_int_ast_node *i = (struct bshell_int_ast_node *)node;
fx_value_to_string(&i->n_value->tok_number, (fx_stream *)out, NULL);
}
static enum bshell_status cleanup(struct bshell_ast_node *node)
{
struct bshell_int_ast_node *i = (struct bshell_int_ast_node *)node;
bshell_lex_token_destroy(i->n_value);
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition int_bshell_ast_node = {
.def_id = BSHELL_AST_INT,
.def_node_size = sizeof(struct bshell_int_ast_node),
.def_to_string = to_string,
.def_cleanup = cleanup,
};
+7
View File
@@ -0,0 +1,7 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
struct bshell_ast_node_definition null_bshell_ast_node = {
.def_id = BSHELL_AST_NULL,
.def_node_size = sizeof(struct bshell_null_ast_node),
};
+38
View File
@@ -0,0 +1,38 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
#include <bshell/runtime/operator.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_op_ast_node *op = (struct bshell_op_ast_node *)node;
if (op->n_left) {
bshell_ast_iterator_enqueue(it, op->n_left);
}
if (op->n_right) {
bshell_ast_iterator_enqueue(it, op->n_right);
}
return BSHELL_SUCCESS;
}
static void to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
const struct bshell_op_ast_node *op = (const struct bshell_op_ast_node
*)node;
fx_bstr_write_fmt(
out,
NULL,
"%s",
bshell_operator_id_to_string(op->n_op->op_id));
}
struct bshell_ast_node_definition op_bshell_ast_node = {
.def_id = BSHELL_AST_OP,
.def_node_size = sizeof(struct bshell_op_ast_node),
.def_collect_children = collect_children,
.def_to_string = to_string,
};
+26
View File
@@ -0,0 +1,26 @@
#include <bshell/ast.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_pipeline_ast_node *pipeline;
pipeline = (struct bshell_pipeline_ast_node *)node;
fx_queue_entry *cur = fx_queue_first(&pipeline->n_stages);
while (cur) {
struct bshell_ast_node *child = fx_unbox(
struct bshell_ast_node,
cur,
n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition pipeline_bshell_ast_node = {
.def_id = BSHELL_AST_PIPELINE,
.def_node_size = sizeof(struct bshell_pipeline_ast_node),
.def_collect_children = collect_children,
};
+61
View File
@@ -0,0 +1,61 @@
#include <bshell/ast.h>
#include <bshell/parse/lex.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_redirection_ast_node *redirection
= (struct bshell_redirection_ast_node *)node;
if (redirection->n_out_path_expr) {
bshell_ast_iterator_enqueue(it, redirection->n_out_path_expr);
}
return BSHELL_SUCCESS;
}
static void to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
struct bshell_redirection_ast_node *redirection
= (struct bshell_redirection_ast_node *)node;
fx_bstr_write_fmt(out, NULL, "&%u", redirection->n_in);
if (redirection->n_append) {
fx_bstr_write_fmt(out, NULL, " >>");
} else {
fx_bstr_write_fmt(out, NULL, " >");
}
if (redirection->n_out_is_fd) {
fx_bstr_write_fmt(out, NULL, " &");
} else {
fx_bstr_write_fmt(out, NULL, " ");
}
if (redirection->n_out_is_expr) {
fx_bstr_write_fmt(out, NULL, "<expr>");
} else if (redirection->n_out_path) {
fx_bstr_write_fmt(out, NULL, "'%s'", redirection->n_out_path);
} else {
fx_bstr_write_fmt(out, NULL, "%u", redirection->n_out);
}
}
static enum bshell_status cleanup(struct bshell_ast_node *node)
{
struct bshell_redirection_ast_node *v
= (struct bshell_redirection_ast_node *)node;
if (v->n_out_tok) {
bshell_lex_token_destroy(v->n_out_tok);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition redirection_bshell_ast_node = {
.def_id = BSHELL_AST_REDIRECTION,
.def_node_size = sizeof(struct bshell_redirection_ast_node),
.def_collect_children = collect_children,
.def_to_string = to_string,
.def_cleanup = cleanup,
};
+24
View File
@@ -0,0 +1,24 @@
#include <bshell/ast.h>
static enum bshell_status collect_children(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it)
{
struct bshell_stmt_list_ast_node *stmt_list
= (struct bshell_stmt_list_ast_node *)node;
fx_queue_entry *cur = fx_queue_first(&stmt_list->n_statements);
while (cur) {
struct bshell_ast_node *child
= fx_unbox(struct bshell_ast_node, cur, n_entry);
bshell_ast_iterator_enqueue(it, child);
cur = fx_queue_next(cur);
}
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition stmt_list_bshell_ast_node = {
.def_id = BSHELL_AST_STMT_LIST,
.def_node_size = sizeof(struct bshell_stmt_list_ast_node),
.def_collect_children = collect_children,
};
+24
View File
@@ -0,0 +1,24 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
static void to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
const struct bshell_string_ast_node *string
= (const struct bshell_string_ast_node *)node;
fx_bstr_write_fmt(out, NULL, "%s", string->n_value->tok_str);
}
static enum bshell_status cleanup(struct bshell_ast_node *node)
{
struct bshell_string_ast_node *string
= (struct bshell_string_ast_node *)node;
bshell_lex_token_destroy(string->n_value);
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition string_bshell_ast_node = {
.def_id = BSHELL_AST_STRING,
.def_node_size = sizeof(struct bshell_string_ast_node),
.def_to_string = to_string,
.def_cleanup = cleanup,
};
+23
View File
@@ -0,0 +1,23 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
static void to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
const struct bshell_var_ast_node *var
= (const struct bshell_var_ast_node *)node;
fx_bstr_write_fmt(out, NULL, "%s", var->n_ident->tok_str);
}
static enum bshell_status cleanup(struct bshell_ast_node *node)
{
struct bshell_var_ast_node *v = (struct bshell_var_ast_node *)node;
bshell_lex_token_destroy(v->n_ident);
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition var_bshell_ast_node = {
.def_id = BSHELL_AST_VAR,
.def_node_size = sizeof(struct bshell_var_ast_node),
.def_to_string = to_string,
.def_cleanup = cleanup,
};
+23
View File
@@ -0,0 +1,23 @@
#include <bshell/ast.h>
#include <bshell/parse/token.h>
static void to_string(const struct bshell_ast_node *node, fx_bstr *out)
{
const struct bshell_word_ast_node *word
= (const struct bshell_word_ast_node *)node;
fx_bstr_write_fmt(out, NULL, "%s", word->n_value->tok_str);
}
static enum bshell_status cleanup(struct bshell_ast_node *node)
{
struct bshell_word_ast_node *w = (struct bshell_word_ast_node *)node;
bshell_lex_token_destroy(w->n_value);
return BSHELL_SUCCESS;
}
struct bshell_ast_node_definition word_bshell_ast_node = {
.def_id = BSHELL_AST_WORD,
.def_node_size = sizeof(struct bshell_word_ast_node),
.def_to_string = to_string,
.def_cleanup = cleanup,
};
@@ -1,8 +1,6 @@
#include "alias.h" #include <bshell/command/alias.h>
#include <bshell/command/command.h>
#include "../status.h" #include <bshell/status.h>
#include "command.h"
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/string.h> #include <fx/string.h>
#include <fx/vector.h> #include <fx/vector.h>
@@ -18,9 +16,8 @@ enum bshell_status bshell_alias_get_callable_name(
const bshell_alias *alias, const bshell_alias *alias,
fx_string *out) fx_string *out)
{ {
bshell_alias_class *c = fx_object_get_interface( bshell_alias_class *c
alias, = fx_object_get_interface(alias, BSHELL_TYPE_ALIAS);
BSHELL_TYPE_ALIAS);
if (!c) { if (!c) {
return BSHELL_ERR_NOT_SUPPORTED; return BSHELL_ERR_NOT_SUPPORTED;
} }
@@ -41,9 +38,8 @@ enum bshell_status bshell_alias_get_target_name(
const bshell_alias *alias, const bshell_alias *alias,
fx_string *out) fx_string *out)
{ {
bshell_alias_class *c = fx_object_get_interface( bshell_alias_class *c
alias, = fx_object_get_interface(alias, BSHELL_TYPE_ALIAS);
BSHELL_TYPE_ALIAS);
if (!c) { if (!c) {
return BSHELL_ERR_NOT_SUPPORTED; return BSHELL_ERR_NOT_SUPPORTED;
} }
@@ -95,6 +91,10 @@ static enum bshell_status get_description(
target_name = c->a_get_target_name(cmd); target_name = c->a_get_target_name(cmd);
} }
if (!callable_name || !target_name) {
return BSHELL_ERR_NOT_SUPPORTED;
}
fx_string_append_cstr(out, callable_name); fx_string_append_cstr(out, callable_name);
fx_string_append_cstr(out, " -> "); fx_string_append_cstr(out, " -> ");
fx_string_append_cstr(out, target_name); fx_string_append_cstr(out, target_name);
@@ -125,7 +125,8 @@ FX_TYPE_CLASS_END(bshell_alias)
FX_TYPE_DEFINITION_BEGIN(bshell_alias) FX_TYPE_DEFINITION_BEGIN(bshell_alias)
FX_TYPE_ID(0x1736c10e, 0xebe6, 0x4ba5, 0x83d9, 0x5da3b7dc706c); FX_TYPE_ID(0x1736c10e, 0xebe6, 0x4ba5, 0x83d9, 0x5da3b7dc706c);
FX_TYPE_NAME("bshell.alias"); FX_TYPE_FLAGS(FX_TYPE_F_ABSTRACT);
FX_TYPE_NAME("bshell.runtime.alias");
FX_TYPE_EXTENDS(BSHELL_TYPE_COMMAND); FX_TYPE_EXTENDS(BSHELL_TYPE_COMMAND);
FX_TYPE_CLASS(bshell_alias_class); FX_TYPE_CLASS(bshell_alias_class);
FX_TYPE_INSTANCE_INIT(init); FX_TYPE_INSTANCE_INIT(init);
@@ -1,8 +1,6 @@
#include "cmdlet.h" #include <bshell/command/cmdlet.h>
#include <bshell/command/command.h>
#include "../status.h" #include <bshell/status.h>
#include "command.h"
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/string.h> #include <fx/string.h>
#include <fx/vector.h> #include <fx/vector.h>
@@ -18,9 +16,8 @@ static enum bshell_status get_callable_name_static(
const fx_type *ty, const fx_type *ty,
fx_string *out) fx_string *out)
{ {
bshell_cmdlet_class *class = fx_type_get_interface( bshell_cmdlet_class *class
ty, = fx_type_get_interface(ty, BSHELL_TYPE_CMDLET);
BSHELL_TYPE_CMDLET);
if (!class) { if (!class) {
return BSHELL_ERR_NOT_SUPPORTED; return BSHELL_ERR_NOT_SUPPORTED;
} }
@@ -52,7 +49,8 @@ FX_TYPE_CLASS_END(bshell_cmdlet)
FX_TYPE_DEFINITION_BEGIN(bshell_cmdlet) FX_TYPE_DEFINITION_BEGIN(bshell_cmdlet)
FX_TYPE_ID(0xc71f4d59, 0x8066, 0x4294, 0xa6b0, 0xe1f3eb04f454); FX_TYPE_ID(0xc71f4d59, 0x8066, 0x4294, 0xa6b0, 0xe1f3eb04f454);
FX_TYPE_NAME("bshell.cmdlet"); FX_TYPE_FLAGS(FX_TYPE_F_ABSTRACT);
FX_TYPE_NAME("bshell.runtime.cmdlet");
FX_TYPE_EXTENDS(BSHELL_TYPE_COMMAND); FX_TYPE_EXTENDS(BSHELL_TYPE_COMMAND);
FX_TYPE_CLASS(bshell_cmdlet_class); FX_TYPE_CLASS(bshell_cmdlet_class);
FX_TYPE_INSTANCE_INIT(init); FX_TYPE_INSTANCE_INIT(init);
@@ -1,8 +1,6 @@
#include "command.h" #include <bshell/command/command.h>
#include <bshell/runtime/pipeline.h>
#include "../runtime/pipeline.h" #include <bshell/status.h>
#include "../status.h"
#include <fx/reflection/assembly.h> #include <fx/reflection/assembly.h>
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/reflection/type.h> #include <fx/reflection/type.h>
@@ -19,6 +17,11 @@ static void init(fx_object *obj, void *priv)
{ {
} }
static void fini(fx_object *obj, void *priv)
{
struct bshell_command_p *cmd = priv;
}
static void command_set_args( static void command_set_args(
struct bshell_command_p *cmd, struct bshell_command_p *cmd,
fx_value *args, fx_value *args,
@@ -54,6 +57,11 @@ static const fx_value *command_get_arg(
return &cmd->cmd_args[index]; return &cmd->cmd_args[index];
} }
static size_t command_get_arg_count(struct bshell_command_p *cmd)
{
return cmd->cmd_nr_args;
}
static fx_status get_command_type( static fx_status get_command_type(
const fx_value *cmd_v, const fx_value *cmd_v,
const fx_property *prop, const fx_property *prop,
@@ -61,9 +69,8 @@ static fx_status get_command_type(
{ {
bshell_command *cmd = NULL; bshell_command *cmd = NULL;
fx_value_get_object(cmd_v, &cmd); fx_value_get_object(cmd_v, &cmd);
bshell_command_class *cmd_class = fx_object_get_interface( bshell_command_class *cmd_class
cmd, = fx_object_get_interface(cmd, BSHELL_TYPE_COMMAND);
BSHELL_TYPE_COMMAND);
*out = FX_CSTR(cmd_class->c_command_type); *out = FX_CSTR(cmd_class->c_command_type);
return FX_SUCCESS; return FX_SUCCESS;
@@ -76,9 +83,8 @@ static fx_status get_name(
{ {
bshell_command *cmd = NULL; bshell_command *cmd = NULL;
fx_value_get_object(cmd_v, &cmd); fx_value_get_object(cmd_v, &cmd);
bshell_command_class *cmd_class = fx_object_get_interface( bshell_command_class *cmd_class
cmd, = fx_object_get_interface(cmd, BSHELL_TYPE_COMMAND);
BSHELL_TYPE_COMMAND);
fx_string *result = fx_string_create(); fx_string *result = fx_string_create();
const fx_type *ty = fx_type_get_by_id(fx_object_query_type(cmd)); const fx_type *ty = fx_type_get_by_id(fx_object_query_type(cmd));
@@ -106,6 +112,10 @@ static fx_status get_version(
fx_value_get_object(cmd_v, &cmd); fx_value_get_object(cmd_v, &cmd);
const fx_type *ty = fx_type_get_by_id(fx_object_query_type(cmd)); const fx_type *ty = fx_type_get_by_id(fx_object_query_type(cmd));
const fx_assembly *assembly = fx_type_get_assembly(ty); const fx_assembly *assembly = fx_type_get_assembly(ty);
if (!assembly) {
*out = FX_VALUE_EMPTY;
return FX_SUCCESS;
}
long major = 0, minor = 0, build = 0, revision = 0; long major = 0, minor = 0, build = 0, revision = 0;
fx_assembly_get_version(assembly, &major, &minor, &build, &revision); fx_assembly_get_version(assembly, &major, &minor, &build, &revision);
@@ -142,11 +152,16 @@ static fx_status get_source(
const fx_type *ty = fx_type_get_by_id(fx_object_query_type(cmd)); const fx_type *ty = fx_type_get_by_id(fx_object_query_type(cmd));
const fx_assembly *assembly = fx_type_get_assembly(ty); const fx_assembly *assembly = fx_type_get_assembly(ty);
if (assembly) {
*out = FX_CSTR(fx_assembly_get_name(assembly)); *out = FX_CSTR(fx_assembly_get_name(assembly));
} else {
*out = FX_VALUE_EMPTY;
}
return FX_SUCCESS; return FX_SUCCESS;
} }
extern const fx_assembly *bshell_assembly_get(void); extern const fx_assembly *bshell_runtime_assembly_get(void);
bshell_command *bshell_command_find_static(const char *name) bshell_command *bshell_command_find_static(const char *name)
{ {
@@ -154,13 +169,24 @@ bshell_command *bshell_command_find_static(const char *name)
fx_string *call_name = fx_string_create_from_cstr(name); fx_string *call_name = fx_string_create_from_cstr(name);
fx_string_transform_lowercase(call_name); fx_string_transform_lowercase(call_name);
const fx_assembly *self = bshell_assembly_get(); bshell_command *result = NULL;
fx_iterator *it = fx_assembly_get_types(self);
fx_foreach(v, it) fx_iterator *assemblies = fx_assembly_get_all();
fx_foreach(asm_v, assemblies)
{
fx_assembly *assembly = NULL;
fx_value_get_object(asm_v, &assembly);
fx_iterator *types = fx_assembly_get_types(assembly);
fx_foreach(v, types)
{ {
fx_type *ty = NULL; fx_type *ty = NULL;
fx_value_get_object(&v, &ty); fx_value_get_object(v, &ty);
const char *ty_name = fx_type_get_name(ty); if (fx_type_id_compare(
fx_type_get_id(ty),
BSHELL_TYPE_COMMAND)
== 0) {
continue;
}
bshell_command_class *cmd = fx_type_get_interface( bshell_command_class *cmd = fx_type_get_interface(
ty, ty,
BSHELL_TYPE_COMMAND); BSHELL_TYPE_COMMAND);
@@ -174,12 +200,19 @@ bshell_command *bshell_command_find_static(const char *name)
if (!fx_strcmp_nocase( if (!fx_strcmp_nocase(
fx_string_get_cstr(call_name), fx_string_get_cstr(call_name),
fx_string_get_cstr(target_name))) { fx_string_get_cstr(target_name))) {
return fx_object_create(fx_type_get_id(ty)); result = fx_object_create(fx_type_get_id(ty));
break;
} }
} }
fx_iterator_unref(it);
return NULL; fx_iterator_unref(types);
}
fx_iterator_unref(assemblies);
fx_string_unref(call_name);
fx_string_unref(target_name);
return result;
} }
void bshell_command_set_args( void bshell_command_set_args(
@@ -217,14 +250,25 @@ const fx_value *bshell_command_get_arg(bshell_command *cmd, size_t index)
index); index);
} }
enum bshell_status bshell_command_begin_processing(bshell_command *command) size_t bshell_command_get_arg_count(const bshell_command *cmd)
{ {
FX_CLASS_DISPATCH_VIRTUAL_0( FX_CLASS_DISPATCH_STATIC_0(
BSHELL_TYPE_COMMAND,
command_get_arg_count,
cmd);
}
enum bshell_status bshell_command_begin_processing(
bshell_command *command,
enum bshell_command_position position)
{
FX_CLASS_DISPATCH_VIRTUAL(
bshell_command, bshell_command,
BSHELL_TYPE_COMMAND, BSHELL_TYPE_COMMAND,
BSHELL_ERR_NOT_SUPPORTED, BSHELL_ERR_NOT_SUPPORTED,
c_begin_processing, c_begin_processing,
command); command,
position);
} }
enum bshell_status bshell_command_process_record( enum bshell_status bshell_command_process_record(
@@ -265,8 +309,10 @@ FX_TYPE_CLASS_END(bshell_command)
FX_TYPE_DEFINITION_BEGIN(bshell_command) FX_TYPE_DEFINITION_BEGIN(bshell_command)
FX_TYPE_ID(0x5c50630d, 0x7535, 0x40ed, 0xbae5, 0x88aabc274d79); FX_TYPE_ID(0x5c50630d, 0x7535, 0x40ed, 0xbae5, 0x88aabc274d79);
FX_TYPE_NAME("bshell.command"); FX_TYPE_FLAGS(FX_TYPE_F_ABSTRACT);
FX_TYPE_NAME("bshell.runtime.command");
FX_TYPE_CLASS(bshell_command_class); FX_TYPE_CLASS(bshell_command_class);
FX_TYPE_INSTANCE_INIT(init); FX_TYPE_INSTANCE_INIT(init);
FX_TYPE_INSTANCE_FINI(fini);
FX_TYPE_INSTANCE_PRIVATE(struct bshell_command_p); FX_TYPE_INSTANCE_PRIVATE(struct bshell_command_p);
FX_TYPE_DEFINITION_END(bshell_command) FX_TYPE_DEFINITION_END(bshell_command)
+200
View File
@@ -0,0 +1,200 @@
#include <bshell/command/command.h>
#include <bshell/command/function.h>
#include <bshell/runtime/pipeline.h>
#include <bshell/runtime/runtime.h>
#include <bshell/runtime/scope.h>
#include <bshell/runtime/script-block.h>
#include <bshell/status.h>
#include <fx/collections/array.h>
#include <fx/reflection/function.h>
#include <fx/string.h>
#include <fx/vector.h>
struct bshell_function_p {
char *func_name;
fx_array *func_positional_params;
bshell_scriptblock *func_body;
};
static void init(fx_object *obj, void *priv)
{
struct bshell_function_p *func_p = priv;
func_p->func_positional_params = fx_array_create();
func_p->func_body = bshell_scriptblock_create();
}
static void fini(fx_object *obj, void *priv)
{
struct bshell_function_p *func_p = priv;
if (func_p->func_name) {
free(func_p->func_name);
}
fx_array_unref(func_p->func_positional_params);
bshell_scriptblock_unref(func_p->func_body);
}
static enum bshell_status get_callable_name(
const bshell_function *func,
fx_string *out)
{
struct bshell_function_p *func_p
= fx_object_get_private(func, BSHELL_TYPE_FUNCTION);
fx_string_append_cstrf(out, "%s", func_p->func_name);
return BSHELL_SUCCESS;
}
static enum bshell_status begin_processing(
bshell_command *cmd,
enum bshell_command_position position)
{
return BSHELL_SUCCESS;
}
static enum bshell_status process_record(
bshell_command *cmd,
bshell_pipeline *pipeline,
struct bshell_runtime *rt)
{
struct bshell_function_p *func_p
= fx_object_get_private(cmd, BSHELL_TYPE_FUNCTION);
bshell_runtime_push_scope(rt, func_p->func_body);
const fx_iterator *param_it
= fx_iterator_begin(func_p->func_positional_params);
size_t i = 1;
fx_foreach(v, param_it)
{
fx_string *param = NULL;
fx_value_get_object(v, &param);
const fx_value *arg = bshell_command_get_arg(cmd, i);
if (!arg) {
break;
}
bshell_variable *var = bshell_runtime_scope_define_variable(
bshell_runtime_get_current_scope(rt),
fx_string_get_cstr(param));
bshell_variable_set_value(var, *arg);
}
fx_iterator_unref(param_it);
#if 0
bshell_variable *item = bshell_runtime_define_var(rt, "_");
bshell_variable_set_value(item, &in);
#endif
fx_value out = bshell_runtime_eval(rt);
bshell_runtime_pop_scope(rt);
if (fx_value_is_set(&out)) {
bshell_pipeline_write_value(pipeline, out, false);
fx_value_unset(&out);
}
return BSHELL_SUCCESS;
}
static enum bshell_status end_processing(bshell_command *cmd)
{
return BSHELL_SUCCESS;
}
bshell_function *bshell_function_create(const char *name)
{
bshell_function *out = fx_object_create(BSHELL_TYPE_FUNCTION);
if (!out) {
return NULL;
}
struct bshell_function_p *func
= fx_object_get_private(out, BSHELL_TYPE_FUNCTION);
func->func_name = fx_strdup(name);
if (!func->func_name) {
bshell_function_unref(out);
return NULL;
}
return out;
}
void bshell_function_add_positional_parameter(
bshell_function *func,
const char *name)
{
fx_string *str = fx_string_create_from_cstr(name);
if (!str) {
return;
}
struct bshell_function_p *func_p
= fx_object_get_private(func, BSHELL_TYPE_FUNCTION);
fx_array_push_back(
func_p->func_positional_params,
FX_VALUE_OBJECT(str));
fx_string_unref(str);
}
static const char *function_get_name(const struct bshell_function_p *func)
{
return func->func_name;
}
static const fx_array *function_get_positional_parameters(
const struct bshell_function_p *func)
{
return func->func_positional_params;
}
static bshell_scriptblock *function_get_body(struct bshell_function_p *func)
{
return func->func_body;
}
const char *bshell_function_get_name(const bshell_function *func)
{
FX_CLASS_DISPATCH_STATIC_0(
BSHELL_TYPE_FUNCTION,
function_get_name,
func);
}
const fx_array *bshell_function_get_positional_parameters(
const bshell_function *func)
{
FX_CLASS_DISPATCH_STATIC_0(
BSHELL_TYPE_FUNCTION,
function_get_positional_parameters,
func);
}
bshell_scriptblock *bshell_function_get_body(bshell_function *func)
{
FX_CLASS_DISPATCH_STATIC_0(
BSHELL_TYPE_FUNCTION,
function_get_body,
func);
}
FX_TYPE_CLASS_BEGIN(bshell_function)
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
FX_INTERFACE_ENTRY(to_string) = NULL;
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
FX_INTERFACE_ENTRY(c_command_type) = "Function";
FX_INTERFACE_ENTRY(c_get_callable_name) = get_callable_name;
FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing;
FX_INTERFACE_ENTRY(c_process_record) = process_record;
FX_INTERFACE_ENTRY(c_end_processing) = end_processing;
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
FX_TYPE_CLASS_END(bshell_function)
FX_TYPE_DEFINITION_BEGIN(bshell_function)
FX_TYPE_ID(0x041f1918, 0x6155, 0x4cee, 0xbb01, 0xfef2d6aa1bcf);
FX_TYPE_NAME("bshell.runtime.function");
FX_TYPE_EXTENDS(BSHELL_TYPE_COMMAND);
FX_TYPE_CLASS(bshell_function_class);
FX_TYPE_INSTANCE_INIT(init);
FX_TYPE_INSTANCE_FINI(fini);
FX_TYPE_INSTANCE_PRIVATE(struct bshell_function_p);
FX_TYPE_DEFINITION_END(bshell_function)
+235
View File
@@ -0,0 +1,235 @@
#if BSHELL_ENABLE_NATIVE_COMMANDS == 1
#include <bshell/command/command.h>
#include <bshell/command/native-command.h>
#include <bshell/format.h>
#include <bshell/runtime/pipeline.h>
#include <bshell/status.h>
#include <fx/diagnostics/process.h>
#include <fx/reflection/function.h>
#include <fx/string.h>
#include <fx/vector.h>
enum {
F_REDIRECT_STDIN = 0x01u,
F_REDIRECT_STDOUT = 0x02u,
};
struct bshell_native_command_p {
int cmd_flags;
fx_string *cmd_path;
fx_stringstream *cmd_tmp;
fx_process *cmd_proc;
struct bshell_value_writer cmd_writer;
bool cmd_writer_init;
};
static void init(fx_object *obj, void *priv)
{
struct bshell_native_command_p *cmd_p = priv;
cmd_p->cmd_tmp = fx_stringstream_create();
}
static void fini(fx_object *obj, void *priv)
{
struct bshell_native_command_p *cmd_p = priv;
fx_stringstream_unref(cmd_p->cmd_tmp);
fx_string_unref(cmd_p->cmd_path);
}
static enum bshell_status start_process(bshell_native_command *cmd, int flags)
{
struct bshell_native_command_p *cmd_p
= fx_object_get_private(cmd, BSHELL_TYPE_NATIVE_COMMAND);
fx_stringstream *tmp = fx_stringstream_create();
size_t argc = bshell_command_get_arg_count(cmd);
char **argv = calloc(argc, sizeof *argv);
for (size_t i = 0; i < argc; i++) {
const fx_value *arg = bshell_command_get_arg(cmd, i);
fx_stringstream_reset(tmp);
fx_value_to_string(arg, tmp, NULL);
argv[i] = fx_stringstream_steal(tmp);
}
fx_stringstream_unref(tmp);
fx_process *self = fx_process_get_self();
fx_process_start_info info = {
.proc_args = (const char **)argv,
.proc_args_count = argc,
.proc_file_name = fx_string_get_cstr(cmd_p->cmd_path),
.proc_environment = fx_process_get_environment(self),
};
if (flags & F_REDIRECT_STDIN) {
info.proc_redirect_stdin = true;
}
if (flags & F_REDIRECT_STDOUT) {
info.proc_redirect_stdout = true;
}
cmd_p->cmd_flags = flags;
cmd_p->cmd_proc = fx_process_create(&info);
fx_status status = fx_process_start(cmd_p->cmd_proc);
for (size_t i = 0; i < argc; i++) {
free(argv[i]);
}
free(argv);
if (!FX_OK(status)) {
return BSHELL_ERR_NO_MEMORY;
}
return BSHELL_SUCCESS;
}
static enum bshell_status begin_processing(
bshell_command *cmd,
enum bshell_command_position position)
{
struct bshell_native_command_p *cmd_p
= fx_object_get_private(cmd, BSHELL_TYPE_NATIVE_COMMAND);
int flags = 0;
switch (position) {
case BSHELL_COMMAND_POSITION_BEGINNING:
flags = F_REDIRECT_STDOUT;
break;
case BSHELL_COMMAND_POSITION_MIDDLE:
flags = F_REDIRECT_STDIN | F_REDIRECT_STDOUT;
break;
case BSHELL_COMMAND_POSITION_END:
flags = F_REDIRECT_STDIN;
break;
default:
break;
}
return start_process(cmd, flags);
}
static enum bshell_status process_record(
bshell_command *cmd,
bshell_pipeline *pipeline,
struct bshell_runtime *rt)
{
struct bshell_native_command_p *cmd_p
= fx_object_get_private(cmd, BSHELL_TYPE_NATIVE_COMMAND);
if (cmd_p->cmd_flags & F_REDIRECT_STDIN) {
fx_value in = bshell_pipeline_read_value(pipeline);
if (!fx_value_is_set(&in)) {
return BSHELL_SUCCESS;
}
fx_stream *in_stream = fx_process_get_stdin(cmd_p->cmd_proc);
if (!cmd_p->cmd_writer_init) {
bshell_value_writer_init(
&cmd_p->cmd_writer,
0,
0,
in_stream);
cmd_p->cmd_writer_init = true;
}
bshell_value_writer_write(&cmd_p->cmd_writer, &in);
fx_value_unset(&in);
}
if (cmd_p->cmd_flags & F_REDIRECT_STDOUT) {
fx_stream *out_stream = fx_process_get_stdout(cmd_p->cmd_proc);
fx_stringstream_reset(cmd_p->cmd_tmp);
fx_status status
= fx_stream_read_line_s(out_stream, cmd_p->cmd_tmp);
if (!FX_OK(status)) {
/* no more data available */
return BSHELL_SUCCESS;
}
fx_string *record = fx_string_create_from_cstr(
fx_stringstream_get_cstr(cmd_p->cmd_tmp));
bshell_pipeline_write_value(
pipeline,
FX_VALUE_OBJECT(record),
false);
fx_string_unref(record);
}
return BSHELL_SUCCESS;
}
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);
if (cmd_p->cmd_writer_init) {
bshell_value_writer_cleanup(&cmd_p->cmd_writer);
cmd_p->cmd_writer_init = false;
}
if (cmd_p->cmd_proc) {
fx_process_close_stdin(cmd_p->cmd_proc);
fx_process_close_stdout(cmd_p->cmd_proc);
fx_process_close_stderr(cmd_p->cmd_proc);
int result = 0;
fx_process_wait(cmd_p->cmd_proc, &result);
fx_process_unref(cmd_p->cmd_proc);
cmd_p->cmd_proc = NULL;
}
return BSHELL_SUCCESS;
}
static enum bshell_status get_callable_name(
const bshell_native_command *cmd,
fx_string *out)
{
struct bshell_native_command_p *cmd_p
= fx_object_get_private(cmd, BSHELL_TYPE_NATIVE_COMMAND);
fx_string_append_s(out, cmd_p->cmd_path);
return BSHELL_SUCCESS;
}
bshell_native_command *bshell_native_command_create(const char *path)
{
bshell_native_command *out
= fx_object_create(BSHELL_TYPE_NATIVE_COMMAND);
if (!out) {
return NULL;
}
struct bshell_native_command_p *cmd
= fx_object_get_private(out, BSHELL_TYPE_NATIVE_COMMAND);
cmd->cmd_path = fx_string_create_from_cstr(path);
return out;
}
FX_TYPE_CLASS_BEGIN(bshell_native_command)
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
FX_INTERFACE_ENTRY(to_string) = NULL;
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
FX_TYPE_VTABLE_INTERFACE_BEGIN(bshell_command, BSHELL_TYPE_COMMAND)
FX_INTERFACE_ENTRY(c_command_type) = "Native-Command";
FX_INTERFACE_ENTRY(c_get_callable_name) = get_callable_name;
FX_INTERFACE_ENTRY(c_begin_processing) = begin_processing;
FX_INTERFACE_ENTRY(c_process_record) = process_record;
FX_INTERFACE_ENTRY(c_end_processing) = end_processing;
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
FX_TYPE_CLASS_END(bshell_native_command)
FX_TYPE_DEFINITION_BEGIN(bshell_native_command)
FX_TYPE_ID(0x720ede87, 0xe586, 0x495a, 0xa229, 0x1505c01b5714);
FX_TYPE_FLAGS(FX_TYPE_F_ABSTRACT);
FX_TYPE_NAME("bshell.runtime.native_command");
FX_TYPE_EXTENDS(BSHELL_TYPE_COMMAND);
FX_TYPE_CLASS(bshell_native_command_class);
FX_TYPE_INSTANCE_INIT(init);
FX_TYPE_INSTANCE_FINI(fini);
FX_TYPE_INSTANCE_PRIVATE(struct bshell_native_command_p);
FX_TYPE_DEFINITION_END(bshell_native_command)
#endif
@@ -5,9 +5,10 @@ static const struct compile_value_type array_item_type = {};
struct compile_result compile_array( struct compile_result compile_array(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
struct array_ast_node *array = (struct array_ast_node *)src; struct bshell_array_ast_node *array;
array = (struct bshell_array_ast_node *)src;
size_t nr_items = fx_queue_length(&array->n_items); size_t nr_items = fx_queue_length(&array->n_items);
for (size_t i = 0; i < nr_items; i++) { for (size_t i = 0; i < nr_items; i++) {
struct compile_value *item = compile_pop_value(ctx); struct compile_value *item = compile_pop_value(ctx);
@@ -17,7 +18,7 @@ struct compile_result compile_array(
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_MK_ARRAY, BSHELL_OPCODE_MK_ARRAY,
nr_items); nr_items);
compile_push_value(ctx, &array_type, src); compile_push_value(ctx, &array_type, src);
return COMPILE_OK(0); return COMPILE_OK(0);
@@ -1,6 +1,6 @@
#include "../compile.h"
#include "compile-node.h" #include "compile-node.h"
#include <bshell/compile.h>
#include <stdio.h> #include <stdio.h>
static enum bshell_status block_load( static enum bshell_status block_load(
@@ -9,7 +9,7 @@ static enum bshell_status block_load(
{ {
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_LDBLOCK, BSHELL_OPCODE_LDBLOCK,
value->v_pool); value->v_pool);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -20,7 +20,7 @@ static const struct compile_value_type block_type = {
struct compile_result compile_block( struct compile_result compile_block(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
bshell_scriptblock *sub_block = bshell_scriptblock_create(); bshell_scriptblock *sub_block = bshell_scriptblock_create();
if (!sub_block) { if (!sub_block) {
@@ -45,14 +45,18 @@ struct compile_result compile_block(
enum bshell_status compile_block_immediate( enum bshell_status compile_block_immediate(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
enum bshell_status status = BSHELL_SUCCESS; enum bshell_status status = BSHELL_SUCCESS;
struct block_ast_node *block = (struct block_ast_node *)src; struct bshell_block_ast_node *block = (struct bshell_block_ast_node *)
src;
fx_queue_entry *cur = fx_queue_first(&block->n_statements); fx_queue_entry *cur = fx_queue_first(&block->n_statements);
while (cur && status == BSHELL_SUCCESS) { while (cur && status == BSHELL_SUCCESS) {
struct ast_node *node = fx_unbox(struct ast_node, cur, n_entry); struct bshell_ast_node *node = fx_unbox(
struct bshell_ast_node,
cur,
n_entry);
status = compile_node(ctx, node); status = compile_node(ctx, node);
cur = fx_queue_next(cur); cur = fx_queue_next(cur);
} }
@@ -4,9 +4,12 @@ enum bshell_status cmdcall_load(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct cmdcall_ast_node *cmdcall = (struct cmdcall_ast_node *) struct bshell_cmdcall_ast_node *cmdcall;
value->v_node; cmdcall = (struct bshell_cmdcall_ast_node *)value->v_node;
bshell_scriptblock_push_instruction(ctx->c_block, OPCODE_PEXEC, 1); bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_PEXEC,
1);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -14,12 +17,12 @@ enum bshell_status pipeline_load(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct pipeline_ast_node *pipeline = (struct pipeline_ast_node *) struct bshell_pipeline_ast_node *pipeline;
value->v_node; pipeline = (struct bshell_pipeline_ast_node *)value->v_node;
size_t nr_items = fx_queue_length(&pipeline->n_stages); size_t nr_items = fx_queue_length(&pipeline->n_stages);
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_PEXEC, BSHELL_OPCODE_PEXEC,
nr_items); nr_items);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -34,9 +37,10 @@ static const struct compile_value_type pipeline_type = {
struct compile_result compile_cmdcall( struct compile_result compile_cmdcall(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
struct cmdcall_ast_node *cmdcall = (struct cmdcall_ast_node *)src; struct bshell_cmdcall_ast_node *cmdcall;
cmdcall = (struct bshell_cmdcall_ast_node *)src;
size_t nr_args = fx_queue_length(&cmdcall->n_args); size_t nr_args = fx_queue_length(&cmdcall->n_args);
for (size_t i = 0; i < nr_args; i++) { for (size_t i = 0; i < nr_args; i++) {
struct compile_value *arg = compile_pop_value(ctx); struct compile_value *arg = compile_pop_value(ctx);
@@ -46,7 +50,7 @@ struct compile_result compile_cmdcall(
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_LDCMD, BSHELL_OPCODE_LDCMD,
nr_args); nr_args);
compile_push_value(ctx, &cmdcall_type, src); compile_push_value(ctx, &cmdcall_type, src);
@@ -55,13 +59,14 @@ struct compile_result compile_cmdcall(
struct compile_result compile_pipeline( struct compile_result compile_pipeline(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
struct pipeline_ast_node *pipeline = (struct pipeline_ast_node *)src; struct bshell_pipeline_ast_node *pipeline;
pipeline = (struct bshell_pipeline_ast_node *)src;
size_t nr_items = fx_queue_length(&pipeline->n_stages); size_t nr_items = fx_queue_length(&pipeline->n_stages);
for (size_t i = 0; i < nr_items; i++) { for (size_t i = 0; i < nr_items; i++) {
struct compile_value *item = compile_pop_value(ctx); struct compile_value *item = compile_pop_value(ctx);
if (item->v_node->n_type != AST_CMDCALL) { if (item->v_node->n_type != BSHELL_AST_CMDCALL) {
compile_value_load(ctx, item); compile_value_load(ctx, item);
} }
compile_value_destroy(item); compile_value_destroy(item);
@@ -1,11 +1,11 @@
#ifndef COMPILE_COMPILE_NODE_H_ #ifndef COMPILE_COMPILE_NODE_H_
#define COMPILE_COMPILE_NODE_H_ #define COMPILE_COMPILE_NODE_H_
#include "../ast/ast.h" #include <bshell/ast.h>
#include "../operator.h" #include <bshell/parse/token.h>
#include "../parse/token.h" #include <bshell/runtime/operator.h>
#include "../script-block.h" #include <bshell/runtime/script-block.h>
#include <bshell/status.h>
#include <fx/queue.h> #include <fx/queue.h>
#include <fx/vector.h> #include <fx/vector.h>
@@ -27,7 +27,7 @@ struct compile_result {
typedef struct compile_result (*compile_begin_impl)(struct compile_ctx *); typedef struct compile_result (*compile_begin_impl)(struct compile_ctx *);
typedef struct compile_result (*compile_end_impl)(struct compile_ctx *); typedef struct compile_result (*compile_end_impl)(struct compile_ctx *);
typedef struct compile_result ( typedef struct compile_result (
*compile_node_impl)(struct compile_ctx *, struct ast_node *); *compile_node_impl)(struct compile_ctx *, struct bshell_ast_node *);
enum compile_state_type_id { enum compile_state_type_id {
COMPILE_NORMAL = 0, COMPILE_NORMAL = 0,
@@ -43,11 +43,11 @@ struct compile_value_type {
struct compile_value { struct compile_value {
const struct compile_value_type *v_type; const struct compile_value_type *v_type;
enum operator_id v_op; enum bshell_operator_id v_op;
struct compile_value *v_left, *v_right; struct compile_value *v_left, *v_right;
struct compile_value **v_args; struct compile_value **v_args;
size_t v_nr_args; size_t v_nr_args;
struct ast_node *v_node; struct bshell_ast_node *v_node;
unsigned long v_pool; unsigned long v_pool;
fx_queue_entry v_entry; fx_queue_entry v_entry;
}; };
@@ -94,11 +94,11 @@ extern struct compile_state *compile_get_state(const struct compile_ctx *ctx);
extern enum bshell_status compile_push_value( extern enum bshell_status compile_push_value(
struct compile_ctx *ctx, struct compile_ctx *ctx,
const struct compile_value_type *type, const struct compile_value_type *type,
struct ast_node *node); struct bshell_ast_node *node);
extern enum bshell_status compile_push_value_array( extern enum bshell_status compile_push_value_array(
struct compile_ctx *ctx, struct compile_ctx *ctx,
const struct compile_value_type *type, const struct compile_value_type *type,
struct ast_node *node, struct bshell_ast_node *node,
struct compile_value **values, struct compile_value **values,
size_t nr_values); size_t nr_values);
extern enum bshell_status compile_push_pool_value( extern enum bshell_status compile_push_pool_value(
@@ -107,9 +107,9 @@ extern enum bshell_status compile_push_pool_value(
unsigned long pool_slot); unsigned long pool_slot);
extern enum bshell_status compile_push_op( extern enum bshell_status compile_push_op(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *node, struct bshell_ast_node *node,
const struct compile_value_type *type, const struct compile_value_type *type,
enum operator_id op, enum bshell_operator_id op,
struct compile_value *left, struct compile_value *left,
struct compile_value *right); struct compile_value *right);
extern struct compile_value *compile_pop_value(struct compile_ctx *ctx); extern struct compile_value *compile_pop_value(struct compile_ctx *ctx);
@@ -128,60 +128,60 @@ extern enum bshell_status compile_resolve_labels(struct compile_ctx *ctx);
extern struct compile_result compile_int( extern struct compile_result compile_int(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_double( extern struct compile_result compile_double(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_string( extern struct compile_result compile_string(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_word( extern struct compile_result compile_word(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_op( extern struct compile_result compile_op(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_var( extern struct compile_result compile_var(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_fstring( extern struct compile_result compile_fstring(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_array( extern struct compile_result compile_array(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_hashtable_item( extern struct compile_result compile_hashtable_item(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_hashtable( extern struct compile_result compile_hashtable(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_block( extern struct compile_result compile_block(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_cmdcall( extern struct compile_result compile_cmdcall(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern struct compile_result compile_pipeline( extern struct compile_result compile_pipeline(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern enum bshell_status compile_if( extern enum bshell_status compile_if(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern enum bshell_status compile_block_immediate( extern enum bshell_status compile_block_immediate(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern enum bshell_status compile_expression( extern enum bshell_status compile_expression(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
extern enum bshell_status compile_node( extern enum bshell_status compile_node(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src); struct bshell_ast_node *src);
#endif #endif
@@ -1,20 +1,17 @@
#include "../compile.h"
#include "../ast/ast.h"
#include "../debug.h"
#include "../status.h"
#include "compile-node.h" #include "compile-node.h"
#include <stdio.h> #include <bshell/ast.h>
#include <bshell/compile.h>
#include <bshell/status.h>
extern enum bshell_status compile_node( extern enum bshell_status compile_node(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
switch (src->n_type) { switch (src->n_type) {
case AST_IF: case BSHELL_AST_IF:
return compile_if(ctx, src); return compile_if(ctx, src);
case AST_BLOCK: case BSHELL_AST_BLOCK:
return compile_block_immediate(ctx, src); return compile_block_immediate(ctx, src);
default: default:
return compile_expression(ctx, src); return compile_expression(ctx, src);
@@ -24,7 +21,7 @@ extern enum bshell_status compile_node(
} }
enum bshell_status bshell_compile( enum bshell_status bshell_compile(
struct ast_node *src, struct bshell_ast_node *src,
bshell_scriptblock *dest) bshell_scriptblock *dest)
{ {
struct compile_ctx ctx = {.c_block = dest}; struct compile_ctx ctx = {.c_block = dest};
@@ -35,6 +32,16 @@ enum bshell_status bshell_compile(
} }
status = compile_resolve_labels(&ctx); status = compile_resolve_labels(&ctx);
while (!fx_queue_empty(&ctx.c_state)) {
compile_pop_state(&ctx);
}
while (!fx_queue_empty(&ctx.c_stack)) {
struct compile_value *value = compile_pop_value(&ctx);
compile_value_destroy(value);
}
if (status != BSHELL_SUCCESS) { if (status != BSHELL_SUCCESS) {
return status; return status;
} }
@@ -4,10 +4,11 @@ enum bshell_status int_load(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct int_ast_node *i = (struct int_ast_node *)value->v_node; struct bshell_int_ast_node *i
= (struct bshell_int_ast_node *)value->v_node;
long long v; long long v;
fx_value_get_longlong(&i->n_value->tok_number, &v); fx_value_get_longlong(&i->n_value->tok_number, &v);
bshell_scriptblock_push_instruction(ctx->c_block, OPCODE_LDC_INT, v); bshell_scriptblock_push_instruction(ctx->c_block, BSHELL_OPCODE_LDC_INT, v);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -15,11 +16,12 @@ enum bshell_status double_load(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct double_ast_node *d = (struct double_ast_node *)value->v_node; struct bshell_double_ast_node *d
= (struct bshell_double_ast_node *)value->v_node;
double v; double v;
fx_value_get_double(&d->n_value->tok_number, &v); fx_value_get_double(&d->n_value->tok_number, &v);
unsigned long index = bshell_scriptblock_get_double(ctx->c_block, v); unsigned long index = bshell_scriptblock_get_double(ctx->c_block, v);
bshell_scriptblock_push_instruction(ctx->c_block, OPCODE_LDC_FP, index); bshell_scriptblock_push_instruction(ctx->c_block, BSHELL_OPCODE_LDC_FP, index);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -27,7 +29,8 @@ enum bshell_status string_load(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct string_ast_node *s = (struct string_ast_node *)value->v_node; struct bshell_string_ast_node *s
= (struct bshell_string_ast_node *)value->v_node;
unsigned long index = bshell_scriptblock_get_string( unsigned long index = bshell_scriptblock_get_string(
ctx->c_block, ctx->c_block,
s->n_value->tok_str); s->n_value->tok_str);
@@ -37,7 +40,7 @@ enum bshell_status string_load(
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_LDC_STR, BSHELL_OPCODE_LDC_STR,
index); index);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -46,7 +49,8 @@ enum bshell_status word_load(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct word_ast_node *s = (struct word_ast_node *)value->v_node; struct bshell_word_ast_node *s
= (struct bshell_word_ast_node *)value->v_node;
unsigned long index = bshell_scriptblock_get_string( unsigned long index = bshell_scriptblock_get_string(
ctx->c_block, ctx->c_block,
s->n_value->tok_str); s->n_value->tok_str);
@@ -56,7 +60,7 @@ enum bshell_status word_load(
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_LDC_STR, BSHELL_OPCODE_LDC_STR,
index); index);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -77,7 +81,9 @@ static const struct compile_value_type word_type = {
.v_load = word_load, .v_load = word_load,
}; };
struct compile_result compile_int(struct compile_ctx *ctx, struct ast_node *src) struct compile_result compile_int(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{ {
compile_push_value(ctx, &int_type, src); compile_push_value(ctx, &int_type, src);
return COMPILE_OK(0); return COMPILE_OK(0);
@@ -85,7 +91,7 @@ struct compile_result compile_int(struct compile_ctx *ctx, struct ast_node *src)
struct compile_result compile_double( struct compile_result compile_double(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
compile_push_value(ctx, &double_type, src); compile_push_value(ctx, &double_type, src);
return COMPILE_OK(0); return COMPILE_OK(0);
@@ -93,7 +99,7 @@ struct compile_result compile_double(
struct compile_result compile_string( struct compile_result compile_string(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
compile_push_value(ctx, &string_type, src); compile_push_value(ctx, &string_type, src);
return COMPILE_OK(0); return COMPILE_OK(0);
@@ -101,7 +107,7 @@ struct compile_result compile_string(
struct compile_result compile_word( struct compile_result compile_word(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
compile_push_value(ctx, &word_type, src); compile_push_value(ctx, &word_type, src);
return COMPILE_OK(0); return COMPILE_OK(0);
@@ -1,22 +1,22 @@
#include "compile-node.h" #include "compile-node.h"
static struct ast_iterate_result do_compile_node( static struct bshell_ast_iterate_result do_compile_node(
struct ast_node *node, struct bshell_ast_node *node,
enum ast_iteration_type it_type, enum bshell_ast_iteration_type it_type,
struct ast_iterator *it, struct bshell_ast_iterator *it,
struct compile_ctx *ctx) struct compile_ctx *ctx)
{ {
if (it_type != AST_ITERATION_POST) { if (it_type != BSHELL_AST_ITERATION_POST) {
int flags = 0; int flags = 0;
switch (node->n_type) { switch (node->n_type) {
case AST_BLOCK: case BSHELL_AST_BLOCK:
break; break;
default: default:
flags |= AST_ITERATE_ADD_CHILDREN; flags |= BSHELL_AST_ITERATE_ADD_CHILDREN;
break; break;
} }
return AST_ITERATE_OK(flags); return BSHELL_AST_ITERATE_OK(flags);
} }
ctx->c_depth = node->n_it.e_depth; ctx->c_depth = node->n_it.e_depth;
@@ -37,30 +37,34 @@ static struct ast_iterate_result do_compile_node(
} }
if (!impl) { if (!impl) {
return AST_ITERATE_OK(0); return BSHELL_AST_ITERATE_OK(0);
} }
struct compile_result result = impl(ctx, node); struct compile_result result = impl(ctx, node);
unsigned int flags = 0; unsigned int flags = 0;
if (result.r_flags & COMPILE_REPEAT_NODE) { if (result.r_flags & COMPILE_REPEAT_NODE) {
flags |= AST_ITERATE_REPEAT; flags |= BSHELL_AST_ITERATE_REPEAT;
} }
if (result.r_status == BSHELL_SUCCESS) { if (result.r_status == BSHELL_SUCCESS) {
return AST_ITERATE_OK(flags); return BSHELL_AST_ITERATE_OK(flags);
} }
return AST_ITERATE_ERR(result.r_status); return BSHELL_AST_ITERATE_ERR(result.r_status);
} }
enum bshell_status compile_expression( enum bshell_status compile_expression(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
compile_push_state(ctx, COMPILE_NORMAL); compile_push_state(ctx, COMPILE_NORMAL);
struct ast_iterator it = {0}; struct bshell_ast_iterator it = {0};
ast_node_iterate(src, &it, (ast_iterator_callback)do_compile_node, ctx); bshell_ast_node_iterate(
src,
&it,
(bshell_ast_iterator_callback)do_compile_node,
ctx);
struct compile_value *result = compile_pop_value(ctx); struct compile_value *result = compile_pop_value(ctx);
if (result) { if (result) {
@@ -68,5 +72,6 @@ enum bshell_status compile_expression(
compile_value_destroy(result); compile_value_destroy(result);
} }
compile_pop_state(ctx);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -4,15 +4,15 @@ enum bshell_status fstring_load(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct fstring_ast_node *fstring = (struct fstring_ast_node *) struct bshell_fstring_ast_node *fstring
value->v_node; = (struct bshell_fstring_ast_node *)value->v_node;
for (size_t i = 0; i < value->v_nr_args; i++) { for (size_t i = 0; i < value->v_nr_args; i++) {
compile_value_load(ctx, value->v_args[i]); compile_value_load(ctx, value->v_args[i]);
} }
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_MK_STR, BSHELL_OPCODE_MK_STR,
fx_queue_length(&fstring->n_elements)); fx_queue_length(&fstring->n_elements));
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -23,9 +23,10 @@ static const struct compile_value_type fstring_type = {
struct compile_result compile_fstring( struct compile_result compile_fstring(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
struct fstring_ast_node *fstring = (struct fstring_ast_node *)src; struct bshell_fstring_ast_node *fstring
= (struct bshell_fstring_ast_node *)src;
size_t nr_items = fx_queue_length(&fstring->n_elements); size_t nr_items = fx_queue_length(&fstring->n_elements);
struct compile_value **items = calloc(nr_items, sizeof *items); struct compile_value **items = calloc(nr_items, sizeof *items);
+39
View File
@@ -0,0 +1,39 @@
#include <bshell/ast.h>
#include <bshell/compile.h>
#include <bshell/parse/token.h>
#include <bshell/status.h>
enum bshell_status bshell_compile_function(
struct bshell_ast_node *src,
bshell_function **out)
{
struct bshell_func_ast_node *func_ast
= (struct bshell_func_ast_node *)src;
bshell_function *func
= bshell_function_create(func_ast->n_name->tok_str);
if (!func) {
return BSHELL_ERR_NO_MEMORY;
}
fx_queue_entry *cur = fx_queue_first(&func_ast->n_params);
while (cur) {
struct bshell_var_ast_node *var_ast = fx_unbox(
struct bshell_var_ast_node,
cur,
n_base.n_entry);
bshell_function_add_positional_parameter(
func,
var_ast->n_ident->tok_str);
cur = fx_queue_next(cur);
}
bshell_scriptblock *body = bshell_function_get_body(func);
enum bshell_status status = bshell_compile(func_ast->n_body, body);
if (status != BSHELL_SUCCESS) {
bshell_function_unref(func);
return status;
}
*out = func;
return BSHELL_SUCCESS;
}
@@ -5,9 +5,10 @@ static const struct compile_value_type hashtable_item_type = {};
struct compile_result compile_hashtable( struct compile_result compile_hashtable(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
struct hashtable_ast_node *hashtable = (struct hashtable_ast_node *)src; struct bshell_hashtable_ast_node *hashtable
= (struct bshell_hashtable_ast_node *)src;
size_t nr_items = fx_queue_length(&hashtable->n_items); size_t nr_items = fx_queue_length(&hashtable->n_items);
for (size_t i = 0; i < nr_items; i++) { for (size_t i = 0; i < nr_items; i++) {
struct compile_value *item = compile_pop_value(ctx); struct compile_value *item = compile_pop_value(ctx);
@@ -17,7 +18,7 @@ struct compile_result compile_hashtable(
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_MK_HTAB, BSHELL_OPCODE_MK_HTAB,
nr_items); nr_items);
compile_push_value(ctx, &hashtable_type, src); compile_push_value(ctx, &hashtable_type, src);
return COMPILE_OK(0); return COMPILE_OK(0);
@@ -25,7 +26,7 @@ struct compile_result compile_hashtable(
struct compile_result compile_hashtable_item( struct compile_result compile_hashtable_item(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *src) struct bshell_ast_node *src)
{ {
struct compile_value *value = compile_pop_value(ctx); struct compile_value *value = compile_pop_value(ctx);
struct compile_value *key = compile_pop_value(ctx); struct compile_value *key = compile_pop_value(ctx);
@@ -1,8 +1,11 @@
#include "compile-node.h" #include "compile-node.h"
enum bshell_status compile_if(struct compile_ctx *ctx, struct ast_node *src) enum bshell_status compile_if(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{ {
struct if_ast_node *if_group = (struct if_ast_node *)src; struct bshell_if_ast_node *if_group;
if_group = (struct bshell_if_ast_node *)src;
size_t nr_labels = fx_queue_length(&if_group->n_branches); size_t nr_labels = fx_queue_length(&if_group->n_branches);
// add one extra label for the end of the if group // add one extra label for the end of the if group
nr_labels++; nr_labels++;
@@ -20,8 +23,9 @@ enum bshell_status compile_if(struct compile_ctx *ctx, struct ast_node *src)
i = 0; i = 0;
fx_queue_entry *cur = fx_queue_first(&if_group->n_branches); fx_queue_entry *cur = fx_queue_first(&if_group->n_branches);
while (cur) { while (cur) {
struct if_branch_ast_node *branch = fx_unbox( struct bshell_if_branch_ast_node *branch;
struct if_branch_ast_node, branch = fx_unbox(
struct bshell_if_branch_ast_node,
cur, cur,
n_base.n_entry); n_base.n_entry);
if (!branch->n_cond) { if (!branch->n_cond) {
@@ -29,7 +33,7 @@ enum bshell_status compile_if(struct compile_ctx *ctx, struct ast_node *src)
compile_ref_label(ctx, label_ids[nr_labels - 1]); compile_ref_label(ctx, label_ids[nr_labels - 1]);
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_BR, BSHELL_OPCODE_BR,
0); 0);
break; break;
} }
@@ -38,7 +42,7 @@ enum bshell_status compile_if(struct compile_ctx *ctx, struct ast_node *src)
compile_ref_label(ctx, label_ids[i++]); compile_ref_label(ctx, label_ids[i++]);
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_BR_TRUE, BSHELL_OPCODE_BR_TRUE,
0); 0);
cur = fx_queue_next(cur); cur = fx_queue_next(cur);
@@ -47,8 +51,8 @@ enum bshell_status compile_if(struct compile_ctx *ctx, struct ast_node *src)
i = 0; i = 0;
cur = fx_queue_first(&if_group->n_branches); cur = fx_queue_first(&if_group->n_branches);
while (cur) { while (cur) {
struct if_branch_ast_node *branch = fx_unbox( struct bshell_if_branch_ast_node *branch = fx_unbox(
struct if_branch_ast_node, struct bshell_if_branch_ast_node,
cur, cur,
n_base.n_entry); n_base.n_entry);
if (!branch->n_cond) { if (!branch->n_cond) {
@@ -63,7 +67,7 @@ enum bshell_status compile_if(struct compile_ctx *ctx, struct ast_node *src)
compile_ref_label(ctx, label_ids[nr_labels - 1]); compile_ref_label(ctx, label_ids[nr_labels - 1]);
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_BR, BSHELL_OPCODE_BR,
0); 0);
} }
} }
+25
View File
@@ -0,0 +1,25 @@
#include "compile-node.h"
static const compile_node_impl node_compilers[] = {
[BSHELL_AST_INT] = compile_int,
[BSHELL_AST_DOUBLE] = compile_double,
[BSHELL_AST_STRING] = compile_string,
[BSHELL_AST_WORD] = compile_word,
[BSHELL_AST_OP] = compile_op,
[BSHELL_AST_VAR] = compile_var,
[BSHELL_AST_FSTRING] = compile_fstring,
[BSHELL_AST_ARRAY] = compile_array,
[BSHELL_AST_HASHTABLE] = compile_hashtable,
[BSHELL_AST_HASHTABLE_ITEM] = compile_hashtable_item,
[BSHELL_AST_CMDCALL] = compile_cmdcall,
[BSHELL_AST_PIPELINE] = compile_pipeline,
[BSHELL_AST_BLOCK] = compile_block,
};
static const size_t nr_node_compilers = sizeof node_compilers
/ sizeof node_compilers[0];
const struct compile_state_type normal_state = {
.s_size = sizeof(struct compile_state),
.s_compile_node = node_compilers,
.s_nr_compile_node = nr_node_compilers,
};
+126
View File
@@ -0,0 +1,126 @@
#include "compile-node.h"
#include <bshell/runtime/operator.h>
static enum bshell_opcode opcode_for_op(enum bshell_operator_id op)
{
switch (op) {
case BSHELL_OP_ADD:
return BSHELL_OPCODE_ADD;
case BSHELL_OP_SUBTRACT:
return BSHELL_OPCODE_SUB;
case BSHELL_OP_MULTIPLY:
return BSHELL_OPCODE_MUL;
case BSHELL_OP_DIVIDE:
return BSHELL_OPCODE_DIV;
case BSHELL_OP_MODULO:
return BSHELL_OPCODE_MOD;
case BSHELL_OP_INCREMENT:
return BSHELL_OPCODE_INC;
case BSHELL_OP_DECREMENT:
return BSHELL_OPCODE_DEC;
case BSHELL_OP_LEFT_SHIFT:
return BSHELL_OPCODE_SHL;
case BSHELL_OP_RIGHT_SHIFT:
return BSHELL_OPCODE_SHR;
case BSHELL_OP_BINARY_AND:
return BSHELL_OPCODE_BAND;
case BSHELL_OP_BINARY_OR:
return BSHELL_OPCODE_BOR;
case BSHELL_OP_BINARY_XOR:
return BSHELL_OPCODE_BXOR;
case BSHELL_OP_BINARY_NOT:
return BSHELL_OPCODE_BNOT;
case BSHELL_OP_LESS_THAN:
return BSHELL_OPCODE_CMP_LT;
case BSHELL_OP_GREATER_THAN:
return BSHELL_OPCODE_CMP_GT;
case BSHELL_OP_EQUAL:
return BSHELL_OPCODE_CMP_EQ;
case BSHELL_OP_NOT_EQUAL:
return BSHELL_OPCODE_CMP_NE;
case BSHELL_OP_LESS_EQUAL:
return BSHELL_OPCODE_CMP_LE;
case BSHELL_OP_GREATER_EQUAL:
return BSHELL_OPCODE_CMP_GE;
case BSHELL_OP_LOGICAL_AND:
return BSHELL_OPCODE_LAND;
case BSHELL_OP_LOGICAL_OR:
return BSHELL_OPCODE_LOR;
case BSHELL_OP_LOGICAL_XOR:
return BSHELL_OPCODE_LXOR;
case BSHELL_OP_LOGICAL_NOT:
return BSHELL_OPCODE_LNOT;
case BSHELL_OP_RANGE:
return BSHELL_OPCODE_RANGE;
case BSHELL_OP_MATCH:
return BSHELL_OPCODE_MATCH;
case BSHELL_OP_REPLACE:
return BSHELL_OPCODE_REPLACE;
case BSHELL_OP_LIKE:
return BSHELL_OPCODE_LIKE;
case BSHELL_OP_IN:
return BSHELL_OPCODE_IN;
case BSHELL_OP_FORMAT:
return BSHELL_OPCODE_FMT;
case BSHELL_OP_CONTAINS:
return BSHELL_OPCODE_CONTAINS;
case BSHELL_OP_USPLIT:
return BSHELL_OPCODE_SPLIT;
case BSHELL_OP_BSPLIT:
return BSHELL_OPCODE_SPLIT;
case BSHELL_OP_UJOIN:
return BSHELL_OPCODE_JOIN;
case BSHELL_OP_BJOIN:
return BSHELL_OPCODE_JOIN;
case BSHELL_OP_IS:
return BSHELL_OPCODE_IS;
case BSHELL_OP_AS:
return BSHELL_OPCODE_AS;
case BSHELL_OP_ACCESS:
return BSHELL_OPCODE_LDPROP;
default:
return BSHELL_OPCODE_NOP;
}
}
enum bshell_status op_load(struct compile_ctx *ctx, struct compile_value *value)
{
enum bshell_opcode opcode = opcode_for_op(value->v_op);
if (opcode != BSHELL_OPCODE_NOP) {
compile_value_load(ctx, value->v_right);
compile_value_load(ctx, value->v_left);
bshell_scriptblock_push_instruction(
ctx->c_block,
opcode_for_op(value->v_op),
0);
return BSHELL_SUCCESS;
}
switch (value->v_op) {
case BSHELL_OP_ASSIGN:
compile_value_load(ctx, value->v_right);
compile_value_store(ctx, value->v_left);
break;
default:
return BSHELL_ERR_NOT_SUPPORTED;
}
return BSHELL_SUCCESS;
}
static const struct compile_value_type op_type = {
.v_load = op_load,
};
struct compile_result compile_op(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct bshell_op_ast_node *op = (struct bshell_op_ast_node *)src;
struct compile_value *left = NULL, *right = NULL;
left = compile_pop_value(ctx);
right = compile_pop_value(ctx);
compile_push_op(ctx, src, &op_type, op->n_op->op_id, left, right);
return COMPILE_OK(0);
}
@@ -3,7 +3,7 @@
enum bshell_status compile_push_value( enum bshell_status compile_push_value(
struct compile_ctx *ctx, struct compile_ctx *ctx,
const struct compile_value_type *type, const struct compile_value_type *type,
struct ast_node *node) struct bshell_ast_node *node)
{ {
struct compile_value *item = malloc(sizeof *item); struct compile_value *item = malloc(sizeof *item);
if (!item) { if (!item) {
@@ -22,7 +22,7 @@ enum bshell_status compile_push_value(
enum bshell_status compile_push_value_array( enum bshell_status compile_push_value_array(
struct compile_ctx *ctx, struct compile_ctx *ctx,
const struct compile_value_type *type, const struct compile_value_type *type,
struct ast_node *node, struct bshell_ast_node *node,
struct compile_value **values, struct compile_value **values,
size_t nr_values) size_t nr_values)
{ {
@@ -63,9 +63,9 @@ enum bshell_status compile_push_pool_value(
enum bshell_status compile_push_op( enum bshell_status compile_push_op(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct ast_node *node, struct bshell_ast_node *node,
const struct compile_value_type *type, const struct compile_value_type *type,
enum operator_id op, enum bshell_operator_id op,
struct compile_value *left, struct compile_value *left,
struct compile_value *right) struct compile_value *right)
{ {
@@ -14,8 +14,8 @@ struct compile_state *compile_push_state(
return NULL; return NULL;
} }
const struct compile_state_type *state_type = state_types const struct compile_state_type *state_type
[state_type_id]; = state_types[state_type_id];
if (!state_type) { if (!state_type) {
return NULL; return NULL;
} }
@@ -43,10 +43,6 @@ void compile_pop_state(struct compile_ctx *ctx)
return; return;
} }
if (!fx_queue_prev(&state->s_entry)) {
return;
}
if (state->s_type->s_compile_end) { if (state->s_type->s_compile_end) {
state->s_type->s_compile_end(ctx); state->s_type->s_compile_end(ctx);
} }
@@ -4,7 +4,8 @@ enum bshell_status var_load(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct var_ast_node *var = (struct var_ast_node *)value->v_node; struct bshell_var_ast_node *var
= (struct bshell_var_ast_node *)value->v_node;
unsigned long index = bshell_scriptblock_get_string( unsigned long index = bshell_scriptblock_get_string(
ctx->c_block, ctx->c_block,
var->n_ident->tok_str); var->n_ident->tok_str);
@@ -14,7 +15,7 @@ enum bshell_status var_load(
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_LDLOCAL, BSHELL_OPCODE_LDLOCAL,
index); index);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -23,7 +24,8 @@ enum bshell_status var_store(
struct compile_ctx *ctx, struct compile_ctx *ctx,
struct compile_value *value) struct compile_value *value)
{ {
struct var_ast_node *var = (struct var_ast_node *)value->v_node; struct bshell_var_ast_node *var
= (struct bshell_var_ast_node *)value->v_node;
unsigned long index = bshell_scriptblock_get_string( unsigned long index = bshell_scriptblock_get_string(
ctx->c_block, ctx->c_block,
var->n_ident->tok_str); var->n_ident->tok_str);
@@ -33,7 +35,7 @@ enum bshell_status var_store(
bshell_scriptblock_push_instruction( bshell_scriptblock_push_instruction(
ctx->c_block, ctx->c_block,
OPCODE_STLOCAL, BSHELL_OPCODE_STLOCAL,
index); index);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
@@ -43,7 +45,9 @@ static const struct compile_value_type var_type = {
.v_store = var_store, .v_store = var_store,
}; };
struct compile_result compile_var(struct compile_ctx *ctx, struct ast_node *src) struct compile_result compile_var(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{ {
compile_push_value(ctx, &var_type, src); compile_push_value(ctx, &var_type, src);
return COMPILE_OK(0); return COMPILE_OK(0);
+11 -13
View File
@@ -1,7 +1,5 @@
#include "file.h" #include <bshell/file.h>
#include <bshell/line-source.h>
#include "line-source.h"
#include <errno.h> #include <errno.h>
#include <fx/collections/array.h> #include <fx/collections/array.h>
#include <fx/string.h> #include <fx/string.h>
@@ -9,24 +7,24 @@
#include <string.h> #include <string.h>
static enum bshell_status get_name( static enum bshell_status get_name(
struct line_source *src, struct bshell_line_source *src,
char *buf, char *buf,
size_t count, size_t count,
size_t *nr_read) size_t *nr_read)
{ {
struct file *f = (struct file *)src; struct bshell_file *f = (struct bshell_file *)src;
*nr_read = snprintf(buf, count, "%s", f->f_path); *nr_read = snprintf(buf, count, "%s", f->f_path);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
static enum bshell_status get_row( static enum bshell_status get_row(
struct line_source *src, struct bshell_line_source *src,
size_t row, size_t row,
char *buf, char *buf,
size_t count, size_t count,
size_t *nr_read) size_t *nr_read)
{ {
struct file *f = (struct file *)src; struct bshell_file *f = (struct bshell_file *)src;
size_t nr_rows = fx_array_get_size(f->f_lines); size_t nr_rows = fx_array_get_size(f->f_lines);
if (row > nr_rows) { if (row > nr_rows) {
@@ -50,10 +48,10 @@ static enum bshell_status get_row(
} }
static enum bshell_status readline( static enum bshell_status readline(
struct line_source *src, struct bshell_line_source *src,
fx_stringstream *out) fx_stringstream *out)
{ {
struct file *f = (struct file *)src; struct bshell_file *f = (struct bshell_file *)src;
fx_wchar c = FX_WCHAR_INVALID; fx_wchar c = FX_WCHAR_INVALID;
size_t nr_read = 0; size_t nr_read = 0;
@@ -78,7 +76,7 @@ static enum bshell_status readline(
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
enum bshell_status file_open(const char *path, struct file **out) enum bshell_status bshell_file_open(const char *path, struct bshell_file **out)
{ {
FILE *fp = fopen(path, "r"); FILE *fp = fopen(path, "r");
if (!fp) { if (!fp) {
@@ -87,7 +85,7 @@ enum bshell_status file_open(const char *path, struct file **out)
fx_stream *strp = fx_stream_open_fp(fp); fx_stream *strp = fx_stream_open_fp(fp);
struct file *file = malloc(sizeof *file); struct bshell_file *file = malloc(sizeof *file);
if (!file) { if (!file) {
fclose(fp); fclose(fp);
return BSHELL_ERR_NO_MEMORY; return BSHELL_ERR_NO_MEMORY;
@@ -108,7 +106,7 @@ enum bshell_status file_open(const char *path, struct file **out)
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
void file_close(struct file *file) void bshell_file_close(struct bshell_file *file)
{ {
fx_stream_unref(file->f_strp); fx_stream_unref(file->f_strp);
fx_array_unref(file->f_lines); fx_array_unref(file->f_lines);
+14
View File
@@ -0,0 +1,14 @@
#include <bshell/format.h>
static struct bshell_table_column command_table_columns[] = {
TABLE_COLUMN("command_type", "command_type", 13),
TABLE_COLUMN("name", "name", COL_WIDTH_INFINITE),
TABLE_COLUMN("version", "version", 12),
TABLE_COLUMN("source", "source", 35),
};
struct bshell_table command_bshell_table = {
.fmt_columns = command_table_columns,
.fmt_column_count
= sizeof command_table_columns / sizeof command_table_columns[0],
};
@@ -1,29 +1,30 @@
#include "format.h" #include <bshell/format.h>
#include <fx/term/print.h>
#include <fx/type.h> #include <fx/type.h>
#include <fx/value-type.h> #include <fx/value-type.h>
#if BSHELL_INTERACTIVE == 1
#include <fx/term/print.h>
#endif
static void format_value_fallback(const fx_value *value, fx_stream *dest) static void format_value_fallback(const fx_value *value, fx_stream *dest)
{ {
#if BSHELL_INTERACTIVE == 1
fx_printf("[yellow]"); fx_printf("[yellow]");
#endif
fx_value_to_string(value, dest, NULL); fx_value_to_string(value, dest, NULL);
#if BSHELL_INTERACTIVE == 1
fx_printf("[reset]\n"); fx_printf("[reset]\n");
#endif
} }
enum bshell_status format_value_default(const fx_value *value, fx_stream *dest) enum bshell_status format_value_default(const fx_value *value, fx_stream *dest)
{ {
if (fx_type_is_value_type(value->v_type)) { struct bshell_value_writer writer;
format_value_fallback(value, dest); bshell_value_writer_init(&writer, 0, 0, dest);
return BSHELL_SUCCESS; bshell_value_writer_write(&writer, value);
} bshell_value_writer_cleanup(&writer);
fx_object *object = NULL;
fx_value_get_object(value, &object);
enum bshell_status status = format_object_table(object, dest);
if (status != BSHELL_SUCCESS) {
format_value_fallback(value, dest);
}
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
+12
View File
@@ -0,0 +1,12 @@
#include <bshell/format.h>
static struct bshell_table_column hashtable_table_columns[] = {
TABLE_COLUMN("key", "key", 37),
TABLE_COLUMN("value", "value", COL_WIDTH_INFINITE),
};
struct bshell_table hashtable_bshell_table = {
.fmt_columns = hashtable_table_columns,
.fmt_column_count
= sizeof hashtable_table_columns / sizeof hashtable_table_columns[0],
};
@@ -1,43 +1,45 @@
#include "format.h" #include <bshell/format.h>
#include <fx/collections/array.h> #include <fx/collections/array.h>
#include <fx/iterator.h> #include <fx/iterator.h>
#include <fx/reflection/type.h> #include <fx/reflection/type.h>
#include <fx/stringstream.h> #include <fx/stringstream.h>
#include <fx/term/print.h>
#include <fx/term/tty.h>
#include <fx/value.h> #include <fx/value.h>
static fx_namemap table_formats = FX_NAMEMAP_INIT; #if BSHELL_INTERACTIVE == 1
#include <fx/term/print.h>
#include <fx/term/tty.h>
#endif
extern struct table_format hashtable_table_format; static fx_namemap bshell_tables = FX_NAMEMAP_INIT;
extern struct table_format verb_table_format;
extern struct table_format command_table_format;
enum bshell_status table_format_init(void) extern struct bshell_table hashtable_bshell_table;
extern struct bshell_table verb_bshell_table;
extern struct bshell_table command_bshell_table;
enum bshell_status bshell_table_init(void)
{ {
fx_namemap_put( fx_namemap_put(
&table_formats, &bshell_tables,
"fx.collections.hashtable", "fx.collections.hashtable",
&hashtable_table_format.fmt_entry); &hashtable_bshell_table.fmt_entry);
fx_namemap_put( fx_namemap_put(
&table_formats, &bshell_tables,
"bshell.verb", "bshell.verb",
&verb_table_format.fmt_entry); &verb_bshell_table.fmt_entry);
fx_namemap_put( fx_namemap_put(
&table_formats, &bshell_tables,
"bshell.command", "bshell.command",
&command_table_format.fmt_entry); &command_bshell_table.fmt_entry);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
const struct table_format *table_format_get_for_type(const fx_type *ty) const struct bshell_table *bshell_table_get_for_type(const fx_type *ty)
{ {
while (ty) { while (ty) {
const char *name = fx_type_get_name(ty); const char *name = fx_type_get_name(ty);
fx_namemap_entry *entry = fx_namemap_get(&table_formats, name); fx_namemap_entry *entry = fx_namemap_get(&bshell_tables, name);
if (entry) { if (entry) {
return fx_unbox(struct table_format, entry, fmt_entry); return fx_unbox(struct bshell_table, entry, fmt_entry);
} }
ty = fx_type_get_parent(ty); ty = fx_type_get_parent(ty);
@@ -53,43 +55,43 @@ enum bshell_status format_object_table(fx_object *object, fx_stream *dest)
return BSHELL_ERR_NOT_SUPPORTED; return BSHELL_ERR_NOT_SUPPORTED;
} }
const struct table_format *fmt = table_format_get_for_type(type); const struct bshell_table *fmt = bshell_table_get_for_type(type);
if (!fmt) { if (!fmt) {
return BSHELL_ERR_NOT_SUPPORTED; return BSHELL_ERR_NOT_SUPPORTED;
} }
struct table_format_ctx ctx; struct bshell_table_ctx ctx;
table_format_ctx_init(&ctx, dest); bshell_table_ctx_init(&ctx, dest);
fx_iterator *it = fx_iterator_begin(object); const fx_iterator *it = fx_iterator_begin(object);
if (!it) { if (!it) {
table_format_ctx_prepare_columns_from_format( bshell_table_ctx_prepare_columns_from_format(
&ctx, &ctx,
fx_type_get_by_id(fx_object_query_type(object)), fx_type_get_by_id(fx_object_query_type(object)),
fmt); fmt);
table_format_ctx_print_headers(&ctx); bshell_table_ctx_print_headers(&ctx);
table_format_ctx_print_record(&ctx, &FX_VALUE_OBJECT(object)); bshell_table_ctx_print_record(&ctx, &FX_VALUE_OBJECT(object));
} else { } else {
fx_value first = fx_iterator_get_value(it); const fx_value *first = fx_iterator_get_value(it);
if (first.v_type) { if (first) {
table_format_ctx_prepare_columns_from_format( bshell_table_ctx_prepare_columns_from_format(
&ctx, &ctx,
fx_type_get_by_id(first.v_type), fx_type_get_by_id(first->v_type),
fmt); fmt);
} }
table_format_ctx_print_headers(&ctx); bshell_table_ctx_print_headers(&ctx);
fx_foreach(value, it) fx_foreach(value, it)
{ {
table_format_ctx_print_record(&ctx, &value); bshell_table_ctx_print_record(&ctx, value);
} }
} }
table_format_ctx_cleanup(&ctx); bshell_table_ctx_cleanup(&ctx);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
enum bshell_status table_format_ctx_init( enum bshell_status bshell_table_ctx_init(
struct table_format_ctx *ctx, struct bshell_table_ctx *ctx,
fx_stream *out) fx_stream *out)
{ {
memset(ctx, 0x0, sizeof *ctx); memset(ctx, 0x0, sizeof *ctx);
@@ -97,7 +99,7 @@ enum bshell_status table_format_ctx_init(
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
enum bshell_status table_format_ctx_cleanup(struct table_format_ctx *ctx) enum bshell_status bshell_table_ctx_cleanup(struct bshell_table_ctx *ctx)
{ {
if (ctx->ctx_columns) { if (ctx->ctx_columns) {
free(ctx->ctx_columns); free(ctx->ctx_columns);
@@ -107,42 +109,45 @@ enum bshell_status table_format_ctx_cleanup(struct table_format_ctx *ctx)
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
enum bshell_status table_format_ctx_prepare_columns_from_format( enum bshell_status bshell_table_ctx_prepare_columns_from_format(
struct table_format_ctx *ctx, struct bshell_table_ctx *ctx,
const fx_type *record_type, const fx_type *record_type,
const struct table_format *fmt) const struct bshell_table *fmt)
{ {
if (!fmt && !record_type) { if (!fmt && !record_type) {
return BSHELL_ERR_INVALID_ARGUMENT; return BSHELL_ERR_INVALID_ARGUMENT;
} }
if (!fmt) { if (!fmt) {
fmt = table_format_get_for_type(record_type); fmt = bshell_table_get_for_type(record_type);
} }
if (!fmt) { if (!fmt) {
return table_format_ctx_prepare_columns_from_object( return bshell_table_ctx_prepare_columns_from_object(
ctx, ctx,
record_type); record_type);
} }
ctx->ctx_fmt = fmt; ctx->ctx_fmt = fmt;
struct table_format_ctx_column *columns = calloc( struct bshell_table_ctx_column *columns
fmt->fmt_column_count, = calloc(fmt->fmt_column_count, sizeof *columns);
sizeof *columns);
if (!columns) { if (!columns) {
return BSHELL_ERR_NO_MEMORY; return BSHELL_ERR_NO_MEMORY;
} }
const struct table_format_column *column_defs = fmt->fmt_columns; const struct bshell_table_column *column_defs = fmt->fmt_columns;
ctx->ctx_columns = columns; ctx->ctx_columns = columns;
ctx->ctx_columns_count = fmt->fmt_column_count; ctx->ctx_columns_count = fmt->fmt_column_count;
ctx->ctx_tty_width = 0;
#if BSHELL_INTERACTIVE == 1
fx_tty_get_dimensions(fx_stdtty, &ctx->ctx_tty_width, NULL); fx_tty_get_dimensions(fx_stdtty, &ctx->ctx_tty_width, NULL);
#endif
if (!ctx->ctx_tty_width) { if (!ctx->ctx_tty_width) {
ctx->ctx_tty_width = 150; ctx->ctx_tty_width = 80;
} }
ctx->ctx_variable_columns_count = 0; ctx->ctx_variable_columns_count = 0;
@@ -162,7 +167,7 @@ enum bshell_status table_format_ctx_prepare_columns_from_format(
if (column_defs[i].col_width <= tty_width) { if (column_defs[i].col_width <= tty_width) {
columns[i].col_width = column_defs[i].col_width; columns[i].col_width = column_defs[i].col_width;
tty_width -= columns[i].col_width; tty_width -= (columns[i].col_width + 1);
continue; continue;
} }
@@ -173,16 +178,16 @@ enum bshell_status table_format_ctx_prepare_columns_from_format(
for (size_t i = 0; i < fmt->fmt_column_count; i++) { for (size_t i = 0; i < fmt->fmt_column_count; i++) {
if (column_defs[i].col_width == COL_WIDTH_INFINITE) { if (column_defs[i].col_width == COL_WIDTH_INFINITE) {
columns[i].col_width = tty_width columns[i].col_width
/ ctx->ctx_variable_columns_count; = tty_width / ctx->ctx_variable_columns_count;
} }
} }
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
enum bshell_status table_format_ctx_prepare_columns_from_object( enum bshell_status bshell_table_ctx_prepare_columns_from_object(
struct table_format_ctx *ctx, struct bshell_table_ctx *ctx,
const fx_type *record_type) const fx_type *record_type)
{ {
fx_array *properties = fx_array_create(); fx_array *properties = fx_array_create();
@@ -190,7 +195,7 @@ enum bshell_status table_format_ctx_prepare_columns_from_object(
fx_iterator *it = fx_type_get_properties(record_type); fx_iterator *it = fx_type_get_properties(record_type);
fx_foreach(prop_v, it) fx_foreach(prop_v, it)
{ {
fx_array_push_back(properties, prop_v); fx_array_push_back(properties, *prop_v);
} }
fx_iterator_unref(it); fx_iterator_unref(it);
@@ -200,9 +205,8 @@ enum bshell_status table_format_ctx_prepare_columns_from_object(
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
struct table_format_ctx_column *columns = calloc( struct bshell_table_ctx_column *columns
column_count, = calloc(column_count, sizeof *columns);
sizeof *columns);
if (!columns) { if (!columns) {
fx_array_unref(properties); fx_array_unref(properties);
@@ -211,10 +215,14 @@ enum bshell_status table_format_ctx_prepare_columns_from_object(
ctx->ctx_columns = columns; ctx->ctx_columns = columns;
ctx->ctx_columns_count = column_count; ctx->ctx_columns_count = column_count;
ctx->ctx_tty_width = 0;
#if BSHELL_INTERACTIVE == 1
fx_tty_get_dimensions(fx_stdtty, &ctx->ctx_tty_width, NULL); fx_tty_get_dimensions(fx_stdtty, &ctx->ctx_tty_width, NULL);
#endif
if (!ctx->ctx_tty_width) { if (!ctx->ctx_tty_width) {
ctx->ctx_tty_width = 150; ctx->ctx_tty_width = 80;
} }
ctx->ctx_variable_columns_count = 0; ctx->ctx_variable_columns_count = 0;
@@ -235,11 +243,25 @@ enum bshell_status table_format_ctx_prepare_columns_from_object(
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
enum bshell_status table_format_ctx_print_headers(struct table_format_ctx *ctx) static void set_table_header_tty_colour(void)
{ {
#if BSHELL_INTERACTIVE == 1
fx_printf("[bold,bright_green]"); fx_printf("[bold,bright_green]");
#endif
}
static void reset_tty_colour(void)
{
#if BSHELL_INTERACTIVE == 1
fx_printf("[reset]");
#endif
}
enum bshell_status bshell_table_ctx_print_headers(struct bshell_table_ctx *ctx)
{
set_table_header_tty_colour();
bool repeat = false; bool repeat = false;
struct table_format_ctx_column *c = NULL; struct bshell_table_ctx_column *c = NULL;
do { do {
repeat = false; repeat = false;
@@ -267,6 +289,10 @@ enum bshell_status table_format_ctx_print_headers(struct table_format_ctx *ctx)
fx_stream_write_char(ctx->ctx_out, ' '); fx_stream_write_char(ctx->ctx_out, ' ');
} }
if (i < ctx->ctx_columns_count - 1) {
fx_stream_write_char(ctx->ctx_out, ' ');
}
if (to_write != title_chars_remaining) { if (to_write != title_chars_remaining) {
repeat = true; repeat = true;
} }
@@ -276,7 +302,7 @@ enum bshell_status table_format_ctx_print_headers(struct table_format_ctx *ctx)
fx_stream_write_char(ctx->ctx_out, '\n'); fx_stream_write_char(ctx->ctx_out, '\n');
for (size_t i = 0; i < ctx->ctx_columns_count; i++) { for (size_t i = 0; i < ctx->ctx_columns_count; i++) {
struct table_format_ctx_column *c = &ctx->ctx_columns[i]; struct bshell_table_ctx_column *c = &ctx->ctx_columns[i];
if (c->col_width == 0) { if (c->col_width == 0) {
continue; continue;
} }
@@ -294,25 +320,37 @@ enum bshell_status table_format_ctx_print_headers(struct table_format_ctx *ctx)
for (; x < c->col_width; x++) { for (; x < c->col_width; x++) {
fx_stream_write_char(ctx->ctx_out, ' '); fx_stream_write_char(ctx->ctx_out, ' ');
} }
if (i < ctx->ctx_columns_count - 1) {
fx_stream_write_char(ctx->ctx_out, ' ');
}
} }
fx_printf("[reset]"); reset_tty_colour();
fx_stream_write_char(ctx->ctx_out, '\n'); fx_stream_write_char(ctx->ctx_out, '\n');
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
enum bshell_status table_format_ctx_print_record( enum bshell_status bshell_table_ctx_print_record(
struct table_format_ctx *ctx, struct bshell_table_ctx *ctx,
const fx_value *record) const fx_value *record)
{ {
fx_stringstream *strm = fx_stringstream_create(); struct bshell_value_writer writer;
size_t written = 0;
for (size_t i = 0; i < ctx->ctx_columns_count; i++) { for (size_t i = 0; i < ctx->ctx_columns_count; i++) {
struct table_format_ctx_column *c = &ctx->ctx_columns[i]; struct bshell_table_ctx_column *c = &ctx->ctx_columns[i];
if (c->col_width == 0) { if (c->col_width == 0) {
continue; continue;
} }
fx_stringstream_reset(strm); bshell_value_writer_init(
&writer,
BSHELL_VALUE_WRITER_NO_NEWLINE
| BSHELL_VALUE_WRITER_ONELINE
| BSHELL_VALUE_WRITER_TRUNCATE,
c->col_width,
ctx->ctx_out);
fx_value column_value = FX_VALUE_EMPTY; fx_value column_value = FX_VALUE_EMPTY;
if (c->col_property) { if (c->col_property) {
fx_status status = fx_property_get_value( fx_status status = fx_property_get_value(
@@ -320,34 +358,23 @@ enum bshell_status table_format_ctx_print_record(
record, record,
&column_value); &column_value);
if (FX_OK(status)) { if (FX_OK(status)) {
fx_value_to_string(&column_value, strm, NULL); written = bshell_value_writer_write(
&writer,
&column_value);
} }
} }
size_t to_write = fx_stringstream_get_length(strm); for (size_t x = written; x < c->col_width; x++) {
const char *s = fx_stringstream_ptr(strm);
bool overflow = false;
if (to_write > c->col_width) {
to_write = c->col_width - 2;
overflow = true;
}
size_t x;
for (x = 0; x < to_write; x++) {
fx_stream_write_char(ctx->ctx_out, s[x]);
}
if (overflow) {
fx_stream_write_char(ctx->ctx_out, L'');
x++;
}
for (; x < c->col_width; x++) {
fx_stream_write_char(ctx->ctx_out, ' '); fx_stream_write_char(ctx->ctx_out, ' ');
} }
if (i < ctx->ctx_columns_count - 1) {
fx_stream_write_char(ctx->ctx_out, ' ');
}
bshell_value_writer_cleanup(&writer);
} }
fx_stream_write_char(ctx->ctx_out, '\n'); fx_stream_write_char(ctx->ctx_out, '\n');
fx_stringstream_unref(strm);
return BSHELL_SUCCESS; return BSHELL_SUCCESS;
} }
+184
View File
@@ -0,0 +1,184 @@
#include <bshell/format.h>
#include <fx/collections/array.h>
#include <fx/string.h>
#include <fx/type.h>
#include <fx/value-type.h>
static void initialise_table(
struct bshell_value_writer *w,
const fx_value *first_record)
{
bshell_table_ctx_init(&w->w_table_ctx, w->w_dest);
const fx_type *ty = fx_type_get_by_id(first_record->v_type);
bshell_table_ctx_prepare_columns_from_format(&w->w_table_ctx, ty, NULL);
bshell_table_ctx_print_headers(&w->w_table_ctx);
w->w_table_initialised = true;
}
static size_t write_iterable(
struct bshell_value_writer *w,
const fx_value *value)
{
size_t written = 0;
fx_array *array = NULL;
fx_value_get_object(value, &array);
const fx_iterator *it = fx_iterator_begin(array);
fx_foreach(v, it)
{
written += bshell_value_writer_write(w, v);
}
fx_iterator_unref(it);
return written;
}
static bool string_has_trailing_newline(const char *s)
{
long len = strlen(s);
if (len == 0) {
return false;
}
return s[len - 1] == '\n';
}
static size_t write_control_char(struct bshell_value_writer *w, fx_wchar c)
{
bool oneline = (w->w_flags & BSHELL_VALUE_WRITER_ONELINE) != 0;
size_t written = 1;
switch (c) {
case '\n':
if (oneline) {
fx_stream_write_cstr(w->w_dest, "\\n", &written);
} else {
fx_stream_write_char(w->w_dest, '\n');
}
break;
case '\r':
fx_stream_write_cstr(w->w_dest, "\\r", NULL);
break;
case '\t':
fx_stream_write_cstr(w->w_dest, "\\t", NULL);
break;
case '\b':
fx_stream_write_cstr(w->w_dest, "\\b", NULL);
break;
default:
written = 0;
break;
}
return written;
}
static size_t write_string(struct bshell_value_writer *w, const fx_value *value)
{
const char *s = NULL;
size_t written = 0;
fx_value_get_cstr(value, &s);
bool trailing_newline = string_has_trailing_newline(s);
bool inhibit_newline
= (w->w_flags & BSHELL_VALUE_WRITER_NO_NEWLINE) != 0;
bool truncate = (w->w_flags & BSHELL_VALUE_WRITER_TRUNCATE) != 0;
for (written = 0; *s;) {
if (truncate && written == w->w_max_width - 1) {
fx_stream_write_char(w->w_dest, L'');
written++;
break;
}
fx_wchar c = fx_wchar_utf8_codepoint_decode(s);
unsigned int stride = fx_wchar_utf8_codepoint_size(c);
if (stride == 0) {
break;
}
if (!fx_wchar_is_graph(c)) {
written += write_control_char(w, c);
goto next;
}
char cs[5] = {0};
fx_wchar_utf8_codepoint_encode(c, cs);
size_t n = 0;
fx_stream_write_cstr(w->w_dest, cs, &n);
written += n;
next:
s += stride;
}
if (!trailing_newline && !inhibit_newline) {
fx_stream_write_char(w->w_dest, '\n');
written++;
}
return written;
}
static size_t write_value(struct bshell_value_writer *w, const fx_value *value)
{
const fx_type *ty = fx_type_get_by_id(value->v_type);
if (fx_value_is_type(value, FX_TYPE_STRING)
|| fx_value_is_type(value, FX_TYPE_CSTR)) {
return write_string(w, value);
}
if (fx_type_get_interface(ty, FX_TYPE_ITERABLE)) {
return write_iterable(w, value);
}
if (fx_type_is_value_type(value->v_type)) {
fx_stringstream_reset(w->w_tmp);
fx_value_to_string(value, w->w_tmp, NULL);
fx_stream_write_char(w->w_tmp, '\n');
size_t result = fx_stringstream_get_length(w->w_tmp);
fx_stream_write_cstr(
w->w_dest,
fx_stringstream_get_cstr(w->w_tmp),
NULL);
return result;
}
if (!w->w_table_initialised) {
initialise_table(w, value);
}
bshell_table_ctx_print_record(&w->w_table_ctx, value);
return 0;
}
void bshell_value_writer_init(
struct bshell_value_writer *w,
enum bshell_value_writer_flags flags,
size_t max_width,
fx_stream *dest)
{
memset(w, 0x00, sizeof *w);
w->w_dest = dest;
w->w_flags = flags;
w->w_max_width = max_width;
w->w_tmp = fx_stringstream_create();
}
size_t bshell_value_writer_write(
struct bshell_value_writer *w,
const fx_value *value)
{
return write_value(w, value);
}
void bshell_value_writer_cleanup(struct bshell_value_writer *w)
{
if (w->w_table_initialised) {
bshell_table_ctx_cleanup(&w->w_table_ctx);
}
fx_stringstream_unref(w->w_tmp);
w->w_table_initialised = false;
}
+14
View File
@@ -0,0 +1,14 @@
#include <bshell/format.h>
static struct bshell_table_column verb_table_columns[] = {
TABLE_COLUMN("verb", "verb", 12),
TABLE_COLUMN("alias_prefix", "alias_prefix", 12),
TABLE_COLUMN("group", "group", 12),
TABLE_COLUMN("description", "description", COL_WIDTH_INFINITE),
};
struct bshell_table verb_bshell_table = {
.fmt_columns = verb_table_columns,
.fmt_column_count
= sizeof verb_table_columns / sizeof verb_table_columns[0],
};
+232
View File
@@ -0,0 +1,232 @@
#ifndef BSHELL_AST_H_
#define BSHELL_AST_H_
#include <bshell/status.h>
#include <fx/bstr.h>
#include <fx/queue.h>
struct bshell_lex_token;
#define BSHELL_AST_ITERATE_OK(flags) \
((struct bshell_ast_iterate_result) {.r_status = BSHELL_SUCCESS, \
.r_flags = (flags)})
#define BSHELL_AST_ITERATE_ERR(status) \
((struct bshell_ast_iterate_result) {.r_status = (status)})
enum bshell_ast_node_type {
BSHELL_AST_NONE = 0x00u,
BSHELL_AST_NULL,
BSHELL_AST_STMT_LIST,
BSHELL_AST_INT,
BSHELL_AST_DOUBLE,
BSHELL_AST_WORD,
BSHELL_AST_STRING,
BSHELL_AST_FSTRING,
BSHELL_AST_VAR,
BSHELL_AST_VAR_SPLAT,
BSHELL_AST_FLAG,
BSHELL_AST_CMDCALL,
BSHELL_AST_FUNCALL,
BSHELL_AST_PIPELINE,
BSHELL_AST_REDIRECTION,
BSHELL_AST_BLOCK,
BSHELL_AST_FUNC,
BSHELL_AST_ARRAY,
BSHELL_AST_HASHTABLE,
BSHELL_AST_HASHTABLE_ITEM,
BSHELL_AST_OP,
BSHELL_AST_IF,
BSHELL_AST_IF_BRANCH,
};
struct bshell_ast_iterator_entry {
fx_queue_entry e_entry;
unsigned long e_depth;
};
struct bshell_ast_node {
enum bshell_ast_node_type n_type;
struct bshell_ast_node *n_parent;
fx_queue_entry n_entry;
struct bshell_ast_iterator_entry n_it;
};
struct bshell_null_ast_node {
struct bshell_ast_node n_base;
};
struct bshell_int_ast_node {
struct bshell_ast_node n_base;
struct bshell_lex_token *n_value;
};
struct bshell_double_ast_node {
struct bshell_ast_node n_base;
struct bshell_lex_token *n_value;
};
struct bshell_word_ast_node {
struct bshell_ast_node n_base;
struct bshell_lex_token *n_value;
};
struct bshell_string_ast_node {
struct bshell_ast_node n_base;
struct bshell_lex_token *n_value;
};
struct bshell_fstring_ast_node {
struct bshell_ast_node n_base;
fx_queue n_elements;
};
struct bshell_var_ast_node {
struct bshell_ast_node n_base;
struct bshell_lex_token *n_ident;
};
struct bshell_var_splat_ast_node {
struct bshell_ast_node n_base;
struct bshell_lex_token *n_ident;
};
struct bshell_cmdcall_ast_node {
struct bshell_ast_node n_base;
fx_queue n_args;
fx_queue n_redirect;
};
struct bshell_funcall_ast_node {
struct bshell_ast_node n_base;
struct bshell_ast_node *n_func;
fx_queue n_args;
};
struct bshell_pipeline_ast_node {
struct bshell_ast_node n_base;
fx_queue n_stages;
};
struct bshell_redirection_ast_node {
struct bshell_ast_node n_base;
bool n_append : 1;
bool n_out_is_fd : 1;
bool n_out_is_expr : 1;
unsigned int n_in, n_out;
struct bshell_ast_node *n_out_path_expr;
const char *n_out_path;
struct bshell_lex_token *n_out_tok;
};
struct bshell_stmt_list_ast_node {
struct bshell_ast_node n_base;
fx_queue n_statements;
};
struct bshell_block_ast_node {
struct bshell_ast_node n_base;
fx_queue n_statements;
};
struct bshell_func_ast_node {
struct bshell_ast_node n_base;
struct bshell_lex_token *n_name;
fx_queue n_params;
struct bshell_ast_node *n_body;
};
struct bshell_array_ast_node {
struct bshell_ast_node n_base;
fx_queue n_items;
};
struct bshell_hashtable_ast_node {
struct bshell_ast_node n_base;
fx_queue n_items;
};
struct bshell_hashtable_item_ast_node {
struct bshell_ast_node n_base;
struct bshell_ast_node *n_key, *n_value;
};
struct bshell_op_ast_node {
struct bshell_ast_node n_base;
const struct bshell_operator_info *n_op;
struct bshell_ast_node *n_left, *n_right;
};
struct bshell_if_branch_ast_node {
struct bshell_ast_node n_base;
struct bshell_ast_node *n_cond;
struct bshell_ast_node *n_body;
};
struct bshell_if_ast_node {
struct bshell_ast_node n_base;
fx_queue n_branches;
};
struct bshell_ast_iterator {
struct bshell_ast_node *it_cur;
fx_queue it_queue;
unsigned int it_depth;
fx_queue_entry *it_insert_after;
};
struct bshell_ast_iterate_result {
enum bshell_status r_status;
enum {
BSHELL_AST_ITERATE_CONTINUE = 0x00u,
BSHELL_AST_ITERATE_STOP = 0x01u,
BSHELL_AST_ITERATE_ADD_CHILDREN = 0x02u,
BSHELL_AST_ITERATE_REPEAT = 0x04u,
} r_flags;
};
enum bshell_ast_iteration_type {
BSHELL_AST_ITERATION_PRE,
BSHELL_AST_ITERATION_POST,
};
typedef struct bshell_ast_iterate_result (*bshell_ast_iterator_callback)(
struct bshell_ast_node *,
enum bshell_ast_iteration_type,
struct bshell_ast_iterator *,
void *);
struct bshell_ast_node_definition {
enum bshell_ast_node_type def_id;
size_t def_node_size;
enum bshell_status (*def_collect_children)(
struct bshell_ast_node *,
struct bshell_ast_iterator *);
enum bshell_status (*def_cleanup)(struct bshell_ast_node *);
void (*def_to_string)(const struct bshell_ast_node *, fx_bstr *);
};
extern struct bshell_ast_node *bshell_ast_node_create(
enum bshell_ast_node_type type);
extern void bshell_ast_node_destroy(struct bshell_ast_node *node);
extern void bshell_ast_node_to_string(
const struct bshell_ast_node *node,
fx_bstr *out);
extern enum bshell_status bshell_ast_node_iterate(
struct bshell_ast_node *node,
struct bshell_ast_iterator *it,
bshell_ast_iterator_callback callback,
void *arg);
extern const char *bshell_ast_node_type_to_string(
enum bshell_ast_node_type type);
extern struct bshell_ast_node *bshell_ast_iterator_peek(
struct bshell_ast_iterator *it);
extern struct bshell_ast_node *bshell_ast_iterator_dequeue(
struct bshell_ast_iterator *it);
extern void bshell_ast_iterator_enqueue(
struct bshell_ast_iterator *it,
struct bshell_ast_node *node);
#endif
@@ -1,5 +1,5 @@
#ifndef COMMAND_ALIAS_H_ #ifndef BSHELL_COMMAND_ALIAS_H_
#define COMMAND_ALIAS_H_ #define BSHELL_COMMAND_ALIAS_H_
#include "../verb.h" #include "../verb.h"
@@ -1,5 +1,5 @@
#ifndef COMMAND_CMDLET_H_ #ifndef BSHELL_COMMAND_CMDLET_H_
#define COMMAND_CMDLET_H_ #define BSHELL_COMMAND_CMDLET_H_
#include "../verb.h" #include "../verb.h"
@@ -1,5 +1,5 @@
#ifndef COMMAND_COMMAND_H_ #ifndef BSHELL_COMMAND_COMMAND_H_
#define COMMAND_COMMAND_H_ #define BSHELL_COMMAND_COMMAND_H_
#include <fx/macros.h> #include <fx/macros.h>
#include <fx/reflection/type.h> #include <fx/reflection/type.h>
@@ -8,6 +8,13 @@
FX_DECLS_BEGIN; FX_DECLS_BEGIN;
enum bshell_command_position {
BSHELL_COMMAND_POSITION_SINGLE = 0,
BSHELL_COMMAND_POSITION_BEGINNING,
BSHELL_COMMAND_POSITION_MIDDLE,
BSHELL_COMMAND_POSITION_END,
};
struct bshell_runtime; struct bshell_runtime;
#define BSHELL_TYPE_COMMAND (bshell_command_get_type()) #define BSHELL_TYPE_COMMAND (bshell_command_get_type())
@@ -24,7 +31,9 @@ FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_command)
*c_get_description)(const bshell_command *, fx_string *); *c_get_description)(const bshell_command *, fx_string *);
enum bshell_status ( enum bshell_status (
*c_get_description_static)(const fx_type *, fx_string *); *c_get_description_static)(const fx_type *, fx_string *);
enum bshell_status (*c_begin_processing)(bshell_command *); enum bshell_status (*c_begin_processing)(
bshell_command *,
enum bshell_command_position);
enum bshell_status (*c_process_record)( enum bshell_status (*c_process_record)(
bshell_command *, bshell_command *,
FX_TYPE_FWDREF(bshell_pipeline) * pipeline, FX_TYPE_FWDREF(bshell_pipeline) * pipeline,
@@ -47,9 +56,11 @@ extern void bshell_command_set_args_reverse(
extern const fx_value *bshell_command_get_arg( extern const fx_value *bshell_command_get_arg(
bshell_command *cmd, bshell_command *cmd,
size_t index); size_t index);
extern size_t bshell_command_get_arg_count(const bshell_command *cmd);
extern enum bshell_status bshell_command_begin_processing( extern enum bshell_status bshell_command_begin_processing(
bshell_command *command); bshell_command *command,
enum bshell_command_position position);
extern enum bshell_status bshell_command_process_record( extern enum bshell_status bshell_command_process_record(
bshell_command *command, bshell_command *command,
FX_TYPE_FWDREF(bshell_pipeline) * pipeline, FX_TYPE_FWDREF(bshell_pipeline) * pipeline,
@@ -0,0 +1,33 @@
#ifndef BSHELL_COMMAND_FUNCTION_H_
#define BSHELL_COMMAND_FUNCTION_H_
#include <bshell/runtime/script-block.h>
#include <fx/collections/array.h>
#include <fx/macros.h>
FX_DECLS_BEGIN;
struct bshell_runtime;
#define BSHELL_TYPE_FUNCTION (bshell_function_get_type())
FX_DECLARE_TYPE(bshell_function);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_function)
FX_TYPE_CLASS_DECLARATION_END(bshell_function)
extern fx_type_id bshell_function_get_type(void);
extern bshell_function *bshell_function_create(const char *name);
extern void bshell_function_add_positional_parameter(
bshell_function *func,
const char *name);
extern const char *bshell_function_get_name(const bshell_function *func);
extern const fx_array *bshell_function_get_positional_parameters(
const bshell_function *func);
extern bshell_scriptblock *bshell_function_get_body(bshell_function *func);
FX_DECLS_END;
#endif
@@ -0,0 +1,23 @@
#ifndef BSHELL_COMMAND_NATIVE_COMMAND_H_
#define BSHELL_COMMAND_NATIVE_COMMAND_H_
#include <fx/macros.h>
FX_DECLS_BEGIN;
struct bshell_runtime;
#define BSHELL_TYPE_NATIVE_COMMAND (bshell_native_command_get_type())
FX_DECLARE_TYPE(bshell_native_command);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_native_command)
FX_TYPE_CLASS_DECLARATION_END(bshell_native_command)
extern fx_type_id bshell_native_command_get_type(void);
extern bshell_native_command *bshell_native_command_create(const char *path);
FX_DECLS_END;
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef BSHELL_COMPILE_H_
#define BSHELL_COMPILE_H_
#include <bshell/command/function.h>
#include <bshell/runtime/script-block.h>
struct bshell_ast_node;
extern enum bshell_status bshell_compile(
struct bshell_ast_node *src,
bshell_scriptblock *dest);
extern enum bshell_status bshell_compile_function(
struct bshell_ast_node *src,
bshell_function **out);
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef BSHELL_FILE_H_
#define BSHELL_FILE_H_
#include <bshell/line-source.h>
#include <fx/collections/array.h>
#include <stdio.h>
struct bshell_file {
struct bshell_line_source f_base;
fx_array *f_lines;
char *f_path;
fx_stream *f_strp;
FILE *f_fp;
};
extern enum bshell_status bshell_file_open(
const char *path,
struct bshell_file **out);
extern void bshell_file_close(struct bshell_file *file);
#endif
+103
View File
@@ -0,0 +1,103 @@
#ifndef BSHELL_FORMAT_H_
#define BSHELL_FORMAT_H_
#include <bshell/status.h>
#include <fx/namemap.h>
#include <fx/object.h>
#include <fx/queue.h>
#include <fx/reflection/property.h>
#include <fx/reflection/type.h>
#include <fx/stream.h>
#include <fx/stringstream.h>
#include <fx/value.h>
#define TABLE_COLUMN(display_name, property_name, width) \
{ \
.col_display_name = (display_name), \
.col_property_name = (property_name), \
.col_width = (width), \
}
#define COL_WIDTH_INFINITE ((size_t)-1)
enum bshell_value_writer_flags {
BSHELL_VALUE_WRITER_ONELINE = 0x01u,
BSHELL_VALUE_WRITER_TRUNCATE = 0x02u,
BSHELL_VALUE_WRITER_NO_NEWLINE = 0x04u,
};
struct bshell_table_column {
const char *col_display_name;
const char *col_property_name;
size_t col_width;
};
struct bshell_table {
fx_namemap_entry fmt_entry;
const struct bshell_table_column *fmt_columns;
size_t fmt_column_count;
};
struct bshell_table_ctx_column {
const char *col_title;
size_t col_width;
size_t col_title_chars_written;
const char *col_title_ptr;
const fx_property *col_property;
};
struct bshell_table_ctx {
const struct bshell_table *ctx_fmt;
struct bshell_table_ctx_column *ctx_columns;
size_t ctx_columns_count;
unsigned int ctx_tty_width;
size_t ctx_variable_columns_count;
fx_stream *ctx_out;
};
struct bshell_value_writer {
struct bshell_table_ctx w_table_ctx;
enum bshell_value_writer_flags w_flags;
size_t w_max_width;
bool w_table_initialised;
fx_stringstream *w_tmp;
fx_stream *w_dest;
};
extern enum bshell_status bshell_table_init(void);
extern const struct bshell_table *bshell_table_get_for_type(const fx_type *ty);
extern enum bshell_status format_object_table(
fx_object *object,
fx_stream *dest);
extern enum bshell_status format_value_default(
const fx_value *value,
fx_stream *dest);
extern enum bshell_status bshell_table_ctx_init(
struct bshell_table_ctx *ctx,
fx_stream *out);
extern enum bshell_status bshell_table_ctx_cleanup(
struct bshell_table_ctx *ctx);
extern enum bshell_status bshell_table_ctx_prepare_columns_from_format(
struct bshell_table_ctx *ctx,
const fx_type *record_type,
const struct bshell_table *fmt);
extern enum bshell_status bshell_table_ctx_prepare_columns_from_object(
struct bshell_table_ctx *ctx,
const fx_type *record_type);
extern enum bshell_status bshell_table_ctx_print_headers(
struct bshell_table_ctx *ctx);
extern enum bshell_status bshell_table_ctx_print_record(
struct bshell_table_ctx *ctx,
const fx_value *record);
extern void bshell_value_writer_init(
struct bshell_value_writer *w,
enum bshell_value_writer_flags flags,
size_t max_width,
fx_stream *dest);
extern size_t bshell_value_writer_write(
struct bshell_value_writer *w,
const fx_value *value);
extern void bshell_value_writer_cleanup(struct bshell_value_writer *w);
#endif
@@ -0,0 +1,21 @@
#ifndef BSHELL_LINE_EDITOR_CORE_H_
#define BSHELL_LINE_EDITOR_CORE_H_
#include <fx/macros.h>
FX_DECLS_BEGIN;
#define BSHELL_TYPE_LINE_EDITOR_CORE (bshell_line_ed_core_get_type())
FX_DECLARE_TYPE(bshell_line_ed_core);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_line_ed_core)
FX_TYPE_CLASS_DECLARATION_END(bshell_line_ed_core)
extern fx_type_id bshell_line_ed_core_get_type(void);
FX_TYPE_DEFAULT_CONSTRUCTOR(bshell_line_ed_core, BSHELL_TYPE_LINE_EDITOR_CORE);
FX_DECLS_END;
#endif
@@ -0,0 +1,23 @@
#ifndef BSHELL_LINE_EDITOR_HIGHLIGHT_H_
#define BSHELL_LINE_EDITOR_HIGHLIGHT_H_
#include <fx/macros.h>
FX_DECLS_BEGIN;
#define BSHELL_TYPE_LINE_EDITOR_HIGHLIGHT (bshell_line_ed_highlight_get_type())
FX_DECLARE_TYPE(bshell_line_ed_highlight);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_line_ed_highlight)
FX_TYPE_CLASS_DECLARATION_END(bshell_line_ed_highlight)
extern fx_type_id bshell_line_ed_highlight_get_type(void);
FX_TYPE_DEFAULT_CONSTRUCTOR(
bshell_line_ed_highlight,
BSHELL_TYPE_LINE_EDITOR_HIGHLIGHT);
FX_DECLS_END;
#endif
@@ -0,0 +1,23 @@
#ifndef BSHELL_LINE_EDITOR_HISTORY_H_
#define BSHELL_LINE_EDITOR_HISTORY_H_
#include <fx/macros.h>
FX_DECLS_BEGIN;
#define BSHELL_TYPE_LINE_EDITOR_HISTORY (bshell_line_ed_history_get_type())
FX_DECLARE_TYPE(bshell_line_ed_history);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_line_ed_history)
FX_TYPE_CLASS_DECLARATION_END(bshell_line_ed_history)
extern fx_type_id bshell_line_ed_history_get_type(void);
FX_TYPE_DEFAULT_CONSTRUCTOR(
bshell_line_ed_history,
BSHELL_TYPE_LINE_EDITOR_HISTORY);
FX_DECLS_END;
#endif
@@ -0,0 +1,44 @@
#ifndef BSHELL_LINE_EDITOR_KEYBIND_H_
#define BSHELL_LINE_EDITOR_KEYBIND_H_
#include <bshell/status.h>
#include <fx/macros.h>
#include <fx/term/tty.h>
FX_DECLS_BEGIN;
#define BSHELL_LINE_EDITOR_KEYBIND_RESULT(status, action) \
((struct bshell_line_ed_keybind_result) { \
.r_status = (status), \
.r_action = (action), \
})
typedef FX_TYPE_FWDREF(bshell_line_ed) bshell_line_ed;
struct bshell_line_ed_keybind_result {
enum bshell_status r_status;
enum {
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE = 0,
BSHELL_LINE_EDITOR_KEYBIND_STOP,
} r_action;
};
typedef struct bshell_line_ed_keybind_result (
*bshell_line_ed_keybind_callback_t)(bshell_line_ed *, fx_keycode);
#define BSHELL_TYPE_LINE_EDITOR_KEYBIND (bshell_line_ed_keybind_get_type())
FX_DECLARE_TYPE(bshell_line_ed_keybind);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_line_ed_keybind)
FX_TYPE_CLASS_DECLARATION_END(bshell_line_ed_keybind)
extern fx_type_id bshell_line_ed_keybind_get_type(void);
FX_TYPE_DEFAULT_CONSTRUCTOR(
bshell_line_ed_keybind,
BSHELL_TYPE_LINE_EDITOR_KEYBIND);
FX_DECLS_END;
#endif
@@ -0,0 +1,68 @@
#ifndef BSHELL_LINE_EDITOR_H_
#define BSHELL_LINE_EDITOR_H_
#include <bshell/line-editor/keybind.h>
#include <bshell/line-editor/plugin.h>
#include <fx/macros.h>
#include <fx/string.h>
#include <fx/term/tty.h>
FX_DECLS_BEGIN;
#define BSHELL_TYPE_LINE_EDITOR (bshell_line_ed_get_type())
FX_DECLARE_TYPE(bshell_line_ed);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_line_ed)
FX_TYPE_CLASS_DECLARATION_END(bshell_line_ed)
extern fx_type_id bshell_line_ed_get_type(void);
FX_TYPE_DEFAULT_CONSTRUCTOR(bshell_line_ed, BSHELL_TYPE_LINE_EDITOR);
extern enum bshell_status bshell_line_ed_readline(
bshell_line_ed *ed,
fx_string *out);
extern struct bshell_line_source *bshell_line_ed_get_line_source(
bshell_line_ed *ed);
extern bshell_line_ed_keybind *bshell_line_ed_bind_key(
bshell_line_ed *ed,
const char *key,
bshell_line_ed_keybind_callback_t callback,
unsigned long priority);
extern enum bshell_status bshell_line_ed_unbind_key(
bshell_line_ed *ed,
bshell_line_ed_keybind *bind);
extern unsigned long bshell_line_ed_get_cursor(const bshell_line_ed *ed);
extern void bshell_line_ed_set_cursor(bshell_line_ed *ed, unsigned long cursor);
extern unsigned long bshell_line_ed_move_cursor(
bshell_line_ed *ed,
long move_amount);
extern enum bshell_status bshell_line_ed_set_done(bshell_line_ed *ed);
extern enum bshell_status bshell_line_ed_set_eof(bshell_line_ed *ed);
extern bool bshell_line_ed_is_done(const bshell_line_ed *ed);
extern bool bshell_line_ed_is_eof(const bshell_line_ed *ed);
extern fx_string *bshell_line_ed_get_prompt(bshell_line_ed *ed);
extern fx_string *bshell_line_ed_get_buffer(bshell_line_ed *ed);
extern fx_tty *bshell_line_ed_get_tty(bshell_line_ed *ed);
extern fx_value bshell_line_ed_get_data(
const bshell_line_ed *ed,
const char *key);
extern void bshell_line_ed_put_data(
bshell_line_ed *ed,
const char *key,
fx_value value);
extern void bshell_line_ed_buffer_changed(bshell_line_ed *ed);
extern enum bshell_status bshell_line_ed_add_plugin(
bshell_line_ed *ed,
bshell_line_ed_plugin *plugin);
FX_DECLS_END;
#endif
@@ -0,0 +1,42 @@
#ifndef BSHELL_LINE_EDITOR_PLUGIN_H_
#define BSHELL_LINE_EDITOR_PLUGIN_H_
#include <bshell/status.h>
#include <fx/macros.h>
#include <fx/value.h>
FX_DECLS_BEGIN;
typedef FX_TYPE_FWDREF(bshell_line_ed) bshell_line_ed;
#define BSHELL_TYPE_LINE_EDITOR_PLUGIN (bshell_line_ed_plugin_get_type())
FX_DECLARE_TYPE(bshell_line_ed_plugin);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_line_ed_plugin)
enum bshell_status (*p_load)(bshell_line_ed_plugin *, bshell_line_ed *);
enum bshell_status (
*p_unload)(bshell_line_ed_plugin *, bshell_line_ed *);
enum bshell_status (
*p_render_prompt)(bshell_line_ed_plugin *, bshell_line_ed *);
enum bshell_status (
*p_render_buffer)(bshell_line_ed_plugin *, bshell_line_ed *);
enum bshell_status (
*p_buffer_changed)(bshell_line_ed_plugin *, bshell_line_ed *);
enum bshell_status (*p_get_data)(
bshell_line_ed_plugin *,
bshell_line_ed *,
const char *,
fx_value *);
enum bshell_status (*p_put_data)(
bshell_line_ed_plugin *,
bshell_line_ed *,
const char *,
const fx_value *);
FX_TYPE_CLASS_DECLARATION_END(bshell_line_ed_plugin)
extern fx_type_id bshell_line_ed_plugin_get_type(void);
FX_DECLS_END;
#endif
@@ -0,0 +1,25 @@
#ifndef BSHELL_LINE_EDITOR_SHELL_INTEGRATION_H_
#define BSHELL_LINE_EDITOR_SHELL_INTEGRATION_H_
#include <fx/macros.h>
FX_DECLS_BEGIN;
struct bshell_runtime;
#define BSHELL_TYPE_LINE_EDITOR_SHELL_INTEGRATION \
(bshell_line_ed_shell_integration_get_type())
FX_DECLARE_TYPE(bshell_line_ed_shell_integration);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_line_ed_shell_integration)
FX_TYPE_CLASS_DECLARATION_END(bshell_line_ed_shell_integration)
extern fx_type_id bshell_line_ed_shell_integration_get_type(void);
extern bshell_line_ed_shell_integration *bshell_line_ed_shell_integration_create(
struct bshell_runtime *rt);
FX_DECLS_END;
#endif
@@ -0,0 +1,23 @@
#ifndef BSHELL_LINE_EDITOR_SYNTAX_H_
#define BSHELL_LINE_EDITOR_SYNTAX_H_
#include <fx/macros.h>
FX_DECLS_BEGIN;
#define BSHELL_TYPE_LINE_EDITOR_SYNTAX (bshell_line_ed_syntax_get_type())
FX_DECLARE_TYPE(bshell_line_ed_syntax);
FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_line_ed_syntax)
FX_TYPE_CLASS_DECLARATION_END(bshell_line_ed_syntax)
extern fx_type_id bshell_line_ed_syntax_get_type(void);
FX_TYPE_DEFAULT_CONSTRUCTOR(
bshell_line_ed_syntax,
BSHELL_TYPE_LINE_EDITOR_SYNTAX);
FX_DECLS_END;
#endif
@@ -0,0 +1,40 @@
#ifndef BSHELL_LINE_SOURCE_H_
#define BSHELL_LINE_SOURCE_H_
#include "status.h"
#include <fx/stringstream.h>
#include <stddef.h>
struct bshell_line_source {
enum bshell_status (*s_get_name)(
struct bshell_line_source *,
char *,
size_t,
size_t *);
enum bshell_status (
*s_readline)(struct bshell_line_source *, fx_stringstream *);
enum bshell_status (*s_get_row)(
struct bshell_line_source *,
size_t,
char *,
size_t,
size_t *);
};
extern enum bshell_status bshell_line_source_get_name(
struct bshell_line_source *src,
char *buf,
size_t count,
size_t *nr_read);
extern enum bshell_status bshell_line_source_readline(
struct bshell_line_source *src,
fx_stringstream *out);
extern enum bshell_status bshell_line_source_get_row(
struct bshell_line_source *src,
size_t row,
char *buf,
size_t count,
size_t *nr_read);
#endif
+97
View File
@@ -0,0 +1,97 @@
#ifndef BSHELL_PARSE_LEX_H_
#define BSHELL_PARSE_LEX_H_
#include <bshell/parse/token.h>
#include <bshell/status.h>
#include <fx/queue.h>
#include <fx/string.h>
#include <fx/stringstream.h>
#define BSHELL_LEX_STATE_MAX_TERMINATORS 16
struct bshell_line_source;
enum bshell_lex_flags {
LEX_PRINT_TOKENS = 0x01u,
};
enum bshell_lex_token_flags {
/* a token with this flag not only interrupts the word currently being
* scanned, but also stops multi-words */
BSHELL_LEX_TOKEN_TERMINATES_WORD = 0x01u,
/* a token with this flag can appear at the start of an arithmetic
* expression. a statement that encounters this token as its first char
* will switch to arithmetic mode */
BSHELL_LEX_TOKEN_UNARY_ARITHMETIC = 0x02u,
/* if a token has this flag defined, the lexer will
* switch to command mode after encountering it. */
BSHELL_LEX_TOKEN_COMMAND_MODE = 0x08u,
/* if a token has this flag defined, the lexer will
* switch to statement mode after encountering it. */
BSHELL_LEX_TOKEN_STATEMENT_MODE = 0x10u,
};
enum bshell_lex_state_id {
BSHELL_LEX_STATE_STATEMENT = 0x01u,
BSHELL_LEX_STATE_COMMAND = 0x02u,
BSHELL_LEX_STATE_ARITHMETIC = 0x04u,
BSHELL_LEX_STATE_STRING = 0x08u,
BSHELL_LEX_STATE_WORD = 0x10u,
BSHELL_LEX_STATE_HASHTABLE = 0x20u,
};
struct bshell_lex_token_definition {
int id;
const char *name;
uint64_t name_hash;
enum bshell_lex_state_id enabled_states;
enum bshell_lex_token_flags flags;
};
struct bshell_lex_symbol_node {
char s_char;
struct bshell_lex_token_definition *s_def;
fx_queue_entry s_entry;
fx_queue s_children;
};
struct bshell_lex_state {
const struct bshell_lex_state_type *s_type;
unsigned int s_terminators[BSHELL_LEX_STATE_MAX_TERMINATORS];
unsigned int s_nr_terminators;
unsigned int s_paren_depth;
fx_queue_entry s_entry;
fx_string *s_tempstr;
unsigned int s_flags;
};
struct bshell_lex_ctx {
enum bshell_lex_flags lex_flags;
fx_queue lex_tokens;
struct bshell_line_source *lex_src;
fx_stringstream *lex_buf;
fx_string *lex_tmp;
fx_wchar lex_ch;
fx_queue lex_state;
void (*lex_token_scanned)(
struct bshell_lex_ctx *,
struct bshell_lex_token *);
enum bshell_lex_token_type lex_prev_token;
struct bshell_char_cell lex_cursor, lex_start, lex_end;
struct bshell_lex_symbol_node *lex_sym_tree;
enum bshell_status lex_status;
};
extern enum bshell_status bshell_lex_ctx_init(
struct bshell_lex_ctx *ctx,
enum bshell_lex_flags flags,
struct bshell_line_source *src);
extern enum bshell_status bshell_lex_ctx_cleanup(struct bshell_lex_ctx *ctx);
extern struct bshell_lex_token *bshell_lex_ctx_peek(struct bshell_lex_ctx *ctx);
extern struct bshell_lex_token *bshell_lex_ctx_claim(
struct bshell_lex_ctx *ctx);
extern void bshell_lex_ctx_discard(struct bshell_lex_ctx *ctx);
#endif
@@ -0,0 +1,22 @@
#ifndef BSHELL_PARSE_PARSE_H_
#define BSHELL_PARSE_PARSE_H_
#include <bshell/status.h>
struct bshell_lex_ctx;
struct bshell_ast_node;
struct bshell_parse_ctx {
struct bshell_lex_ctx *p_src;
enum bshell_status p_status;
};
extern enum bshell_status bshell_parse_ctx_init(
struct bshell_parse_ctx *ctx,
struct bshell_lex_ctx *src);
extern void bshell_parse_ctx_cleanup(struct bshell_parse_ctx *ctx);
extern struct bshell_ast_node *bshell_parse_ctx_read_node(
struct bshell_parse_ctx *ctx);
#endif
+190
View File
@@ -0,0 +1,190 @@
#ifndef BSHELL_PARSE_TOKEN_H_
#define BSHELL_PARSE_TOKEN_H_
#include <fx/queue.h>
#include <fx/value.h>
#include <stdbool.h>
struct bshell_char_cell {
unsigned long c_row, c_col;
};
enum bshell_lex_token_type {
BSHELL_TOK_NONE = 0,
__BSHELL_TOK_INDEX_BASE = 100,
BSHELL_TOK_KEYWORD,
BSHELL_TOK_SYMBOL,
BSHELL_TOK_INT,
BSHELL_TOK_DOUBLE,
BSHELL_TOK_WORD,
BSHELL_TOK_WORD_START,
BSHELL_TOK_WORD_END,
BSHELL_TOK_FLAG,
BSHELL_TOK_OPERATOR,
BSHELL_TOK_VAR,
BSHELL_TOK_VAR_SPLAT,
BSHELL_TOK_STRING,
BSHELL_TOK_STR_START,
BSHELL_TOK_STR_END,
BSHELL_TOK_LINEFEED,
__BSHELL_TOK_INDEX_LIMIT,
};
enum bshell_lex_keyword {
BSHELL_KW_NONE = 0,
__BSHELL_KW_INDEX_BASE = 200,
BSHELL_KW_FUNC,
BSHELL_KW_IF,
BSHELL_KW_ELSEIF,
BSHELL_KW_ELSE,
__BSHELL_KW_INDEX_LIMIT,
};
enum bshell_lex_operator {
BSHELL_TKOP_NONE = 0,
__BSHELL_TKOP_INDEX_BASE = 300,
BSHELL_TKOP_F,
BSHELL_TKOP_BAND,
BSHELL_TKOP_BOR,
BSHELL_TKOP_BXOR,
BSHELL_TKOP_BNOT,
BSHELL_TKOP_SHL,
BSHELL_TKOP_SHR,
BSHELL_TKOP_EQ,
BSHELL_TKOP_NE,
BSHELL_TKOP_GT,
BSHELL_TKOP_LT,
BSHELL_TKOP_GE,
BSHELL_TKOP_LE,
BSHELL_TKOP_MATCH,
BSHELL_TKOP_NOTMATCH,
BSHELL_TKOP_REPLACE,
BSHELL_TKOP_LIKE,
BSHELL_TKOP_NOTLIKE,
BSHELL_TKOP_IN,
BSHELL_TKOP_NOTIN,
BSHELL_TKOP_CONTAINS,
BSHELL_TKOP_NOTCONTAINS,
BSHELL_TKOP_AND,
BSHELL_TKOP_OR,
BSHELL_TKOP_XOR,
BSHELL_TKOP_NOT,
BSHELL_TKOP_SPLIT,
BSHELL_TKOP_JOIN,
BSHELL_TKOP_IS,
BSHELL_TKOP_ISNOT,
BSHELL_TKOP_AS,
__BSHELL_TKOP_INDEX_LIMIT,
};
enum bshell_lex_symbol {
BSHELL_SYM_NONE = 0,
__BSHELL_SYM_INDEX_BASE = 400,
BSHELL_SYM_BANG,
BSHELL_SYM_PLUS,
BSHELL_SYM_HYPHEN,
BSHELL_SYM_FORWARD_SLASH,
BSHELL_SYM_ASTERISK,
BSHELL_SYM_AMPERSAND,
BSHELL_SYM_PERCENT,
BSHELL_SYM_SQUOTE,
BSHELL_SYM_DQUOTE,
BSHELL_SYM_HASH,
BSHELL_SYM_COLON_COLON,
BSHELL_SYM_SEMICOLON,
BSHELL_SYM_COMMA,
BSHELL_SYM_DOLLAR,
BSHELL_SYM_DOLLAR_LEFT_PAREN,
BSHELL_SYM_DOLLAR_LEFT_BRACE,
BSHELL_SYM_DOT,
BSHELL_SYM_DOT_DOT,
BSHELL_SYM_PIPE,
BSHELL_SYM_AT,
BSHELL_SYM_AT_LEFT_PAREN,
BSHELL_SYM_AT_LEFT_BRACE,
BSHELL_SYM_LEFT_BRACE,
BSHELL_SYM_RIGHT_BRACE,
BSHELL_SYM_LEFT_BRACKET,
BSHELL_SYM_RIGHT_BRACKET,
BSHELL_SYM_LEFT_PAREN,
BSHELL_SYM_RIGHT_PAREN,
BSHELL_SYM_EQUAL,
BSHELL_SYM_PLUS_EQUAL,
BSHELL_SYM_HYPHEN_EQUAL,
BSHELL_SYM_ASTERISK_EQUAL,
BSHELL_SYM_FORWARD_SLASH_EQUAL,
BSHELL_SYM_PERCENT_EQUAL,
BSHELL_SYM_QUESTION_DOT,
BSHELL_SYM_QUESTION_LEFT_BRACKET,
__BSHELL_SYM_INDEX_LIMIT,
};
struct bshell_lex_token {
enum bshell_lex_token_type tok_type;
struct bshell_char_cell tok_start, tok_end;
fx_queue_entry tok_entry;
union {
enum bshell_lex_keyword tok_keyword;
enum bshell_lex_symbol tok_symbol;
enum bshell_lex_operator tok_operator;
fx_value tok_number;
char *tok_str;
};
};
extern struct bshell_lex_token *bshell_lex_token_create(
enum bshell_lex_token_type type);
extern struct bshell_lex_token *bshell_lex_token_create_with_string(
enum bshell_lex_token_type type,
const char *s);
extern void bshell_lex_token_destroy(struct bshell_lex_token *tok);
extern struct bshell_lex_token *bshell_lex_token_change_type(
struct bshell_lex_token *tok,
enum bshell_lex_token_type new_type);
extern void bshell_lex_token_change_string(
struct bshell_lex_token *tok,
const char *s);
static inline bool bshell_lex_token_is_symbol(
struct bshell_lex_token *tok,
enum bshell_lex_symbol sym)
{
return (tok->tok_type == BSHELL_TOK_SYMBOL && tok->tok_symbol == sym);
}
static inline bool bshell_lex_token_is_keyword(
struct bshell_lex_token *tok,
enum bshell_lex_keyword kw)
{
return (tok->tok_type == BSHELL_TOK_KEYWORD && tok->tok_keyword == kw);
}
static inline bool bshell_lex_token_type_has_string_value(
enum bshell_lex_token_type type)
{
switch (type) {
case BSHELL_TOK_WORD:
case BSHELL_TOK_STRING:
case BSHELL_TOK_FLAG:
case BSHELL_TOK_VAR:
case BSHELL_TOK_VAR_SPLAT:
return true;
default:
return false;
}
}
static inline bool bshell_lex_token_has_string_value(
const struct bshell_lex_token *tok)
{
return bshell_lex_token_type_has_string_value(tok->tok_type);
}
extern const char *bshell_token_type_to_string(enum bshell_lex_token_type type);
extern const char *bshell_lex_keyword_to_string(
enum bshell_lex_keyword keyword);
extern const char *bshell_lex_symbol_to_string(enum bshell_lex_symbol sym);
extern const char *bshell_lex_operator_to_string(enum bshell_lex_operator op);
#endif
@@ -1,5 +1,5 @@
#ifndef RUNTIME_CMDCALL_H_ #ifndef BSHELL_RUNTIME_CMDCALL_H_
#define RUNTIME_CMDCALL_H_ #define BSHELL_RUNTIME_CMDCALL_H_
#include <fx/macros.h> #include <fx/macros.h>
#include <fx/value.h> #include <fx/value.h>
@@ -8,6 +8,14 @@ FX_DECLS_BEGIN;
struct bshell_runtime; struct bshell_runtime;
enum bshell_command_position;
enum bshell_cmdcall_type {
BSHELL_CMDCALL_NONE = 0,
BSHELL_CMDCALL_CMDLET,
BSHELL_CMDCALL_NATIVE,
};
#define BSHELL_TYPE_CMDCALL (bshell_cmdcall_get_type()) #define BSHELL_TYPE_CMDCALL (bshell_cmdcall_get_type())
FX_DECLARE_TYPE(bshell_cmdcall); FX_DECLARE_TYPE(bshell_cmdcall);
@@ -19,6 +27,9 @@ extern fx_type_id bshell_cmdcall_get_type(void);
FX_TYPE_DEFAULT_CONSTRUCTOR(bshell_cmdcall, BSHELL_TYPE_CMDCALL); FX_TYPE_DEFAULT_CONSTRUCTOR(bshell_cmdcall, BSHELL_TYPE_CMDCALL);
extern enum bshell_cmdcall_type bshell_cmdcall_get_target_type(
const bshell_cmdcall *cmdcall);
extern enum bshell_status bshell_cmdcall_push_arg( extern enum bshell_status bshell_cmdcall_push_arg(
bshell_cmdcall *cmdcall, bshell_cmdcall *cmdcall,
fx_value arg); fx_value arg);
@@ -29,7 +40,8 @@ extern enum bshell_status bshell_cmdcall_resolve(
extern enum bshell_status bshell_cmdcall_process_record( extern enum bshell_status bshell_cmdcall_process_record(
bshell_cmdcall *cmdcall, bshell_cmdcall *cmdcall,
FX_TYPE_FWDREF(bshell_pipeline) * pipeline, FX_TYPE_FWDREF(bshell_pipeline) * pipeline,
struct bshell_runtime *rt); struct bshell_runtime *rt,
enum bshell_command_position position);
FX_DECLS_END; FX_DECLS_END;
@@ -0,0 +1,82 @@
#ifndef BSHELL_RUNTIME_OPCODE_H_
#define BSHELL_RUNTIME_OPCODE_H_
#include <stdint.h>
#define BSHELL_INSTRUCTION_INVALID 0xFFFFFFFF
typedef uint32_t bshell_instruction;
enum bshell_opcode {
BSHELL_OPCODE_NOP = 0,
BSHELL_OPCODE_LDC_INT,
BSHELL_OPCODE_LDC_STR,
BSHELL_OPCODE_LDC_FP,
BSHELL_OPCODE_LDGLOBAL,
BSHELL_OPCODE_LDLOCAL,
BSHELL_OPCODE_LDBLOCK,
BSHELL_OPCODE_LDENV,
BSHELL_OPCODE_LDSTATIC,
BSHELL_OPCODE_LDARG,
BSHELL_OPCODE_LDPROP,
BSHELL_OPCODE_LDELEM,
BSHELL_OPCODE_LDELEM_C,
BSHELL_OPCODE_STLOCAL,
BSHELL_OPCODE_STPROP,
BSHELL_OPCODE_STELEM,
BSHELL_OPCODE_LDCMD,
BSHELL_OPCODE_PEXEC,
BSHELL_OPCODE_CALL,
BSHELL_OPCODE_MK_STR,
BSHELL_OPCODE_MK_ARRAY,
BSHELL_OPCODE_MK_HTAB,
BSHELL_OPCODE_POP,
BSHELL_OPCODE_ADD,
BSHELL_OPCODE_SUB,
BSHELL_OPCODE_MUL,
BSHELL_OPCODE_DIV,
BSHELL_OPCODE_ADD_IP,
BSHELL_OPCODE_MOD,
BSHELL_OPCODE_INC,
BSHELL_OPCODE_DEC,
BSHELL_OPCODE_SHL,
BSHELL_OPCODE_SHR,
BSHELL_OPCODE_BAND,
BSHELL_OPCODE_BOR,
BSHELL_OPCODE_BXOR,
BSHELL_OPCODE_BNOT,
BSHELL_OPCODE_CMP_NULL,
BSHELL_OPCODE_CMP_EQ,
BSHELL_OPCODE_CMP_NE,
BSHELL_OPCODE_CMP_LT,
BSHELL_OPCODE_CMP_GT,
BSHELL_OPCODE_CMP_LE,
BSHELL_OPCODE_CMP_GE,
BSHELL_OPCODE_LAND,
BSHELL_OPCODE_LOR,
BSHELL_OPCODE_LXOR,
BSHELL_OPCODE_LNOT,
BSHELL_OPCODE_BR,
BSHELL_OPCODE_BR_TRUE,
BSHELL_OPCODE_RANGE,
BSHELL_OPCODE_MATCH,
BSHELL_OPCODE_REPLACE,
BSHELL_OPCODE_LIKE,
BSHELL_OPCODE_IN,
BSHELL_OPCODE_FMT,
BSHELL_OPCODE_CONTAINS,
BSHELL_OPCODE_SPLIT,
BSHELL_OPCODE_JOIN,
BSHELL_OPCODE_IS,
BSHELL_OPCODE_AS,
};
extern bshell_instruction bshell_instruction_encode(
enum bshell_opcode opcode,
uint32_t arg);
extern void bshell_instruction_decode(
bshell_instruction instr,
enum bshell_opcode *out_opcode,
uint32_t *out_arg);
#endif
@@ -0,0 +1,126 @@
#ifndef BSHELL_RUNTIME_OPERATOR_H_
#define BSHELL_RUNTIME_OPERATOR_H_
enum bshell_operator_precedence {
BSHELL_PRECEDENCE_MINIMUM = 0,
BSHELL_PRECEDENCE_ASSIGN,
BSHELL_PRECEDENCE_PIPELINE,
BSHELL_PRECEDENCE_LOGICAL,
BSHELL_PRECEDENCE_BITWISE,
BSHELL_PRECEDENCE_COMPARISON,
BSHELL_PRECEDENCE_ADDITION,
BSHELL_PRECEDENCE_MULTIPLICATION,
BSHELL_PRECEDENCE_NEGATE,
BSHELL_PRECEDENCE_FORMAT,
BSHELL_PRECEDENCE_RANGE,
BSHELL_PRECEDENCE_NOT,
BSHELL_PRECEDENCE_INCREMENT,
BSHELL_PRECEDENCE_ARRAY,
BSHELL_PRECEDENCE_JOIN,
BSHELL_PRECEDENCE_SPLIT,
BSHELL_PRECEDENCE_CAST,
BSHELL_PRECEDENCE_SUBSCRIPT,
BSHELL_PRECEDENCE_STATIC_ACCESS,
BSHELL_PRECEDENCE_MEMBER_ACCESS,
BSHELL_PRECEDENCE_PARENTHESIS,
};
enum bshell_operator_associativity {
BSHELL_ASSOCIATIVITY_LEFT,
BSHELL_ASSOCIATIVITY_RIGHT,
};
enum bshell_operator_location {
BSHELL_OPL_PREFIX,
BSHELL_OPL_INFIX,
BSHELL_OPL_POSTFIX,
};
enum bshell_operator_arity {
BSHELL_OPA_UNARY,
BSHELL_OPA_BINARY,
};
enum bshell_operator_id {
BSHELL_OP_NONE = 0,
BSHELL_OP_ADD,
BSHELL_OP_SUBTRACT,
BSHELL_OP_MULTIPLY,
BSHELL_OP_DIVIDE,
BSHELL_OP_MODULO,
BSHELL_OP_INCREMENT,
BSHELL_OP_DECREMENT,
BSHELL_OP_LEFT_SHIFT,
BSHELL_OP_RIGHT_SHIFT,
BSHELL_OP_BINARY_AND,
BSHELL_OP_BINARY_OR,
BSHELL_OP_BINARY_XOR,
BSHELL_OP_BINARY_NOT,
BSHELL_OP_LESS_THAN,
BSHELL_OP_GREATER_THAN,
BSHELL_OP_EQUAL,
BSHELL_OP_NOT_EQUAL,
BSHELL_OP_LESS_EQUAL,
BSHELL_OP_GREATER_EQUAL,
BSHELL_OP_ASSIGN,
BSHELL_OP_ADD_ASSIGN,
BSHELL_OP_SUBTRACT_ASSIGN,
BSHELL_OP_MULTIPLY_ASSIGN,
BSHELL_OP_DIVIDE_ASSIGN,
BSHELL_OP_MODULO_ASSIGN,
BSHELL_OP_LOGICAL_AND,
BSHELL_OP_LOGICAL_OR,
BSHELL_OP_LOGICAL_XOR,
BSHELL_OP_LOGICAL_NOT,
BSHELL_OP_RANGE,
BSHELL_OP_MATCH,
BSHELL_OP_NOTMATCH,
BSHELL_OP_REPLACE,
BSHELL_OP_LIKE,
BSHELL_OP_NOTLIKE,
BSHELL_OP_IN,
BSHELL_OP_NOTIN,
BSHELL_OP_FORMAT,
BSHELL_OP_CONTAINS,
BSHELL_OP_NOTCONTAINS,
BSHELL_OP_USPLIT,
BSHELL_OP_BSPLIT,
BSHELL_OP_UJOIN,
BSHELL_OP_BJOIN,
BSHELL_OP_IS,
BSHELL_OP_ISNOT,
BSHELL_OP_AS,
BSHELL_OP_SUBSCRIPT,
BSHELL_OP_CONDITIONAL_SUBSCRIPT,
BSHELL_OP_ARRAY_DELIMITER,
BSHELL_OP_ACCESS,
BSHELL_OP_STATIC_ACCESS,
BSHELL_OP_CONDITIONAL_ACCESS,
/* these are not real operators, and are just used internally by the
* parser. */
BSHELL_OP_CAST,
BSHELL_OP_SUBEXPR,
BSHELL_OP_PAREN,
BSHELL_OP_SCRIPTBLOCK,
BSHELL_OP_ARRAY_START,
BSHELL_OP_HASHTABLE_START,
};
struct bshell_operator_info {
enum bshell_operator_id op_id;
enum bshell_operator_precedence op_precedence;
enum bshell_operator_associativity op_associativity;
enum bshell_operator_location op_location;
enum bshell_operator_arity op_arity;
};
extern const struct bshell_operator_info *bshell_operator_get_by_id(
enum bshell_operator_id id);
extern const struct bshell_operator_info *bshell_operator_get_by_token(
unsigned int token);
extern const char *bshell_operator_id_to_string(enum bshell_operator_id op);
#endif
@@ -1,5 +1,5 @@
#ifndef RUNTIME_PIPELINE_H_ #ifndef BSHELL_RUNTIME_PIPELINE_H_
#define RUNTIME_PIPELINE_H_ #define BSHELL_RUNTIME_PIPELINE_H_
#include "../command/command.h" #include "../command/command.h"
#include "../runtime/cmdcall.h" #include "../runtime/cmdcall.h"
@@ -0,0 +1,63 @@
#ifndef BSHELL_RUNTIME_RUNTIME_H_
#define BSHELL_RUNTIME_RUNTIME_H_
#include <bshell/command/command.h>
#include <bshell/command/function.h>
#include <bshell/format.h>
#include <bshell/runtime/script-block.h>
#include <bshell/runtime/var.h>
#include <fx/collections/hashtable.h>
#include <fx/queue.h>
#include <fx/value.h>
struct bshell_runtime_scope;
struct bshell_runtime {
struct bshell_runtime_scope *rt_global;
fx_hashtable *rt_aliases;
fx_queue rt_scope;
struct bshell_value_writer rt_writer;
};
extern struct bshell_runtime *bshell_runtime_create(void);
extern void bshell_runtime_destroy(struct bshell_runtime *rt);
extern fx_value bshell_runtime_eval_global(
struct bshell_runtime *rt,
bshell_scriptblock *block);
extern fx_value bshell_runtime_eval_script(
struct bshell_runtime *rt,
bshell_scriptblock *block);
extern bshell_variable *bshell_runtime_find_var(
struct bshell_runtime *rt,
const char *name);
extern enum bshell_status bshell_runtime_define_function(
struct bshell_runtime *rt,
bshell_function *func);
extern bshell_command *bshell_runtime_find_command(
struct bshell_runtime *rt,
const char *callable_name);
extern enum bshell_status bshell_runtime_push_scope(
struct bshell_runtime *rt,
bshell_scriptblock *block);
extern enum bshell_status bshell_runtime_pop_scope(struct bshell_runtime *rt);
extern fx_value bshell_runtime_eval(struct bshell_runtime *rt);
extern struct bshell_runtime_scope *bshell_runtime_get_global_scope(
struct bshell_runtime *rt);
extern struct bshell_runtime_scope *bshell_runtime_get_current_scope(
struct bshell_runtime *rt);
extern struct bshell_runtime_scope *bshell_runtime_get_parent_scope(
struct bshell_runtime *rt,
struct bshell_runtime_scope *scope);
extern void bshell_runtime_begin_output(struct bshell_runtime *rt);
extern void bshell_runtime_output_value(
struct bshell_runtime *rt,
const fx_value *value);
extern void bshell_runtime_end_output(struct bshell_runtime *rt);
#endif
@@ -0,0 +1,15 @@
#ifndef BSHELL_RUNTIME_SCOPE_H_
#define BSHELL_RUNTIME_SCOPE_H_
#include <bshell/runtime/var.h>
#include <fx/collections/hashtable.h>
struct bshell_runtime_scope;
extern fx_hashtable *bshell_runtime_scope_get_functions(
struct bshell_runtime_scope *scope);
extern bshell_variable *bshell_runtime_scope_define_variable(
struct bshell_runtime_scope *scope,
const char *name);
#endif
@@ -1,8 +1,7 @@
#ifndef SCRIPT_BLOCK_H_ #ifndef BSHELL_RUNTIME_SCRIPT_BLOCK_H_
#define SCRIPT_BLOCK_H_ #define BSHELL_RUNTIME_SCRIPT_BLOCK_H_
#include "runtime/opcode.h"
#include <bshell/runtime/opcode.h>
#include <fx/macros.h> #include <fx/macros.h>
#include <fx/value.h> #include <fx/value.h>
@@ -1,5 +1,5 @@
#ifndef RUNTIME_VAR_H_ #ifndef BSHELL_RUNTIME_VAR_H_
#define RUNTIME_VAR_H_ #define BSHELL_RUNTIME_VAR_H_
#include <fx/macros.h> #include <fx/macros.h>
#include <fx/value.h> #include <fx/value.h>
@@ -19,7 +19,7 @@ extern bshell_variable *bshell_variable_create(const char *name);
extern const char *bshell_variable_get_name(const bshell_variable *var); extern const char *bshell_variable_get_name(const bshell_variable *var);
extern const fx_value *bshell_variable_get_value(const bshell_variable *var); extern const fx_value *bshell_variable_get_value(const bshell_variable *var);
extern void bshell_variable_set_value(bshell_variable *var, fx_value *value); extern void bshell_variable_set_value(bshell_variable *var, fx_value value);
FX_DECLS_END; FX_DECLS_END;
@@ -1,5 +1,5 @@
#ifndef STATUS_H_ #ifndef BSHELL_STATUS_H_
#define STATUS_H_ #define BSHELL_STATUS_H_
enum bshell_status { enum bshell_status {
BSHELL_SUCCESS = 0, BSHELL_SUCCESS = 0,
@@ -20,5 +20,6 @@ enum bshell_status {
}; };
extern enum bshell_status bshell_status_from_errno(int err); extern enum bshell_status bshell_status_from_errno(int err);
extern const char *bshell_status_get_description(int err);
#endif #endif
@@ -1,5 +1,5 @@
#ifndef VERB_H_ #ifndef BSHELL_VERB_H_
#define VERB_H_ #define BSHELL_VERB_H_
#include <fx/collections/hashtable.h> #include <fx/collections/hashtable.h>
#include <fx/macros.h> #include <fx/macros.h>
@@ -124,6 +124,8 @@ FX_TYPE_CLASS_DECLARATION_BEGIN(bshell_verb)
FX_TYPE_CLASS_DECLARATION_END(bshell_verb) FX_TYPE_CLASS_DECLARATION_END(bshell_verb)
extern enum bshell_status bshell_init_all_verbs(void); extern enum bshell_status bshell_init_all_verbs(void);
extern enum bshell_status bshell_cleanup_all_verbs(void);
extern fx_hashtable *bshell_get_all_verbs(void); extern fx_hashtable *bshell_get_all_verbs(void);
extern bshell_verb *bshell_verb_get_by_id(enum bshell_verb_id id); extern bshell_verb *bshell_verb_get_by_id(enum bshell_verb_id id);
extern bshell_verb *bshell_verb_get_by_name(const char *name); extern bshell_verb *bshell_verb_get_by_name(const char *name);
+229
View File
@@ -0,0 +1,229 @@
#include <bshell/line-editor/core.h>
#include <bshell/line-editor/line-editor.h>
#include <bshell/line-editor/plugin.h>
#include <fx/collections/hashtable.h>
#include <fx/term/tty.h>
struct bshell_line_ed_core_p {
bshell_line_ed_keybind *c_key_cursor_left;
bshell_line_ed_keybind *c_key_cursor_right;
bshell_line_ed_keybind *c_key_return;
bshell_line_ed_keybind *c_key_eof;
bshell_line_ed_keybind *c_key_generic;
bshell_line_ed_keybind *c_key_backspace;
fx_hashtable *c_data;
};
static void init(fx_object *obj, void *priv)
{
struct bshell_line_ed_core_p *core = priv;
core->c_data = fx_hashtable_create();
}
static void fini(fx_object *obj, void *priv)
{
struct bshell_line_ed_core_p *core = priv;
fx_hashtable_unref(core->c_data);
}
static struct bshell_line_ed_keybind_result delete_backward(
bshell_line_ed *ed,
fx_keycode key)
{
return BSHELL_LINE_EDITOR_KEYBIND_RESULT(
BSHELL_SUCCESS,
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE);
}
static struct bshell_line_ed_keybind_result cursor_left(
bshell_line_ed *ed,
fx_keycode key)
{
bshell_line_ed_move_cursor(ed, -1);
return BSHELL_LINE_EDITOR_KEYBIND_RESULT(
BSHELL_SUCCESS,
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE);
}
static struct bshell_line_ed_keybind_result cursor_right(
bshell_line_ed *ed,
fx_keycode key)
{
bshell_line_ed_move_cursor(ed, 1);
return BSHELL_LINE_EDITOR_KEYBIND_RESULT(
BSHELL_SUCCESS,
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE);
}
static struct bshell_line_ed_keybind_result eof_key(
bshell_line_ed *ed,
fx_keycode key)
{
bshell_line_ed_set_eof(ed);
return BSHELL_LINE_EDITOR_KEYBIND_RESULT(
BSHELL_SUCCESS,
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE);
}
static struct bshell_line_ed_keybind_result return_key(
bshell_line_ed *ed,
fx_keycode key)
{
bshell_line_ed_set_done(ed);
fx_string *buf = bshell_line_ed_get_buffer(ed);
fx_string_append_c(buf, '\n');
return BSHELL_LINE_EDITOR_KEYBIND_RESULT(
BSHELL_SUCCESS,
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE);
}
static struct bshell_line_ed_keybind_result backspace(
bshell_line_ed *ed,
fx_keycode key)
{
fx_string *buf = bshell_line_ed_get_buffer(ed);
unsigned long cursor = bshell_line_ed_get_cursor(ed);
if (cursor > 0) {
fx_string_remove(buf, cursor - 1, 1);
bshell_line_ed_move_cursor(ed, -1);
bshell_line_ed_buffer_changed(ed);
}
return BSHELL_LINE_EDITOR_KEYBIND_RESULT(
BSHELL_SUCCESS,
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE);
}
static struct bshell_line_ed_keybind_result generic_key(
bshell_line_ed *ed,
fx_keycode key)
{
fx_wchar c = key;
bool valid = fx_wchar_utf8_is_valid_scalar(c) && fx_wchar_is_graph(c);
if (valid) {
fx_string *buf = bshell_line_ed_get_buffer(ed);
unsigned long cursor = bshell_line_ed_get_cursor(ed);
char cstr[5] = {0};
fx_string_insert_wc(buf, c, cursor);
bshell_line_ed_move_cursor(ed, 1);
bshell_line_ed_buffer_changed(ed);
}
return BSHELL_LINE_EDITOR_KEYBIND_RESULT(
BSHELL_SUCCESS,
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE);
}
static enum bshell_status load(
bshell_line_ed_plugin *plugin,
bshell_line_ed *ed)
{
struct bshell_line_ed_core_p *core
= fx_object_get_private(plugin, BSHELL_TYPE_LINE_EDITOR_CORE);
core->c_key_eof = bshell_line_ed_bind_key(ed, "^d", eof_key, 100);
core->c_key_cursor_left
= bshell_line_ed_bind_key(ed, "left", cursor_left, 100);
core->c_key_cursor_right
= bshell_line_ed_bind_key(ed, "right", cursor_right, 100);
core->c_key_cursor_right
= bshell_line_ed_bind_key(ed, "return", return_key, 100);
core->c_key_generic
= bshell_line_ed_bind_key(ed, "*", generic_key, 100);
core->c_key_backspace
= bshell_line_ed_bind_key(ed, "backspace", backspace, 100);
return BSHELL_SUCCESS;
}
static enum bshell_status render_prompt(
bshell_line_ed_plugin *plugin,
bshell_line_ed *ed)
{
fx_string *prompt = bshell_line_ed_get_prompt(ed);
fx_tty *tty = bshell_line_ed_get_tty(ed);
const char *s = fx_string_get_cstr(prompt);
fx_tty_puts(tty, 0, s);
return BSHELL_SUCCESS;
}
static enum bshell_status render_buffer(
bshell_line_ed_plugin *plugin,
bshell_line_ed *ed)
{
fx_string *buf = bshell_line_ed_get_buffer(ed);
fx_tty *tty = bshell_line_ed_get_tty(ed);
const char *s = fx_string_get_cstr(buf);
for (unsigned long i = 0; *s; i++) {
fx_wchar c = fx_wchar_utf8_codepoint_decode(s);
unsigned int stride = fx_wchar_utf8_codepoint_size(c);
if (stride == 0) {
break;
}
char cs[5] = {0};
fx_wchar_utf8_codepoint_encode(c, cs);
fx_tty_puts(tty, 0, cs);
s += stride;
}
return BSHELL_SUCCESS;
}
static enum bshell_status get_data(
bshell_line_ed_plugin *plugin,
bshell_line_ed *ed,
const char *key,
fx_value *out)
{
struct bshell_line_ed_core_p *core
= fx_object_get_private(plugin, BSHELL_TYPE_LINE_EDITOR_CORE);
const fx_value *v = fx_hashtable_get(core->c_data, &FX_CSTR(key));
if (v) {
fx_value_copy(out, v);
} else {
*out = FX_VALUE_EMPTY;
}
return BSHELL_SUCCESS;
}
static enum bshell_status put_data(
bshell_line_ed_plugin *plugin,
bshell_line_ed *ed,
const char *key,
const fx_value *value)
{
struct bshell_line_ed_core_p *core
= fx_object_get_private(plugin, BSHELL_TYPE_LINE_EDITOR_CORE);
fx_hashtable_put(core->c_data, &FX_CSTR(key), (fx_value *)value);
return BSHELL_SUCCESS;
}
FX_TYPE_CLASS_BEGIN(bshell_line_ed_core)
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
FX_INTERFACE_ENTRY(to_string) = NULL;
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
FX_TYPE_VTABLE_INTERFACE_BEGIN(
bshell_line_ed_plugin,
BSHELL_TYPE_LINE_EDITOR_PLUGIN)
FX_INTERFACE_ENTRY(p_load) = load;
FX_INTERFACE_ENTRY(p_render_prompt) = render_prompt;
FX_INTERFACE_ENTRY(p_render_buffer) = render_buffer;
FX_INTERFACE_ENTRY(p_get_data) = get_data;
FX_INTERFACE_ENTRY(p_put_data) = put_data;
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
FX_TYPE_CLASS_END(bshell_line_ed_core)
FX_TYPE_DEFINITION_BEGIN(bshell_line_ed_core)
FX_TYPE_ID(0xf5174a63, 0x8fe4, 0x4720, 0xa861, 0x4ebb0d170dd3);
FX_TYPE_NAME("bshell.runtime.line_editor.plugins.core");
FX_TYPE_EXTENDS(BSHELL_TYPE_LINE_EDITOR_PLUGIN);
FX_TYPE_CLASS(bshell_line_ed_core_class);
FX_TYPE_INSTANCE_INIT(init);
FX_TYPE_INSTANCE_FINI(fini);
FX_TYPE_INSTANCE_PRIVATE(struct bshell_line_ed_core_p);
FX_TYPE_DEFINITION_END(bshell_line_ed_core)
+105
View File
@@ -0,0 +1,105 @@
#include "line-editor.h"
#include <fx/encoding.h>
static void convert_offset_to_xy(
struct bshell_line_ed_p *ed,
unsigned long offset,
unsigned long *out_x,
unsigned long *out_y)
{
unsigned long x = 0, y = 0;
unsigned int w = 0, h = 0;
fx_tty_get_dimensions(ed->ed_tty, &w, &h);
if (!w || !h) {
w = 80;
h = 25;
}
fx_string *prompt = line_ed_get_prompt(ed);
fx_string *buffer = line_ed_get_buffer(ed);
const char *s = fx_string_get_cstr(prompt);
size_t len = fx_string_get_size(prompt, FX_STRLEN_CODEPOINTS);
fx_wchar prev = FX_WCHAR_INVALID;
for (unsigned long i = 0; i < len; i++) {
fx_wchar c = fx_wchar_utf8_codepoint_decode(s);
if (prev != FX_WCHAR_INVALID) {
if (prev == '\n' || x + 1 >= w) {
x = 0;
y++;
} else {
x += line_ed_get_char_width(c);
}
}
unsigned int stride = fx_wchar_utf8_codepoint_size(c);
if (stride == 0) {
break;
}
s += stride;
prev = c;
}
s = fx_string_get_cstr(buffer);
len = fx_string_get_size(buffer, FX_STRLEN_CODEPOINTS);
for (unsigned long i = 0; i < offset && i < len; i++) {
fx_wchar c = fx_wchar_utf8_codepoint_decode(s);
if (prev != FX_WCHAR_INVALID) {
if (prev == '\n' || x + 1 >= w) {
x = 0;
y++;
} else {
x += line_ed_get_char_width(c);
}
}
unsigned int stride = fx_wchar_utf8_codepoint_size(c);
if (stride == 0) {
break;
}
s += stride;
prev = c;
}
if (offset > len) {
if (x + 1 >= w) {
x = 0;
y++;
} else {
x++;
}
}
if (out_x) {
*out_x = x;
}
if (out_y) {
*out_y = y;
}
}
void line_ed_get_points(struct bshell_line_ed_p *ed, struct cursor_points *out)
{
unsigned long cursor = line_ed_get_cursor(ed);
fx_string *buffer = line_ed_get_buffer(ed);
convert_offset_to_xy(
ed,
cursor + 1,
&out->c_cursor_x,
&out->c_cursor_y);
convert_offset_to_xy(
ed,
fx_string_get_size(buffer, FX_STRLEN_CODEPOINTS),
&out->c_render_limit_x,
&out->c_render_limit_y);
convert_offset_to_xy(
ed,
fx_string_get_size(buffer, FX_STRLEN_CODEPOINTS) + 1,
&out->c_cursor_limit_x,
&out->c_cursor_limit_y);
}
+98
View File
@@ -0,0 +1,98 @@
#include "line-editor.h"
void line_ed_hide(struct bshell_line_ed_p *ed)
{
if (!ed->ed_render.r_vlines) {
return;
}
#if 0
fprintf(stderr, "--- hide ---\n");
fprintf(stderr,
"vlines=%lu, cursor=%lu->(%ld,%ld)\n",
ed->ed_render.r_vlines,
ed->ed_cursor,
ed->ed_render.ed_points.c_cursor_x,
ed->ed_render.ed_points.c_cursor_y);
#endif
if (ed->ed_render.ed_points.c_cursor_y > 0) {
fx_tty_move_cursor_y(
ed->ed_tty,
FX_TTY_POS_CURSOR,
-ed->ed_render.ed_points.c_cursor_y);
}
fx_tty_move_cursor_x(ed->ed_tty, FX_TTY_POS_START, 0);
fx_tty_clear(
ed->ed_tty,
FX_TTY_CLEAR_SCREEN | FX_TTY_CLEAR_FROM_CURSOR);
memset(&ed->ed_render, 0x0, sizeof ed->ed_render);
}
static void render_prompt(struct bshell_line_ed_p *ed)
{
if (ed->ed_render_prompt) {
bshell_line_ed_plugin_class *renderer = fx_object_get_interface(
ed->ed_render_prompt,
BSHELL_TYPE_LINE_EDITOR_PLUGIN);
renderer->p_render_prompt(ed->ed_render_prompt, ed->ed_self);
}
}
static void render_buffer(struct bshell_line_ed_p *ed)
{
if (ed->ed_render_buffer) {
bshell_line_ed_plugin_class *renderer = fx_object_get_interface(
ed->ed_render_buffer,
BSHELL_TYPE_LINE_EDITOR_PLUGIN);
renderer->p_render_buffer(ed->ed_render_buffer, ed->ed_self);
}
}
void line_ed_show(struct bshell_line_ed_p *ed)
{
render_prompt(ed);
render_buffer(ed);
line_ed_get_points(ed, &ed->ed_render.ed_points);
bool cursor_limit_newline
= ed->ed_render.ed_points.c_cursor_limit_x == 0
&& ed->ed_render.ed_points.c_cursor_limit_y > 0;
if (cursor_limit_newline) {
fx_tty_putc(ed->ed_tty, 0, '\r');
fx_tty_putc(ed->ed_tty, 0, '\n');
}
long shift_x = 0, shift_y = 0;
shift_x = (long)ed->ed_render.ed_points.c_cursor_x
- (long)ed->ed_render.ed_points.c_cursor_limit_x;
shift_y = (long)ed->ed_render.ed_points.c_cursor_y
- (long)ed->ed_render.ed_points.c_cursor_limit_y;
fx_tty_move_cursor_x(ed->ed_tty, FX_TTY_POS_CURSOR, shift_x);
fx_tty_move_cursor_y(ed->ed_tty, FX_TTY_POS_CURSOR, shift_y);
#if 0
fprintf(stderr, "--- show ---\n");
fprintf(stderr,
"cursor=%lu->(%lu,%lu)\n",
ed->ed_cursor,
ed->ed_render.ed_points.c_cursor_x,
ed->ed_render.ed_points.c_cursor_y);
fprintf(stderr,
"cursor_limit=(%lu,%lu)\n",
ed->ed_render.ed_points.c_cursor_limit_x,
ed->ed_render.ed_points.c_cursor_limit_y);
fprintf(stderr,
"render_limit=(%lu,%lu)\n",
ed->ed_render.ed_points.c_render_limit_x,
ed->ed_render.ed_points.c_render_limit_y);
#endif
ed->ed_render.r_vlines = ed->ed_render.ed_points.c_render_limit_y + 1;
}
int line_ed_get_char_width(fx_wchar c)
{
/* TODO support double-width and zero-width characters */
return fx_wchar_is_graph(c) ? 1 : 0;
}
+61
View File
@@ -0,0 +1,61 @@
#include <bshell/line-editor/highlight.h>
#include <bshell/line-editor/line-editor.h>
#include <bshell/line-editor/plugin.h>
#include <fx/term/tty.h>
struct bshell_line_ed_highlight_p {
};
static void init(fx_object *obj, void *priv)
{
}
static void fini(fx_object *obj, void *priv)
{
}
static enum bshell_status render_buffer(
bshell_line_ed_plugin *plugin,
bshell_line_ed *ed)
{
fx_string *buf = bshell_line_ed_get_buffer(ed);
fx_tty *tty = bshell_line_ed_get_tty(ed);
const char *s = fx_string_get_cstr(buf);
for (unsigned long i = 0; *s; i++) {
fx_wchar c = fx_wchar_utf8_codepoint_decode(s);
unsigned int stride = fx_wchar_utf8_codepoint_size(c);
if (stride == 0) {
break;
}
char cs[5] = {0};
fx_wchar_utf8_codepoint_encode(c, cs);
fx_tty_puts(tty, 0, cs);
s += stride;
}
fx_tty_puts(tty, 0, "[reset]");
return BSHELL_SUCCESS;
}
FX_TYPE_CLASS_BEGIN(bshell_line_ed_highlight)
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
FX_INTERFACE_ENTRY(to_string) = NULL;
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
FX_TYPE_VTABLE_INTERFACE_BEGIN(
bshell_line_ed_plugin,
BSHELL_TYPE_LINE_EDITOR_PLUGIN)
FX_INTERFACE_ENTRY(p_render_buffer) = render_buffer;
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
FX_TYPE_CLASS_END(bshell_line_ed_highlight)
FX_TYPE_DEFINITION_BEGIN(bshell_line_ed_highlight)
FX_TYPE_ID(0x162823ef, 0x4893, 0x4089, 0xa4f6, 0xf015a1976881);
FX_TYPE_NAME("bshell.runtime.line_editor.plugins.highlight");
FX_TYPE_EXTENDS(BSHELL_TYPE_LINE_EDITOR_PLUGIN);
FX_TYPE_CLASS(bshell_line_ed_highlight_class);
FX_TYPE_INSTANCE_INIT(init);
FX_TYPE_INSTANCE_FINI(fini);
FX_TYPE_INSTANCE_PRIVATE(struct bshell_line_ed_highlight_p);
FX_TYPE_DEFINITION_END(bshell_line_ed_highlight)
+34
View File
@@ -0,0 +1,34 @@
#include <bshell/line-editor/history.h>
#include <bshell/line-editor/plugin.h>
struct bshell_line_ed_history_p {
};
static void init(fx_object *obj, void *priv)
{
}
static void fini(fx_object *obj, void *priv)
{
}
FX_TYPE_CLASS_BEGIN(bshell_line_ed_history)
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
FX_INTERFACE_ENTRY(to_string) = NULL;
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
FX_TYPE_VTABLE_INTERFACE_BEGIN(
bshell_line_ed_plugin,
BSHELL_TYPE_LINE_EDITOR_PLUGIN)
FX_TYPE_VTABLE_INTERFACE_END(bshell_command, BSHELL_TYPE_COMMAND)
FX_TYPE_CLASS_END(bshell_line_ed_history)
FX_TYPE_DEFINITION_BEGIN(bshell_line_ed_history)
FX_TYPE_ID(0xa08c98d5, 0x9512, 0x4a65, 0xaf57, 0x0daa8a943e52);
FX_TYPE_NAME("bshell.runtime.line_editor.plugins.history");
FX_TYPE_EXTENDS(BSHELL_TYPE_LINE_EDITOR_PLUGIN);
FX_TYPE_CLASS(bshell_line_ed_history_class);
FX_TYPE_INSTANCE_INIT(init);
FX_TYPE_INSTANCE_FINI(fini);
FX_TYPE_INSTANCE_PRIVATE(struct bshell_line_ed_history_p);
FX_TYPE_DEFINITION_END(bshell_line_ed_history)
+223
View File
@@ -0,0 +1,223 @@
#include "keybind.h"
#include "line-editor.h"
#include <fx/term/tty.h>
#define KEYCODE_WILDCARD FX_KEY_RESERVED_START
static FX_BST_DEFINE_SIMPLE_INSERT(
struct keymap_entry,
e_node,
e_code,
put_keymap_entry);
static FX_BST_DEFINE_SIMPLE_GET(
struct keymap_entry,
fx_keycode,
e_node,
e_code,
get_keymap_entry);
static FX_BST_DEFINE_SIMPLE_INSERT(
struct keybind,
b_node,
b_priority,
put_keybind);
struct bshell_line_ed_keybind_p {
bshell_line_ed_keybind *kb_self;
struct keybind kb_bind;
};
static void keymap_entry_destroy(struct keymap_entry *entry)
{
fx_bst_node *cur_bind = fx_bst_first(&entry->e_binds);
while (cur_bind) {
fx_bst_node *next_bind = fx_bst_next(cur_bind);
fx_bst_delete(&entry->e_binds, cur_bind);
struct keybind *keybind
= fx_unbox(struct keybind, cur_bind, b_node);
struct bshell_line_ed_keybind_p *keybind_object_p = fx_unbox(
struct bshell_line_ed_keybind_p,
keybind,
kb_bind);
bshell_line_ed_keybind_unref(keybind_object_p->kb_self);
cur_bind = next_bind;
}
free(entry);
}
void line_ed_cleanup_keymap(fx_bst *keymap)
{
fx_bst_node *cur_entry = fx_bst_first(keymap);
while (cur_entry) {
fx_bst_node *next_entry = fx_bst_next(cur_entry);
fx_bst_delete(keymap, cur_entry);
struct keymap_entry *keymap_entry
= fx_unbox(struct keymap_entry, cur_entry, e_node);
keymap_entry_destroy(keymap_entry);
cur_entry = next_entry;
}
}
static fx_keycode key_string_to_code(const char *key)
{
const char *tmp = key;
fx_keycode result = 0;
if (*key == '^') {
result |= FX_MOD_CTRL;
key++;
}
if (!strcmp(key, "*")) {
result |= KEYCODE_WILDCARD;
} else if (!strcmp(key, "left")) {
result |= FX_KEY_ARROW_LEFT;
} else if (!strcmp(key, "right")) {
result |= FX_KEY_ARROW_RIGHT;
} else if (!strcmp(key, "up")) {
result |= FX_KEY_ARROW_UP;
} else if (!strcmp(key, "down")) {
result |= FX_KEY_ARROW_DOWN;
} else if (!strcmp(key, "backspace")) {
result |= FX_KEY_BACKSPACE;
} else if (!strcmp(key, "return")) {
result |= FX_KEY_RETURN;
} else {
result |= fx_wchar_utf8_codepoint_decode(key);
}
return result;
}
static bshell_line_ed_keybind *line_ed_bind_key(
struct bshell_line_ed_p *ed,
const char *key,
bshell_line_ed_keybind_callback_t callback,
unsigned long priority)
{
fx_keycode keycode = key_string_to_code(key);
if (!keycode) {
return NULL;
}
bshell_line_ed_keybind *bind = NULL;
bind = bshell_line_ed_keybind_create();
if (!bind) {
return NULL;
}
struct bshell_line_ed_keybind_p *bind_p
= fx_object_get_private(bind, BSHELL_TYPE_LINE_EDITOR_KEYBIND);
struct keymap_entry *keymap_entry
= get_keymap_entry(&ed->ed_keymap, keycode);
if (!keymap_entry) {
keymap_entry = calloc(1, sizeof *keymap_entry);
if (!keymap_entry) {
bshell_line_ed_keybind_unref(bind);
return NULL;
}
keymap_entry->e_code = keycode;
put_keymap_entry(&ed->ed_keymap, keymap_entry);
}
bind_p->kb_self = bind;
bind_p->kb_bind.b_priority = priority;
bind_p->kb_bind.b_callback = callback;
put_keybind(&keymap_entry->e_binds, &bind_p->kb_bind);
return bind;
}
bshell_line_ed_keybind *bshell_line_ed_bind_key(
bshell_line_ed *ed,
const char *key,
bshell_line_ed_keybind_callback_t callback,
unsigned long priority)
{
FX_CLASS_DISPATCH_STATIC(
BSHELL_TYPE_LINE_EDITOR,
line_ed_bind_key,
ed,
key,
callback,
priority);
}
static struct bshell_line_ed_keybind_result do_handle_key(
struct bshell_line_ed_p *ed,
fx_keycode match_code,
fx_keycode real_code)
{
struct bshell_line_ed_keybind_result result
= BSHELL_LINE_EDITOR_KEYBIND_RESULT(
BSHELL_SUCCESS,
BSHELL_LINE_EDITOR_KEYBIND_CONTINUE);
struct keymap_entry *keymap_entry
= get_keymap_entry(&ed->ed_keymap, match_code);
if (!keymap_entry) {
return result;
}
fx_bst_node *cur = fx_bst_last(&keymap_entry->e_binds);
while (cur) {
struct keybind *bind = fx_unbox(struct keybind, cur, b_node);
result = bind->b_callback(ed->ed_self, real_code);
if (result.r_status != BSHELL_SUCCESS
|| result.r_action != BSHELL_LINE_EDITOR_KEYBIND_CONTINUE) {
break;
}
cur = fx_bst_prev(cur);
}
return result;
}
void line_ed_handle_key(struct bshell_line_ed_p *ed, fx_keycode code)
{
struct bshell_line_ed_keybind_result result
= do_handle_key(ed, code, code);
if (result.r_status != BSHELL_SUCCESS
|| result.r_action != BSHELL_LINE_EDITOR_KEYBIND_CONTINUE) {
return;
}
if (code & FX_MOD_CTRL) {
result = do_handle_key(
ed,
FX_MOD_CTRL | KEYCODE_WILDCARD,
code);
} else {
result = do_handle_key(ed, KEYCODE_WILDCARD, code);
}
}
static void fini(fx_object *obj, void *priv)
{
}
FX_TYPE_CLASS_BEGIN(bshell_line_ed_keybind)
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
FX_INTERFACE_ENTRY(to_string) = NULL;
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
FX_TYPE_CLASS_END(bshell_line_ed_keybind)
FX_TYPE_DEFINITION_BEGIN(bshell_line_ed_keybind)
FX_TYPE_ID(0x5d842371, 0x40a3, 0x4683, 0xaff2, 0x05daa53d36b7);
FX_TYPE_NAME("bshell.line_editor.keybind");
FX_TYPE_CLASS(bshell_line_ed_keybind_class);
FX_TYPE_INSTANCE_PRIVATE(struct bshell_line_ed_keybind_p);
FX_TYPE_INSTANCE_FINI(fini);
FX_TYPE_DEFINITION_END(bshell_line_ed_keybind)
+22
View File
@@ -0,0 +1,22 @@
#ifndef _KEYBIND_H_
#define _KEYBIND_H_
#include <bshell/line-editor/keybind.h>
#include <fx/bst.h>
#include <fx/term/tty.h>
struct keybind {
fx_bst_node b_node;
unsigned long b_priority;
bshell_line_ed_keybind_callback_t b_callback;
};
struct keymap_entry {
fx_bst_node e_node;
fx_keycode e_code;
fx_bst e_binds;
};
extern void line_ed_cleanup_keymap(fx_bst *keymap);
#endif

Some files were not shown because too many files have changed in this diff Show More