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) \
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_eolian_h) \
+ $(ecore_test_c) \
+ $(ecore_test_h)
ecoreeolianfilesdir = $(datadir)/eolian/include/ecore-@VMAJ@
ecoreeolianfiles_DATA = $(ecore_eolian_files_public) lib/ecore/efl_loop_timer.eo
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 \
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
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<String> command_line = new Eina.Array<String>();
+ command_line.Append(Environment.GetCommandLineArgs());
+ app.SetCommandArray(command_line);
app.ArgumentsEvt += (object sender, LoopArgumentsEvt_Args evt) => {
if (evt.arg.Initialization) {
OnInitialize(evt.arg.Argv);
#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"
import efl_types;
-class Efl.App extends Efl.Loop
+class Efl.App extends Efl.Loop implements Efl.Core.Command_Line
{
[[ ]]
data: null;
-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 {
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define EFL_CORE_COMMAND_LINE_PROTECTED
+
+#include <Efl_Core.h>
+
+#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"
--- /dev/null
+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<stringshare>;
+ }
+ @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<string> @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]]
+ }
+
+ }
+ }
+}
}
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;
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);
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 {
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,
//////////////////////////////////////////////////////////////////////////
-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)
{
{
eina_stringshare_del(pd->command);
pd->command = NULL;
- _clear_args(pd);
efl_destructor(efl_super(obj, MY_CLASS));
}
{
[[ ]]
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 { }
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;
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;
Eo *obj;
Eina_Value *ret;
Control_Data cmd;
- unsigned int i;
int real;
Efl_Callback_Array_Item_Full *it;
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);
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);
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;
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);
-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 {
}
'efl_composite_model.eo',
'efl_view_model.eo',
'efl_core_env.eo',
- 'efl_core_proc_env.eo'
+ 'efl_core_proc_env.eo',
+ 'efl_core_command_line.eo',
]
foreach eo_file : pub_eo_files
'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
{ "Promise", efl_app_test_promise_3 },
{ "Promise", efl_app_test_promise_safety },
{ "Env", efl_test_efl_env },
+ { "CML", efl_test_efl_cml },
{ NULL, NULL }
};
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 */
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define EFL_CORE_COMMAND_LINE_PROTECTED
+
+#include <stdio.h>
+#include <unistd.h>
+#define EFL_NOLEGACY_API_SUPPORT
+#include <Efl_Core.h>
+#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);
+}
--- /dev/null
+class Efl.App.Test.CML extends Efl.Object implements Efl.Core.Command_Line
+{
+
+}
'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_env.c',
+ 'efl_app_test_cml.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,
+ efl_app_suite_src, priv_eo_file_target,
dependencies: [efl_app_suite_deps, check],
c_args : [
'-DTESTS_BUILD_DIR="'+meson.current_build_dir()+'"',