diff --git a/src/bindings/mono/efl_mono/efl_csharp_application.cs b/src/bindings/mono/efl_mono/efl_csharp_application.cs index 2b2c55c75e..84732d3993 100644 --- a/src/bindings/mono/efl_mono/efl_csharp_application.cs +++ b/src/bindings/mono/efl_mono/efl_csharp_application.cs @@ -104,8 +104,9 @@ namespace Efl { public void Launch(Efl.Csharp.Components components=Components.Ui) { Init(components); Efl.App app = Efl.App.AppMain; - foreach (var arg in Environment.GetCommandLineArgs()) - app.AppendArg(arg); + Eina.Array command_line = new Eina.Array(); + command_line.Append(Environment.GetCommandLineArgs()); + app.SetCommandArray(command_line); app.ArgumentsEvt += (object sender, LoopArgumentsEvt_Args evt) => { if (evt.arg.Initialization) { OnInitialize(evt.arg.Argv); diff --git a/src/lib/ecore/efl_app.eo b/src/lib/ecore/efl_app.eo index f90324b39d..e046428626 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 +class Efl.App extends Efl.Loop implements Efl.Core.Command_Line { [[ ]] data: null; diff --git a/src/lib/ecore/efl_appthread.eo b/src/lib/ecore/efl_appthread.eo index c60308f468..82a9d77ace 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 +class Efl.Appthread extends Efl.Loop implements Efl.ThreadIO, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Efl.Core.Command_Line { [[ ]] methods { diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c index 4b3bc658d6..61ff4ba798 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 EINA_UNUSED, Efl_Exe_Data *pd) +_efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd) { #ifdef _WIN32 return EINA_FALSE; @@ -414,7 +414,7 @@ _efl_exe_efl_task_run(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd) if (!td) return NULL; // get a cmdline to run - cmd = efl_task_command_get(obj); + cmd = efl_core_command_line_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 111814af21..b7f97da7dc 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 +class Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer,Efl.Core.Command_Line { [[ ]] methods { diff --git a/src/lib/ecore/efl_loop.c b/src/lib/ecore/efl_loop.c index 68f9573b76..cf8600c998 100644 --- a/src/lib/ecore/efl_loop.c +++ b/src/lib/ecore/efl_loop.c @@ -383,17 +383,19 @@ _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; + Eina_Array *arga, *cml; 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_array_push(arga, eina_stringshare_add(argv[i])); - efl_task_arg_append(efl_main_loop_get(), argv[i]); + Eina_Stringshare *arg = eina_stringshare_add(argv[i]); + eina_array_push(arga, arg); + eina_array_push(cml, arg); } + 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 311de0506a..d610fcbf8b 100644 --- a/src/lib/ecore/efl_task.c +++ b/src/lib/ecore/efl_task.c @@ -12,303 +12,6 @@ ////////////////////////////////////////////////////////////////////////// -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) { @@ -344,7 +47,6 @@ _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 526746ff60..ddab5e6826 100644 --- a/src/lib/ecore/efl_task.eo +++ b/src/lib/ecore/efl_task.eo @@ -19,83 +19,6 @@ 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 4d48296093..a324af4f58 100644 --- a/src/lib/ecore/efl_thread.c +++ b/src/lib/ecore/efl_thread.c @@ -25,10 +25,7 @@ typedef struct int in, out; Eo *in_handler, *out_handler; } fd, ctrl; - struct { - unsigned int argc; - const char **argv; - } args; + Eina_Array *argv; Efl_Callback_Array_Item_Full *event_cb; void *indata, *outdata; } Thread_Data; @@ -151,16 +148,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; - unsigned int argc = efl_task_arg_count_get(obj); - unsigned int i; + Eina_Accessor *accessor; + const char *argv; + int i = 0; - arga = eina_array_new(argc); + accessor = efl_core_command_line_command_access(obj); + arga = eina_array_new(10); - for (i = 0; i < argc; i++) + EINA_ACCESSOR_FOREACH(accessor, i, argv) { - const char *argv = efl_task_arg_value_get(obj, i); - if (argv) - eina_array_push(arga, eina_stringshare_add(argv)); + eina_array_push(arga, eina_stringshare_add(argv)); } arge.argv = arga; arge.initialization = EINA_TRUE; @@ -229,7 +226,6 @@ _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; @@ -280,16 +276,13 @@ _efl_thread_main(void *data, Eina_Thread t) efl_event_callback_priority_add(obj, it->desc, it->priority, it->func, it->user_data); } - for (i = 0; i < thdat->args.argc; i++) - efl_task_arg_append(obj, thdat->args.argv[i]); + efl_core_command_line_command_array_set(obj, thdat->argv); efl_future_then(obj, efl_loop_job(obj), .success = _efl_loop_arguments_send); - for (i = 0; i < thdat->args.argc; i++) - eina_stringshare_del(thdat->args.argv[i]); - free(thdat->args.argv); + while (thdat->argv && eina_array_count(thdat->argv)) free(eina_array_pop(thdat->argv)); + eina_array_free(thdat->argv); free(thdat->event_cb); - thdat->args.argv = NULL; thdat->event_cb = NULL; ret = efl_loop_begin(obj); @@ -575,7 +568,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 argc, i, num; + unsigned int num; Efl_Callback_Array_Item_Full *it; Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS); @@ -729,24 +722,23 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd) name = efl_name_get(obj); if (name) thdat->name = eina_stringshare_add(name); - 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? - } + { + 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)); + } + } + + } + if (pd->event_cb) { num = 0; @@ -762,9 +754,8 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd) if (!eina_thread_create(&(pd->thread), pri, -1, _efl_thread_main, thdat)) { - for (i = 0; i < thdat->args.argc; i++) - eina_stringshare_del(thdat->args.argv[i]); - free(thdat->args.argv); + while (eina_array_count(thdat->argv)) eina_stringshare_del(eina_array_pop(thdat->argv)); + eina_array_free(thdat->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 7837c7bfdb..02bf2f15df 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 +class Efl.Thread extends Efl.Task implements Efl.ThreadIO, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Efl.Core.Command_Line { methods { } diff --git a/src/lib/ecore/meson.build b/src/lib/ecore/meson.build index 375f745abd..2e44804481 100644 --- a/src/lib/ecore/meson.build +++ b/src/lib/ecore/meson.build @@ -181,6 +181,7 @@ 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',