Revert command line array object because it's broken by design
Revert "ecore: get rid of commands in efl_task." This reverts commit616381e9cf
. Revert "ecore: here comes a command line object" This reverts commit48e5684b3c
. 1. this is broken: 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); } it returns a const char * BUT it duplicates it on return. no. a big fat honking NO. return a char * or don't duplicate. pick. 2. _efl_core_command_line_command_array_set() is broken by design. it accepts an array of strings, but the strings are owned by the caller who creates the array (requiring they free them up themselves after this call) but the array becomes owned by the callee. the code here frees the incoming array but doesn't care about the string content of it. it's leak heaven waiting to happen (or bugs when someone wants to access the array they create to walk it to free the strings they put into it after it is set). i brought this up and it was dismissed. now exactly he issue i brought up is there with mixed ownership and the added complexity as well as transfer of some ownership but not others. go back and think about this so it isn't broken by design.
This commit is contained in:
parent
e908142da6
commit
a57c7f7510
|
@ -52,10 +52,6 @@ ecore_eolian_files_public = \
|
||||||
lib/ecore/efl_view_model.eo \
|
lib/ecore/efl_view_model.eo \
|
||||||
lib/ecore/efl_core_env.eo \
|
lib/ecore/efl_core_env.eo \
|
||||||
lib/ecore/efl_core_proc_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 = \
|
||||||
$(ecore_eolian_files_legacy) \
|
$(ecore_eolian_files_legacy) \
|
||||||
|
@ -64,14 +60,10 @@ ecore_eolian_files = \
|
||||||
ecore_eolian_c = $(ecore_eolian_files:%.eo=%.eo.c)
|
ecore_eolian_c = $(ecore_eolian_files:%.eo=%.eo.c)
|
||||||
ecore_eolian_h = $(ecore_eolian_files:%.eo=%.eo.h) \
|
ecore_eolian_h = $(ecore_eolian_files:%.eo=%.eo.h) \
|
||||||
$(ecore_eolian_files_legacy:%.eo=%.eo.legacy.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 += \
|
BUILT_SOURCES += \
|
||||||
$(ecore_eolian_c) \
|
$(ecore_eolian_c) \
|
||||||
$(ecore_eolian_h) \
|
$(ecore_eolian_h)
|
||||||
$(ecore_test_c) \
|
|
||||||
$(ecore_test_h)
|
|
||||||
|
|
||||||
ecoreeolianfilesdir = $(datadir)/eolian/include/ecore-@VMAJ@
|
ecoreeolianfilesdir = $(datadir)/eolian/include/ecore-@VMAJ@
|
||||||
ecoreeolianfiles_DATA = $(ecore_eolian_files_public) lib/ecore/efl_loop_timer.eo
|
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_main.c \
|
||||||
lib/ecore/ecore_event_message.c \
|
lib/ecore/ecore_event_message.c \
|
||||||
lib/ecore/ecore_event_message_handler.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_env.c \
|
||||||
lib/ecore/efl_core_proc_env.c \
|
lib/ecore/efl_core_proc_env.c \
|
||||||
lib/ecore/efl_app.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_fd.c \
|
||||||
tests/ecore/efl_app_test_loop_timer.c \
|
tests/ecore/efl_app_test_loop_timer.c \
|
||||||
tests/ecore/efl_app_test_promise.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_test_env.c \
|
||||||
tests/ecore/efl_app_suite.c \
|
tests/ecore/efl_app_suite.c \
|
||||||
tests/ecore/efl_app_suite.h
|
tests/ecore/efl_app_suite.h
|
||||||
|
|
|
@ -104,9 +104,8 @@ namespace Efl {
|
||||||
public void Launch(Efl.Csharp.Components components=Components.Ui) {
|
public void Launch(Efl.Csharp.Components components=Components.Ui) {
|
||||||
Init(components);
|
Init(components);
|
||||||
Efl.App app = Efl.App.AppMain;
|
Efl.App app = Efl.App.AppMain;
|
||||||
Eina.Array<String> command_line = new Eina.Array<String>();
|
foreach (var arg in Environment.GetCommandLineArgs())
|
||||||
command_line.Append(Environment.GetCommandLineArgs());
|
app.AppendArg(arg);
|
||||||
app.SetCommandArray(command_line);
|
|
||||||
app.ArgumentsEvt += (object sender, LoopArgumentsEvt_Args evt) => {
|
app.ArgumentsEvt += (object sender, LoopArgumentsEvt_Args evt) => {
|
||||||
if (evt.arg.Initialization) {
|
if (evt.arg.Initialization) {
|
||||||
OnInitialize(evt.arg.Argv);
|
OnInitialize(evt.arg.Argv);
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#include "efl_core_env.eo.h"
|
#include "efl_core_env.eo.h"
|
||||||
#include "efl_core_proc_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.eo.h"
|
||||||
#include "efl_loop_message_handler.eo.h"
|
#include "efl_loop_message_handler.eo.h"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import efl_types;
|
import efl_types;
|
||||||
|
|
||||||
class Efl.App extends Efl.Loop implements Efl.Core.Command_Line
|
class Efl.App extends Efl.Loop
|
||||||
{
|
{
|
||||||
[[ ]]
|
[[ ]]
|
||||||
data: null;
|
data: null;
|
||||||
|
|
|
@ -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 {
|
methods {
|
||||||
|
|
|
@ -1,267 +0,0 @@
|
||||||
#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"
|
|
|
@ -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<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]]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -395,7 +395,7 @@ _efl_exe_efl_task_priority_get(const Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static Eina_Future *
|
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
|
#ifdef _WIN32
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
|
@ -414,7 +414,7 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
|
||||||
if (!td) return NULL;
|
if (!td) return NULL;
|
||||||
|
|
||||||
// get a cmdline to run
|
// get a cmdline to run
|
||||||
cmd = efl_core_command_line_command_get(obj);
|
cmd = efl_task_command_get(obj);
|
||||||
if (!cmd) return NULL;
|
if (!cmd) return NULL;
|
||||||
|
|
||||||
ret = pipe(pipe_exited);
|
ret = pipe(pipe_exited);
|
||||||
|
|
|
@ -19,7 +19,7 @@ enum Efl.Exe_Flags {
|
||||||
hide_io = 4
|
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 {
|
methods {
|
||||||
|
|
|
@ -383,19 +383,17 @@ _efl_loop_arguments_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *de
|
||||||
EAPI void
|
EAPI void
|
||||||
ecore_loop_arguments_send(int argc, const char **argv)
|
ecore_loop_arguments_send(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
Eina_Array *arga, *cml;
|
Eina_Array *arga;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
efl_task_arg_reset(efl_main_loop_get());
|
||||||
arga = eina_array_new(argc);
|
arga = eina_array_new(argc);
|
||||||
cml = eina_array_new(argc);
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
Eina_Stringshare *arg = eina_stringshare_add(argv[i]);
|
eina_array_push(arga, eina_stringshare_add(argv[i]));
|
||||||
eina_array_push(arga, arg);
|
efl_task_arg_append(efl_main_loop_get(), argv[i]);
|
||||||
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()),
|
efl_future_then(efl_main_loop_get(), efl_loop_job(efl_main_loop_get()),
|
||||||
.success = _efl_loop_arguments_send,
|
.success = _efl_loop_arguments_send,
|
||||||
.free = _efl_loop_arguments_cleanup,
|
.free = _efl_loop_arguments_cleanup,
|
||||||
|
|
|
@ -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
|
EOLIAN static void
|
||||||
_efl_task_priority_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, Efl_Task_Priority priority)
|
_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);
|
eina_stringshare_del(pd->command);
|
||||||
pd->command = NULL;
|
pd->command = NULL;
|
||||||
|
_clear_args(pd);
|
||||||
efl_destructor(efl_super(obj, MY_CLASS));
|
efl_destructor(efl_super(obj, MY_CLASS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,83 @@ abstract Efl.Task extends Efl.Object
|
||||||
{
|
{
|
||||||
[[ ]]
|
[[ ]]
|
||||||
methods {
|
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 {
|
@property priority {
|
||||||
[[ The priority of this task. ]]
|
[[ The priority of this task. ]]
|
||||||
get { }
|
get { }
|
||||||
|
|
|
@ -25,7 +25,10 @@ typedef struct
|
||||||
int in, out;
|
int in, out;
|
||||||
Eo *in_handler, *out_handler;
|
Eo *in_handler, *out_handler;
|
||||||
} fd, ctrl;
|
} fd, ctrl;
|
||||||
Eina_Array *argv;
|
struct {
|
||||||
|
unsigned int argc;
|
||||||
|
const char **argv;
|
||||||
|
} args;
|
||||||
Efl_Callback_Array_Item_Full *event_cb;
|
Efl_Callback_Array_Item_Full *event_cb;
|
||||||
void *indata, *outdata;
|
void *indata, *outdata;
|
||||||
} Thread_Data;
|
} Thread_Data;
|
||||||
|
@ -148,16 +151,16 @@ _efl_loop_arguments_send(Eo *obj, void *data EINA_UNUSED, const Eina_Value v)
|
||||||
Efl_Loop_Arguments arge;
|
Efl_Loop_Arguments arge;
|
||||||
Eina_Array *arga;
|
Eina_Array *arga;
|
||||||
Eina_Stringshare *s;
|
Eina_Stringshare *s;
|
||||||
Eina_Accessor *accessor;
|
unsigned int argc = efl_task_arg_count_get(obj);
|
||||||
const char *argv;
|
unsigned int i;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
accessor = efl_core_command_line_command_access(obj);
|
arga = eina_array_new(argc);
|
||||||
arga = eina_array_new(10);
|
|
||||||
|
|
||||||
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.argv = arga;
|
||||||
arge.initialization = EINA_TRUE;
|
arge.initialization = EINA_TRUE;
|
||||||
|
@ -226,6 +229,7 @@ _efl_thread_main(void *data, Eina_Thread t)
|
||||||
Eo *obj;
|
Eo *obj;
|
||||||
Eina_Value *ret;
|
Eina_Value *ret;
|
||||||
Control_Data cmd;
|
Control_Data cmd;
|
||||||
|
unsigned int i;
|
||||||
int real;
|
int real;
|
||||||
Efl_Callback_Array_Item_Full *it;
|
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,
|
efl_event_callback_priority_add(obj, it->desc, it->priority,
|
||||||
it->func, it->user_data);
|
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),
|
efl_future_then(obj, efl_loop_job(obj),
|
||||||
.success = _efl_loop_arguments_send);
|
.success = _efl_loop_arguments_send);
|
||||||
|
|
||||||
while (thdat->argv && eina_array_count(thdat->argv)) free(eina_array_pop(thdat->argv));
|
for (i = 0; i < thdat->args.argc; i++)
|
||||||
eina_array_free(thdat->argv);
|
eina_stringshare_del(thdat->args.argv[i]);
|
||||||
|
free(thdat->args.argv);
|
||||||
free(thdat->event_cb);
|
free(thdat->event_cb);
|
||||||
|
thdat->args.argv = NULL;
|
||||||
thdat->event_cb = NULL;
|
thdat->event_cb = NULL;
|
||||||
|
|
||||||
ret = efl_loop_begin(obj);
|
ret = efl_loop_begin(obj);
|
||||||
|
@ -568,7 +575,7 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
|
||||||
const char *name;
|
const char *name;
|
||||||
int pipe_to_thread[2];
|
int pipe_to_thread[2];
|
||||||
int pipe_from_thread[2];
|
int pipe_from_thread[2];
|
||||||
unsigned int num;
|
unsigned int argc, i, num;
|
||||||
Efl_Callback_Array_Item_Full *it;
|
Efl_Callback_Array_Item_Full *it;
|
||||||
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
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);
|
name = efl_name_get(obj);
|
||||||
if (name) thdat->name = eina_stringshare_add(name);
|
if (name) thdat->name = eina_stringshare_add(name);
|
||||||
|
|
||||||
{
|
argc = efl_task_arg_count_get(obj);
|
||||||
Eina_Accessor *acc;
|
if (argc > 0)
|
||||||
int i = 0;
|
{
|
||||||
const char *argv;
|
thdat->args.argc = argc;
|
||||||
|
thdat->args.argv = malloc(argc * sizeof(char *));
|
||||||
acc = efl_core_command_line_command_access(obj);
|
if (thdat->args.argv)
|
||||||
if (acc)
|
{
|
||||||
{
|
for (i = 0; i < argc; i++)
|
||||||
thdat->argv = eina_array_new(0);
|
{
|
||||||
EINA_ACCESSOR_FOREACH(acc, i, argv)
|
const char *argv = efl_task_arg_value_get(obj, i);
|
||||||
{
|
if (argv)
|
||||||
eina_array_push(thdat->argv, eina_stringshare_add(argv));
|
thdat->args.argv[i] = eina_stringshare_add(argv);
|
||||||
}
|
else
|
||||||
}
|
thdat->args.argv[i] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// XXX: if malloc fails?
|
||||||
|
}
|
||||||
if (pd->event_cb)
|
if (pd->event_cb)
|
||||||
{
|
{
|
||||||
num = 0;
|
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))
|
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));
|
for (i = 0; i < thdat->args.argc; i++)
|
||||||
eina_array_free(thdat->argv);
|
eina_stringshare_del(thdat->args.argv[i]);
|
||||||
|
free(thdat->args.argv);
|
||||||
efl_del(pd->fd.in_handler);
|
efl_del(pd->fd.in_handler);
|
||||||
efl_del(pd->fd.out_handler);
|
efl_del(pd->fd.out_handler);
|
||||||
efl_del(pd->ctrl.in_handler);
|
efl_del(pd->ctrl.in_handler);
|
||||||
|
|
|
@ -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 {
|
methods {
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,8 +76,7 @@ pub_eo_files = [
|
||||||
'efl_composite_model.eo',
|
'efl_composite_model.eo',
|
||||||
'efl_view_model.eo',
|
'efl_view_model.eo',
|
||||||
'efl_core_env.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
|
foreach eo_file : pub_eo_files
|
||||||
|
@ -181,12 +180,10 @@ ecore_src = [
|
||||||
'ecore_main_common.h',
|
'ecore_main_common.h',
|
||||||
'efl_exe.c',
|
'efl_exe.c',
|
||||||
'efl_thread.c',
|
'efl_thread.c',
|
||||||
'efl_appthread.c',
|
|
||||||
'efl_threadio.c',
|
'efl_threadio.c',
|
||||||
'efl_appthread.c',
|
'efl_appthread.c',
|
||||||
'efl_core_env.c',
|
'efl_core_env.c',
|
||||||
'efl_core_proc_env.c',
|
'efl_core_proc_env.c',
|
||||||
'efl_core_command_line.c',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if sys_windows == true
|
if sys_windows == true
|
||||||
|
|
|
@ -53,7 +53,6 @@ static const Efl_Test_Case etc[] = {
|
||||||
{ "Promise", efl_app_test_promise_3 },
|
{ "Promise", efl_app_test_promise_3 },
|
||||||
{ "Promise", efl_app_test_promise_safety },
|
{ "Promise", efl_app_test_promise_safety },
|
||||||
{ "Env", efl_test_efl_env },
|
{ "Env", efl_test_efl_env },
|
||||||
{ "CML", efl_test_efl_cml },
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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_3(TCase *tc);
|
||||||
void efl_app_test_promise_safety(TCase *tc);
|
void efl_app_test_promise_safety(TCase *tc);
|
||||||
void efl_test_efl_env(TCase *tc);
|
void efl_test_efl_env(TCase *tc);
|
||||||
void efl_test_efl_cml(TCase *tc);
|
|
||||||
|
|
||||||
#endif /* _EFL_APP_SUITE_H */
|
#endif /* _EFL_APP_SUITE_H */
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
class Efl.App.Test.CML extends Efl.Object implements Efl.Core.Command_Line
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -76,32 +76,14 @@ efl_app_suite_src = [
|
||||||
'efl_app_test_loop_fd.c',
|
'efl_app_test_loop_fd.c',
|
||||||
'efl_app_test_loop_timer.c',
|
'efl_app_test_loop_timer.c',
|
||||||
'efl_app_test_promise.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 = [m]
|
||||||
efl_app_suite_deps += ecore
|
efl_app_suite_deps += ecore
|
||||||
|
|
||||||
efl_app_suite = executable('efl_app_suite',
|
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],
|
dependencies: [efl_app_suite_deps, check],
|
||||||
c_args : [
|
c_args : [
|
||||||
'-DTESTS_BUILD_DIR="'+meson.current_build_dir()+'"',
|
'-DTESTS_BUILD_DIR="'+meson.current_build_dir()+'"',
|
||||||
|
|
Loading…
Reference in New Issue