diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am index fd6074dec3..5f10ea7f2e 100644 --- a/src/Makefile_Ecore.am +++ b/src/Makefile_Ecore.am @@ -52,10 +52,6 @@ ecore_eolian_files_public = \ lib/ecore/efl_view_model.eo \ lib/ecore/efl_core_env.eo \ lib/ecore/efl_core_proc_env.eo \ - lib/ecore/efl_core_command_line.eo - -ecore_test_eolian_files = \ - tests/ecore/efl_app_test_cml.eo ecore_eolian_files = \ $(ecore_eolian_files_legacy) \ @@ -64,14 +60,10 @@ ecore_eolian_files = \ ecore_eolian_c = $(ecore_eolian_files:%.eo=%.eo.c) ecore_eolian_h = $(ecore_eolian_files:%.eo=%.eo.h) \ $(ecore_eolian_files_legacy:%.eo=%.eo.legacy.h) -ecore_test_c = $(ecore_test_eolian_files:%.eo=%.eo.c) -ecore_test_h = $(ecore_test_eolian_files:%.eo=%.eo.h) BUILT_SOURCES += \ $(ecore_eolian_c) \ - $(ecore_eolian_h) \ - $(ecore_test_c) \ - $(ecore_test_h) + $(ecore_eolian_h) ecoreeolianfilesdir = $(datadir)/eolian/include/ecore-@VMAJ@ ecoreeolianfiles_DATA = $(ecore_eolian_files_public) lib/ecore/efl_loop_timer.eo @@ -108,7 +100,6 @@ lib/ecore/ecore_job.c \ lib/ecore/ecore_main.c \ lib/ecore/ecore_event_message.c \ lib/ecore/ecore_event_message_handler.c \ -lib/ecore/efl_core_command_line.c \ lib/ecore/efl_core_env.c \ lib/ecore/efl_core_proc_env.c \ lib/ecore/efl_app.c \ @@ -348,7 +339,6 @@ tests/ecore/efl_app_test_loop.c \ tests/ecore/efl_app_test_loop_fd.c \ tests/ecore/efl_app_test_loop_timer.c \ tests/ecore/efl_app_test_promise.c \ -tests/ecore/efl_app_test_cml.c \ tests/ecore/efl_app_test_env.c \ tests/ecore/efl_app_suite.c \ tests/ecore/efl_app_suite.h diff --git a/src/bindings/mono/efl_mono/efl_csharp_application.cs b/src/bindings/mono/efl_mono/efl_csharp_application.cs index 84732d3993..2b2c55c75e 100644 --- a/src/bindings/mono/efl_mono/efl_csharp_application.cs +++ b/src/bindings/mono/efl_mono/efl_csharp_application.cs @@ -104,9 +104,8 @@ namespace Efl { public void Launch(Efl.Csharp.Components components=Components.Ui) { Init(components); Efl.App app = Efl.App.AppMain; - Eina.Array command_line = new Eina.Array(); - command_line.Append(Environment.GetCommandLineArgs()); - app.SetCommandArray(command_line); + foreach (var arg in Environment.GetCommandLineArgs()) + app.AppendArg(arg); app.ArgumentsEvt += (object sender, LoopArgumentsEvt_Args evt) => { if (evt.arg.Initialization) { OnInitialize(evt.arg.Argv); diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h index 3615219c38..348b0f5b6d 100644 --- a/src/lib/ecore/Ecore_Eo.h +++ b/src/lib/ecore/Ecore_Eo.h @@ -28,7 +28,6 @@ #include "efl_core_env.eo.h" #include "efl_core_proc_env.eo.h" -#include "efl_core_command_line.eo.h" #include "efl_loop_message.eo.h" #include "efl_loop_message_handler.eo.h" diff --git a/src/lib/ecore/efl_app.eo b/src/lib/ecore/efl_app.eo index e046428626..f90324b39d 100644 --- a/src/lib/ecore/efl_app.eo +++ b/src/lib/ecore/efl_app.eo @@ -1,6 +1,6 @@ import efl_types; -class Efl.App extends Efl.Loop implements Efl.Core.Command_Line +class Efl.App extends Efl.Loop { [[ ]] data: null; diff --git a/src/lib/ecore/efl_appthread.eo b/src/lib/ecore/efl_appthread.eo index 82a9d77ace..c60308f468 100644 --- a/src/lib/ecore/efl_appthread.eo +++ b/src/lib/ecore/efl_appthread.eo @@ -1,4 +1,4 @@ -class Efl.Appthread extends Efl.Loop implements Efl.ThreadIO, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Efl.Core.Command_Line +class Efl.Appthread extends Efl.Loop implements Efl.ThreadIO, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer { [[ ]] methods { diff --git a/src/lib/ecore/efl_core_command_line.c b/src/lib/ecore/efl_core_command_line.c deleted file mode 100644 index 74ae690c26..0000000000 --- a/src/lib/ecore/efl_core_command_line.c +++ /dev/null @@ -1,267 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - -#define EFL_CORE_COMMAND_LINE_PROTECTED - -#include - -#define MY_CLASS EFL_CORE_COMMAND_LINE_MIXIN - -typedef struct { - Eina_Bool filled; - char *string_command; - Eina_Array *command; -} Efl_Core_Command_Line_Data; - -static Eina_Array * -_unescape(const char *s) -{ - Eina_Array *args; - const char *p; - char *tmp = NULL, *d = NULL; - if (!s) return NULL; - - Eina_Bool in_quote_dbl = EINA_FALSE; - Eina_Bool in_quote = EINA_FALSE; - - args = eina_array_new(16); - if (!args) return NULL; - for (p = s; *p; p++) - { - if (!tmp) tmp = d = strdup(p); - if (tmp) - { - if (in_quote_dbl) - { - switch (*p) - { - case '\"': - in_quote_dbl = EINA_FALSE; - *d = 0; - eina_array_push(args, eina_stringshare_add(tmp)); - free(tmp); - tmp = d = NULL; - break; - case '\\': - p++; - EINA_FALLTHROUGH - default: - *d = *p; - d++; - break; - } - } - else if (in_quote) - { - switch (*p) - { - case '\'': - in_quote = EINA_FALSE; - *d = 0; - eina_array_push(args, eina_stringshare_add(tmp)); - free(tmp); - tmp = d = NULL; - break; - case '\\': - p++; - EINA_FALLTHROUGH - default: - *d = *p; - d++; - break; - } - } - else - { - switch (*p) - { - case ' ': - case '\t': - case '\r': - case '\n': - *d = 0; - eina_array_push(args, eina_stringshare_add(tmp)); - free(tmp); - tmp = d = NULL; - break; - case '\"': - in_quote_dbl = EINA_TRUE; - break; - case '\'': - in_quote = EINA_TRUE; - break; - case '\\': - p++; - EINA_FALLTHROUGH - default: - *d = *p; - d++; - break; - } - } - } - } - if (tmp) - { - *d = 0; - eina_array_push(args, eina_stringshare_add(tmp)); - free(tmp); - } - return args; -} - -static char * -_escape(const char *s) -{ - Eina_Bool need_quote = EINA_FALSE; - const char *p; - char *s2 = malloc((strlen(s) * 2) + 1 + 2), *d; - - if (!s2) return NULL; - - for (p = s; *p; p++) - { - switch (*p) - { - case '\'': - case '\"': - case '$': - case '#': - case ';': - case '&': - case '`': - case '|': - case '(': - case ')': - case '[': - case ']': - case '{': - case '}': - case '>': - case '<': - case '\n': - case '\r': - case '\t': - case ' ': - need_quote = EINA_TRUE; - default: - break; - } - } - - d = s2; - if (need_quote) - { - *d = '\"'; - d++; - } - for (p = s; *p; p++, d++) - { - switch (*p) - { - case '\\': - case '\'': - case '\"': - *d = '\\'; - d++; - EINA_FALLTHROUGH - default: - *d = *p; - break; - } - } - if (need_quote) - { - *d = '\"'; - d++; - } - *d = 0; - return s2; -} - -EOLIAN static const char* -_efl_core_command_line_command_get(const Eo *obj EINA_UNUSED, Efl_Core_Command_Line_Data *pd) -{ - return eina_strdup(pd->string_command); -} - -EOLIAN static Eina_Accessor* -_efl_core_command_line_command_access(Eo *obj EINA_UNUSED, Efl_Core_Command_Line_Data *pd) -{ - return pd->command ? eina_array_accessor_new(pd->command) : NULL; -} - -static void -_remove_invalid_chars(char *command) -{ - for (unsigned int i = 0; i < strlen(command); ++i) - { - char c = command[i]; - if (c < 0x20 || c == 0x7f) - command[i] = '\x12'; - } -} - -EOLIAN static Eina_Bool -_efl_core_command_line_command_array_set(Eo *obj EINA_UNUSED, Efl_Core_Command_Line_Data *pd, Eina_Array *array) -{ - EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->filled, EINA_FALSE); - Eina_Strbuf *command = eina_strbuf_new(); - unsigned int i = 0; - - pd->command = eina_array_new(eina_array_count(array)); - for (i = 0; i < (array ? eina_array_count(array) : 0); ++i) - { - char *content = eina_array_data_get(array, i); - char *param = calloc(1, strlen(content)); - - if (!param) - { - free(param); - while (eina_array_count(pd->command) > 0) - eina_stringshare_del(eina_array_pop(pd->command)); - eina_array_free(pd->command); - pd->command = NULL; - eina_array_free(array); - return EINA_FALSE; - } - - //build the command - if (i != 0) - eina_strbuf_append(command, " "); - eina_strbuf_append(command, _escape(content)); - //convert string to stringshare - strcpy(param, content); - _remove_invalid_chars(param); - eina_array_push(pd->command, eina_stringshare_add(param)); - free(param); - } - pd->string_command = eina_strbuf_release(command); - pd->filled = EINA_TRUE; - eina_array_free(array); - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_core_command_line_command_string_set(Eo *obj EINA_UNUSED, Efl_Core_Command_Line_Data *pd, const char *str) -{ - EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->filled, EINA_FALSE); - - pd->string_command = eina_strdup(str); - _remove_invalid_chars(pd->string_command); - pd->command = _unescape(str); - if (!pd->command) - { - if (pd->string_command) - free(pd->string_command); - pd->string_command = NULL; - return EINA_FALSE; - } - pd->filled = EINA_TRUE; - - return EINA_TRUE; -} - -#include "efl_core_command_line.eo.c" diff --git a/src/lib/ecore/efl_core_command_line.eo b/src/lib/ecore/efl_core_command_line.eo deleted file mode 100644 index 1cbb020856..0000000000 --- a/src/lib/ecore/efl_core_command_line.eo +++ /dev/null @@ -1,80 +0,0 @@ -mixin Efl.Core.Command_Line { - [[A mixin that implements standard functions for command lines. - - This object parses the command line that gets passed, later the object can be accessed via accessor or the string directly. - ]] - methods { - @property command { - [[ A commandline that encodes arguments in a command string. - This command is unix shell-style, thus whitespace separates - arguments unless escaped. Also a semi-colon ';', ampersand - '&', pipe/bar '|', hash '#', bracket, square brace, brace - character ('(', ')', '[', ']', '{', '}'), exclamation - mark '!', backquote '`', greator or less than ('>' '<') - character unless escaped or in quotes would cause - args_count/value to not be generated properly, because - it would force complex shell interpretation which - will not be supported in evaluating the arg_count/value - information, but the final shell may interpret this if this - is executed via a command-line shell. To not be a complex - shell command, it should be simple with paths, options - and variable expansions, but nothing more complex involving - the above unescaped characters. - - "cat -option /path/file" - "cat 'quoted argument'" - "cat ~/path/escaped\ argument" - "/bin/cat escaped\ argument $VARIABLE" - etc. - - It should not try and use "complex shell features" if you - want the arg_count and arg_value set to be correct after - setting the command string. For example none of: - - "VAR=x /bin/command && /bin/othercommand >& /dev/null" - "VAR=x /bin/command `/bin/othercommand` | /bin/cmd2 && cmd3 &" - etc. - - If you set the command the arg_count/value property contents - can change and be completely re-evaluated by parsing the - command string into an argument array set along with - interpreting escapes back into individual argument strings. - ]] - get { - - } - values { - commandline : string; - } - } - command_access { - [[ Get the accessor which enables access to each argument that got passed to this object. ]] - return : accessor; - } - @property command_array { - [[ Use an array to fill this object - - Every element of a string is a argument. - ]] - set { - return : bool; [[On success $true, $false otherwise]] - } - values { - array : array @owned; [[An array where every array field is an argument]] - } - } - @property command_string { - [[ Use a string to fill this object - - The string will be split at every unescaped ' ', every resulting substring will be a new argument to the command line. - ]] - set { - return : bool; [[On success $true, $false otherwise]] - } - values { - str : string; [[A command in form of a string]] - } - - } - } -} diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c index 61ff4ba798..4b3bc658d6 100644 --- a/src/lib/ecore/efl_exe.c +++ b/src/lib/ecore/efl_exe.c @@ -395,7 +395,7 @@ _efl_exe_efl_task_priority_get(const Eo *obj EINA_UNUSED, Efl_Exe_Data *pd) } EOLIAN static Eina_Future * -_efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd) +_efl_exe_efl_task_run(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd) { #ifdef _WIN32 return EINA_FALSE; @@ -414,7 +414,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd) if (!td) return NULL; // get a cmdline to run - cmd = efl_core_command_line_command_get(obj); + cmd = efl_task_command_get(obj); if (!cmd) return NULL; ret = pipe(pipe_exited); diff --git a/src/lib/ecore/efl_exe.eo b/src/lib/ecore/efl_exe.eo index b7f97da7dc..111814af21 100644 --- a/src/lib/ecore/efl_exe.eo +++ b/src/lib/ecore/efl_exe.eo @@ -19,7 +19,7 @@ enum Efl.Exe_Flags { hide_io = 4 } -class Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer,Efl.Core.Command_Line +class Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer { [[ ]] methods { diff --git a/src/lib/ecore/efl_loop.c b/src/lib/ecore/efl_loop.c index cf8600c998..68f9573b76 100644 --- a/src/lib/ecore/efl_loop.c +++ b/src/lib/ecore/efl_loop.c @@ -383,19 +383,17 @@ _efl_loop_arguments_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *de EAPI void ecore_loop_arguments_send(int argc, const char **argv) { - Eina_Array *arga, *cml; + Eina_Array *arga; int i = 0; + efl_task_arg_reset(efl_main_loop_get()); arga = eina_array_new(argc); - cml = eina_array_new(argc); for (i = 0; i < argc; i++) { - Eina_Stringshare *arg = eina_stringshare_add(argv[i]); - eina_array_push(arga, arg); - eina_array_push(cml, arg); + eina_array_push(arga, eina_stringshare_add(argv[i])); + efl_task_arg_append(efl_main_loop_get(), argv[i]); } - efl_core_command_line_command_array_set(efl_app_main_get(EFL_APP_CLASS), cml); efl_future_then(efl_main_loop_get(), efl_loop_job(efl_main_loop_get()), .success = _efl_loop_arguments_send, .free = _efl_loop_arguments_cleanup, diff --git a/src/lib/ecore/efl_task.c b/src/lib/ecore/efl_task.c index d610fcbf8b..311de0506a 100644 --- a/src/lib/ecore/efl_task.c +++ b/src/lib/ecore/efl_task.c @@ -12,6 +12,303 @@ ////////////////////////////////////////////////////////////////////////// +static void +_clear_args(Efl_Task_Data *pd) +{ + unsigned int count, i; + + if (!pd->args) return; + count = eina_array_count(pd->args); + for (i = 0; i < count; i++) + eina_stringshare_del(eina_array_data_get(pd->args, i)); + eina_array_free(pd->args); + pd->args = NULL; +} + +static Eina_Array * +_unescape(const char *s) +{ + Eina_Array *args; + const char *p; + char *tmp = NULL, *d = NULL; + if (!s) return NULL; + + Eina_Bool in_quote_dbl = EINA_FALSE; + Eina_Bool in_quote = EINA_FALSE; + + args = eina_array_new(16); + if (!args) return NULL; + for (p = s; *p; p++) + { + if (!tmp) tmp = d = strdup(p); + if (tmp) + { + if (in_quote_dbl) + { + switch (*p) + { + case '\"': + in_quote_dbl = EINA_FALSE; + *d = 0; + eina_array_push(args, eina_stringshare_add(tmp)); + free(tmp); + tmp = d = NULL; + break; + case '\\': + p++; + EINA_FALLTHROUGH + default: + *d = *p; + d++; + break; + } + } + else if (in_quote) + { + switch (*p) + { + case '\'': + in_quote = EINA_FALSE; + *d = 0; + eina_array_push(args, eina_stringshare_add(tmp)); + free(tmp); + tmp = d = NULL; + break; + case '\\': + p++; + EINA_FALLTHROUGH + default: + *d = *p; + d++; + break; + } + } + else + { + switch (*p) + { + case ' ': + case '\t': + case '\r': + case '\n': + *d = 0; + eina_array_push(args, eina_stringshare_add(tmp)); + free(tmp); + tmp = d = NULL; + break; + case '\"': + in_quote_dbl = EINA_TRUE; + break; + case '\'': + in_quote = EINA_TRUE; + break; + case '\\': + p++; + EINA_FALLTHROUGH + default: + *d = *p; + d++; + break; + } + } + } + } + if (tmp) + { + *d = 0; + eina_array_push(args, eina_stringshare_add(tmp)); + free(tmp); + } + return args; +} + +static char * +_escape(const char *s) +{ + Eina_Bool need_quote = EINA_FALSE; + const char *p; + char *s2 = malloc((strlen(s) * 2) + 1 + 2), *d; + + if (!s2) return NULL; + + for (p = s; *p; p++) + { + switch (*p) + { + case '\'': + case '\"': + case '$': + case '#': + case ';': + case '&': + case '`': + case '|': + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case '>': + case '<': + case '\n': + case '\r': + case '\t': + need_quote = EINA_TRUE; + default: + break; + } + } + + d = s2; + if (need_quote) + { + *d = '\"'; + d++; + } + for (p = s; *p; p++, d++) + { + switch (*p) + { + case ' ': + case '\\': + case '\'': + case '\"': + *d = '\\'; + d++; + EINA_FALLTHROUGH + default: + *d = *p; + break; + } + } + if (need_quote) + { + *d = '\"'; + d++; + } + *d = 0; + return s2; +} + +static void +_rebuild_command(Efl_Task_Data *pd) +{ + unsigned int count, i; + Eina_Strbuf *sb; + const char *arg, *cmd; + Eina_Bool have_args = EINA_FALSE; + + if (!pd->command_dirty) return; + pd->command_dirty = EINA_FALSE; + eina_stringshare_del(pd->command); + pd->command = NULL; + if (!pd->args) return; + sb = eina_strbuf_new(); + if (!sb) return; + count = eina_array_count(pd->args); + for (i = 0; i < count; i++) + { + arg = eina_array_data_get(pd->args, i); + if (arg) + { + char *str = _escape(arg); + if (str) + { + if (have_args) eina_strbuf_append(sb, " "); + eina_strbuf_append(sb, str); + free(str); + have_args = EINA_TRUE; + } + } + } + cmd = eina_strbuf_string_get(sb); + if (cmd) pd->command = eina_stringshare_add(cmd); + eina_strbuf_free(sb); +} + +////////////////////////////////////////////////////////////////////////// + +EOLIAN static void +_efl_task_command_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *command) +{ + eina_stringshare_replace(&pd->command, command); + _clear_args(pd); + pd->args = _unescape(pd->command); +} + +EOLIAN static const char * +_efl_task_command_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd) +{ + _rebuild_command(pd); + return pd->command; +} + +EOLIAN static unsigned int +_efl_task_arg_count_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd) +{ + if (!pd->args) return 0; + return eina_array_count(pd->args); +} + +EOLIAN static void +_efl_task_arg_value_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, unsigned int num, const char *arg) +{ + const char *parg = NULL; + unsigned int count; + + if (!pd->args) pd->args = eina_array_new(16); + count = eina_array_count(pd->args); + if ((count > 0) && (count > num)) + parg = eina_array_data_get(pd->args, num); + else + { + unsigned int i; + + for (i = count; i <= num; i++) + { + eina_array_push(pd->args, ""); + eina_array_data_set(pd->args, i, NULL); + } + } + + if (arg) + eina_array_data_set(pd->args, num, eina_stringshare_add(arg)); + else + eina_array_data_set(pd->args, num, NULL); + if (parg) eina_stringshare_del(parg); + pd->command_dirty = EINA_TRUE; +} + +EOLIAN static const char * +_efl_task_arg_value_get(const Eo *obj EINA_UNUSED, Efl_Task_Data *pd, unsigned int num) +{ + unsigned int count; + + if (!pd->args) return NULL; + count = eina_array_count(pd->args); + if (num >= count) return NULL; + return eina_array_data_get(pd->args, num); +} + +EOLIAN static void +_efl_task_arg_append(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, const char *arg) +{ + if (!pd->args) pd->args = eina_array_new(16); + if (arg) + eina_array_push(pd->args, eina_stringshare_add(arg)); + else + eina_array_push(pd->args, NULL); + pd->command_dirty = EINA_TRUE; +} + +EOLIAN static void +_efl_task_arg_reset(Eo *obj EINA_UNUSED, Efl_Task_Data *pd) +{ + _clear_args(pd); + pd->command_dirty = EINA_TRUE; +} + EOLIAN static void _efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority) { @@ -47,6 +344,7 @@ _efl_task_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Task_Data *pd) { eina_stringshare_del(pd->command); pd->command = NULL; + _clear_args(pd); efl_destructor(efl_super(obj, MY_CLASS)); } diff --git a/src/lib/ecore/efl_task.eo b/src/lib/ecore/efl_task.eo index ddab5e6826..526746ff60 100644 --- a/src/lib/ecore/efl_task.eo +++ b/src/lib/ecore/efl_task.eo @@ -19,6 +19,83 @@ abstract Efl.Task extends Efl.Object { [[ ]] methods { + @property command { + [[ A commandline that encodes arguments in a command string. + This command is unix shell-style, thus whitespace separates + arguments unless escaped. Also a semi-colon ';', ampersand + '&', pipe/bar '|', hash '#', bracket, square brace, brace + character ('(', ')', '[', ']', '{', '}'), exclamation + mark '!', backquote '`', greator or less than ('>' '<') + character unless escaped or in quotes would cause + args_count/value to not be generated properly, because + it would force complex shell interpretation which + will not be supported in evaluating the arg_count/value + information, but the final shell may interpret this if this + is executed via a command-line shell. To not be a complex + shell command, it should be simple with paths, options + and variable expansions, but nothing more complex involving + the above unescaped characters. + + "cat -option /path/file" + "cat 'quoted argument'" + "cat ~/path/escaped\ argument" + "/bin/cat escaped\ argument $VARIABLE" + etc. + + It should not try and use "complex shell features" if you + want the arg_count and arg_value set to be correct after + setting the command string. For example none of: + + "VAR=x /bin/command && /bin/othercommand >& /dev/null" + "VAR=x /bin/command `/bin/othercommand` | /bin/cmd2 && cmd3 &" + etc. + + If you set the command the arg_count/value property contents + can change and be completely re-evaluated by parsing the + command string into an argument array set along with + interpreting escapes back into individual argument strings. ]] + get { } + set { } + values { + command: string; [[ The command string as described ]] + } + } + @property arg_count { + [[ Number of arguments passed in or arguments that are to be + passed as sepcified by arg_value ]] + get { } + values { + args: uint; [[ ]] + } + } + @property arg_value { + [[ Argument number by index. If the index does not exist when + set, it is allocated and created. Getting an argument that + Has not been set yet will return $NULL. Empty arguments will + Be ignored. Setting an argument will result in the command + porperty being re-evaluated and escaped into a single + command string if needed. ]] + set { } + get { } + keys { + num: uint; [[ ]] + } + values { + arg: string; [[ ]] + } + } + arg_append { + [[ Append a new string argument at the end of the arg set. + This functions like setting an arg_value at the end of the + current set so the set increases by 1 in size. ]] + params { + arg: string; [[ ]] + } + } + arg_reset { + [[ Clear all arguments in arg_value/count set. Will result in the + command property also being cleared. ]] + } @property priority { [[ The priority of this task. ]] get { } diff --git a/src/lib/ecore/efl_thread.c b/src/lib/ecore/efl_thread.c index a324af4f58..4d48296093 100644 --- a/src/lib/ecore/efl_thread.c +++ b/src/lib/ecore/efl_thread.c @@ -25,7 +25,10 @@ typedef struct int in, out; Eo *in_handler, *out_handler; } fd, ctrl; - Eina_Array *argv; + struct { + unsigned int argc; + const char **argv; + } args; Efl_Callback_Array_Item_Full *event_cb; void *indata, *outdata; } Thread_Data; @@ -148,16 +151,16 @@ _efl_loop_arguments_send(Eo *obj, void *data EINA_UNUSED, const Eina_Value v) Efl_Loop_Arguments arge; Eina_Array *arga; Eina_Stringshare *s; - Eina_Accessor *accessor; - const char *argv; - int i = 0; + unsigned int argc = efl_task_arg_count_get(obj); + unsigned int i; - accessor = efl_core_command_line_command_access(obj); - arga = eina_array_new(10); + arga = eina_array_new(argc); - EINA_ACCESSOR_FOREACH(accessor, i, argv) + for (i = 0; i < argc; i++) { - eina_array_push(arga, eina_stringshare_add(argv)); + const char *argv = efl_task_arg_value_get(obj, i); + if (argv) + eina_array_push(arga, eina_stringshare_add(argv)); } arge.argv = arga; arge.initialization = EINA_TRUE; @@ -226,6 +229,7 @@ _efl_thread_main(void *data, Eina_Thread t) Eo *obj; Eina_Value *ret; Control_Data cmd; + unsigned int i; int real; Efl_Callback_Array_Item_Full *it; @@ -276,13 +280,16 @@ _efl_thread_main(void *data, Eina_Thread t) efl_event_callback_priority_add(obj, it->desc, it->priority, it->func, it->user_data); } - efl_core_command_line_command_array_set(obj, thdat->argv); + for (i = 0; i < thdat->args.argc; i++) + efl_task_arg_append(obj, thdat->args.argv[i]); efl_future_then(obj, efl_loop_job(obj), .success = _efl_loop_arguments_send); - while (thdat->argv && eina_array_count(thdat->argv)) free(eina_array_pop(thdat->argv)); - eina_array_free(thdat->argv); + for (i = 0; i < thdat->args.argc; i++) + eina_stringshare_del(thdat->args.argv[i]); + free(thdat->args.argv); free(thdat->event_cb); + thdat->args.argv = NULL; thdat->event_cb = NULL; ret = efl_loop_begin(obj); @@ -568,7 +575,7 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd) const char *name; int pipe_to_thread[2]; int pipe_from_thread[2]; - unsigned int num; + unsigned int argc, i, num; Efl_Callback_Array_Item_Full *it; Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS); @@ -722,23 +729,24 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd) name = efl_name_get(obj); if (name) thdat->name = eina_stringshare_add(name); - { - Eina_Accessor *acc; - int i = 0; - const char *argv; - - acc = efl_core_command_line_command_access(obj); - if (acc) - { - thdat->argv = eina_array_new(0); - EINA_ACCESSOR_FOREACH(acc, i, argv) - { - eina_array_push(thdat->argv, eina_stringshare_add(argv)); - } - } - - } - + argc = efl_task_arg_count_get(obj); + if (argc > 0) + { + thdat->args.argc = argc; + thdat->args.argv = malloc(argc * sizeof(char *)); + if (thdat->args.argv) + { + for (i = 0; i < argc; i++) + { + const char *argv = efl_task_arg_value_get(obj, i); + if (argv) + thdat->args.argv[i] = eina_stringshare_add(argv); + else + thdat->args.argv[i] = NULL; + } + } + // XXX: if malloc fails? + } if (pd->event_cb) { num = 0; @@ -754,8 +762,9 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd) if (!eina_thread_create(&(pd->thread), pri, -1, _efl_thread_main, thdat)) { - while (eina_array_count(thdat->argv)) eina_stringshare_del(eina_array_pop(thdat->argv)); - eina_array_free(thdat->argv); + for (i = 0; i < thdat->args.argc; i++) + eina_stringshare_del(thdat->args.argv[i]); + free(thdat->args.argv); efl_del(pd->fd.in_handler); efl_del(pd->fd.out_handler); efl_del(pd->ctrl.in_handler); diff --git a/src/lib/ecore/efl_thread.eo b/src/lib/ecore/efl_thread.eo index 02bf2f15df..7837c7bfdb 100644 --- a/src/lib/ecore/efl_thread.eo +++ b/src/lib/ecore/efl_thread.eo @@ -1,4 +1,4 @@ -class Efl.Thread extends Efl.Task implements Efl.ThreadIO, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Efl.Core.Command_Line +class Efl.Thread extends Efl.Task implements Efl.ThreadIO, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer { methods { } diff --git a/src/lib/ecore/meson.build b/src/lib/ecore/meson.build index 2e44804481..98909cb618 100644 --- a/src/lib/ecore/meson.build +++ b/src/lib/ecore/meson.build @@ -76,8 +76,7 @@ pub_eo_files = [ 'efl_composite_model.eo', 'efl_view_model.eo', 'efl_core_env.eo', - 'efl_core_proc_env.eo', - 'efl_core_command_line.eo', + 'efl_core_proc_env.eo' ] foreach eo_file : pub_eo_files @@ -181,12 +180,10 @@ ecore_src = [ 'ecore_main_common.h', 'efl_exe.c', 'efl_thread.c', - 'efl_appthread.c', 'efl_threadio.c', 'efl_appthread.c', 'efl_core_env.c', 'efl_core_proc_env.c', - 'efl_core_command_line.c', ] if sys_windows == true diff --git a/src/tests/ecore/efl_app_suite.c b/src/tests/ecore/efl_app_suite.c index 2cab632622..cd26e2d95e 100644 --- a/src/tests/ecore/efl_app_suite.c +++ b/src/tests/ecore/efl_app_suite.c @@ -53,7 +53,6 @@ static const Efl_Test_Case etc[] = { { "Promise", efl_app_test_promise_3 }, { "Promise", efl_app_test_promise_safety }, { "Env", efl_test_efl_env }, - { "CML", efl_test_efl_cml }, { NULL, NULL } }; diff --git a/src/tests/ecore/efl_app_suite.h b/src/tests/ecore/efl_app_suite.h index 874d2bb503..3a66dcdfcf 100644 --- a/src/tests/ecore/efl_app_suite.h +++ b/src/tests/ecore/efl_app_suite.h @@ -12,6 +12,5 @@ void efl_app_test_promise_2(TCase *tc); void efl_app_test_promise_3(TCase *tc); void efl_app_test_promise_safety(TCase *tc); void efl_test_efl_env(TCase *tc); -void efl_test_efl_cml(TCase *tc); #endif /* _EFL_APP_SUITE_H */ diff --git a/src/tests/ecore/efl_app_test_cml.c b/src/tests/ecore/efl_app_test_cml.c deleted file mode 100644 index 1b7cebf552..0000000000 --- a/src/tests/ecore/efl_app_test_cml.c +++ /dev/null @@ -1,85 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - -#define EFL_CORE_COMMAND_LINE_PROTECTED - -#include -#include -#define EFL_NOLEGACY_API_SUPPORT -#include -#include "efl_app_suite.h" -#include "../efl_check.h" - -typedef struct { - -} Efl_App_Test_CML_Data; - -#include "efl_app_test_cml.eo.h" -#include "efl_app_test_cml.eo.c" - -static Eina_Array* -_construct_array(void) -{ - Eina_Array *array = eina_array_new(16); - - eina_array_push(array, "/bin/sh"); - eina_array_push(array, "-C"); - eina_array_push(array, "foo"); - eina_array_push(array, "--test"); - eina_array_push(array, "--option=done"); - eina_array_push(array, "--"); - eina_array_push(array, "asdf --test"); - return array; -} - -static const char* -_construct_string(void) -{ - return "/bin/sh -C foo --test --option=done -- \"asdf --test\""; -} - -EFL_START_TEST(efl_core_cml_string) -{ - Efl_App_Test_CML *cml = efl_add_ref(EFL_APP_TEST_CML_CLASS, NULL); - Eina_Array *content = _construct_array(); - Eina_Stringshare *str; - Eina_Bool b; - int i = 0; - - b = efl_core_command_line_command_string_set(cml, _construct_string()); - ck_assert_int_ne(b, 0); - - EINA_ACCESSOR_FOREACH(efl_core_command_line_command_access(cml), i, str) - { - ck_assert_str_eq(eina_array_data_get(content, i), str); - } - ck_assert_str_eq(efl_core_command_line_command_get(cml), _construct_string()); -} -EFL_END_TEST - -EFL_START_TEST(efl_core_cml_array) -{ - Efl_App_Test_CML *cml = efl_add_ref(EFL_APP_TEST_CML_CLASS, NULL); - Eina_Array *content1 = _construct_array(); - Eina_Array *content2 = _construct_array(); - Eina_Stringshare *str; - Eina_Bool b; - int i = 0; - - b = efl_core_command_line_command_array_set(cml, content1); - ck_assert_int_ne(b, 0); - - EINA_ACCESSOR_FOREACH(efl_core_command_line_command_access(cml), i, str) - { - ck_assert_str_eq(eina_array_data_get(content2, i), str); - } - ck_assert_str_eq(efl_core_command_line_command_get(cml), _construct_string()); -} -EFL_END_TEST - -void efl_test_efl_cml(TCase *tc) -{ - tcase_add_test(tc, efl_core_cml_string); - tcase_add_test(tc, efl_core_cml_array); -} diff --git a/src/tests/ecore/efl_app_test_cml.eo b/src/tests/ecore/efl_app_test_cml.eo deleted file mode 100644 index b0877e0cf7..0000000000 --- a/src/tests/ecore/efl_app_test_cml.eo +++ /dev/null @@ -1,4 +0,0 @@ -class Efl.App.Test.CML extends Efl.Object implements Efl.Core.Command_Line -{ - -} diff --git a/src/tests/ecore/meson.build b/src/tests/ecore/meson.build index c49d941355..e3b4f6c851 100644 --- a/src/tests/ecore/meson.build +++ b/src/tests/ecore/meson.build @@ -76,32 +76,14 @@ efl_app_suite_src = [ 'efl_app_test_loop_fd.c', 'efl_app_test_loop_timer.c', 'efl_app_test_promise.c', - 'efl_app_test_env.c', - 'efl_app_test_cml.c', + 'efl_app_test_env.c' ] -priv_eo_files = [ - 'efl_app_test_cml.eo', -] - -priv_eo_file_target = [] -foreach eo_file : priv_eo_files - priv_eo_file_target += custom_target('eolian_gen_' + eo_file, - input : eo_file, - output : [eo_file + '.h'], - depfile : eo_file + '.d', - command : eolian_gen + [ '-I', meson.current_source_dir(), eolian_include_directories, - '-o', 'h:' + join_paths(meson.current_build_dir(), eo_file + '.h'), - '-o', 'c:' + join_paths(meson.current_build_dir(), eo_file + '.c'), - '-o', 'd:' + join_paths(meson.current_build_dir(), eo_file + '.d'), - '-gchd', '@INPUT@']) -endforeach - efl_app_suite_deps = [m] efl_app_suite_deps += ecore efl_app_suite = executable('efl_app_suite', - efl_app_suite_src, priv_eo_file_target, + efl_app_suite_src, dependencies: [efl_app_suite_deps, check], c_args : [ '-DTESTS_BUILD_DIR="'+meson.current_build_dir()+'"',