implement [[ ]] debashify
This commit is contained in:
parent
9c2f3c91f9
commit
c12ec601f1
6 changed files with 259 additions and 54 deletions
|
|
@ -3,13 +3,28 @@
|
||||||
|
|
||||||
#include "struc.hpp"
|
#include "struc.hpp"
|
||||||
|
|
||||||
|
// makers
|
||||||
arg* make_arg(std::string const& in);
|
arg* make_arg(std::string const& in);
|
||||||
|
|
||||||
cmd* make_cmd(std::vector<std::string> const& args);
|
cmd* make_cmd(std::vector<std::string> const& args);
|
||||||
|
cmd* make_cmd(std::vector<arg*> const& args);
|
||||||
cmd* make_cmd(std::string const& in);
|
cmd* make_cmd(std::string const& in);
|
||||||
|
|
||||||
|
pipeline* make_pipeline(std::vector<block*> const& bls);
|
||||||
|
pipeline* make_pipeline(std::string const& in);
|
||||||
|
|
||||||
condlist* make_condlist(std::string const& in);
|
condlist* make_condlist(std::string const& in);
|
||||||
|
list* make_list(std::string const& in);
|
||||||
|
|
||||||
|
// testers
|
||||||
|
|
||||||
|
bool arg_has_char(char c, arg* in);
|
||||||
|
|
||||||
|
// modifiers
|
||||||
void force_quotes(arg* in);
|
void force_quotes(arg* in);
|
||||||
|
void add_quotes(arg* in);
|
||||||
|
|
||||||
|
// operators
|
||||||
inline bool operator==(arg a, std::string const& b) { return a.equals(b); }
|
inline bool operator==(arg a, std::string const& b) { return a.equals(b); }
|
||||||
|
|
||||||
#endif //STRUC_HELPER_HPP
|
#endif //STRUC_HELPER_HPP
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,11 @@ std::string strf( const std::string& format, Args ... args )
|
||||||
return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
|
return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T, typename ... Args>
|
||||||
|
std::vector<T> make_vector(Args ... args)
|
||||||
|
{
|
||||||
|
return std::vector<T>( { args... } );
|
||||||
|
}
|
||||||
|
|
||||||
template <class KEY, class VAL>
|
template <class KEY, class VAL>
|
||||||
std::vector<std::pair<KEY, VAL>> sort_by_value(std::map<KEY,VAL> const& in)
|
std::vector<std::pair<KEY, VAL>> sort_by_value(std::map<KEY,VAL> const& in)
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,103 @@
|
||||||
#include "parse.hpp"
|
#include "parse.hpp"
|
||||||
#include "struc_helper.hpp"
|
#include "struc_helper.hpp"
|
||||||
|
|
||||||
bool debashify_bashtest(cmd* in)
|
/*
|
||||||
|
[[ ]] debashifying:
|
||||||
|
[[ EXPRESSION && EXPRESSION ]] separated into two parts
|
||||||
|
EXPRESSION : gen_bashtest_cmd
|
||||||
|
&& , || : debashify_bashtest
|
||||||
|
*/
|
||||||
|
|
||||||
|
// [[ $a = b ]] : quote vars
|
||||||
|
// [[ a == b ]] : replace == with =
|
||||||
|
// [[ a = b* ]] : case a in b*) true;; *) false;; esac
|
||||||
|
// [[ a =~ b ]] : echo a | grep -q b
|
||||||
|
pipeline* gen_bashtest_cmd(std::vector<arg*> args)
|
||||||
{
|
{
|
||||||
|
pipeline* ret = nullptr;
|
||||||
|
|
||||||
|
if(args.size() == 3 && args[1]->string() == "==")
|
||||||
|
{
|
||||||
|
delete args[1]->sa[0];
|
||||||
|
args[1]->sa[0] = new string_subarg("=");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(args.size() == 3 && args[1]->string() == "=" && arg_has_char('*', args[2]))
|
||||||
|
{
|
||||||
|
delete args[1];
|
||||||
|
args[1]=nullptr;
|
||||||
|
case_block* tc = new case_block(args[0]);
|
||||||
|
tc->cases.push_back( std::make_pair(std::vector<arg*>({args[2]}), make_list("true")) );
|
||||||
|
tc->cases.push_back( std::make_pair(std::vector<arg*>({new arg("*")}), make_list("false")) );
|
||||||
|
ret = new pipeline(tc);
|
||||||
|
}
|
||||||
|
else if(args.size() == 3 && args[1]->string() == "=~")
|
||||||
|
{
|
||||||
|
delete args[1];
|
||||||
|
args[1]=nullptr;
|
||||||
|
cmd* echo_arg1 = make_cmd( std::vector<arg*>({ new arg("echo"), args[0] }) );
|
||||||
|
cmd* grep_arg2 = make_cmd( std::vector<arg*>({ new arg("grep"), new arg("-q"), new arg("--"), args[2] }) );
|
||||||
|
add_quotes(args[2]);
|
||||||
|
ret = make_pipeline( std::vector<block*>({echo_arg1, grep_arg2}) );
|
||||||
|
}
|
||||||
|
else // regular [ ]
|
||||||
|
{
|
||||||
|
cmd* t = make_cmd(args);
|
||||||
|
t->args->insert(0, new arg("["));
|
||||||
|
t->add(new arg("]"));
|
||||||
|
ret = new pipeline(t);
|
||||||
|
}
|
||||||
|
// arg oblivious replacements:
|
||||||
|
// quote variables
|
||||||
|
for(auto it: args)
|
||||||
|
{
|
||||||
|
if(it!=nullptr)
|
||||||
|
force_quotes(it);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [[ a && b ]] : [ a ] && [ b ]
|
||||||
|
bool debashify_bashtest(pipeline* pl)
|
||||||
|
{
|
||||||
|
if(pl->cmds.size()<=0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(pl->cmds[0]->type != _obj::block_cmd)
|
||||||
|
return false;
|
||||||
|
cmd* in = dynamic_cast<cmd*>(pl->cmds[0]);
|
||||||
|
|
||||||
if(in->firstarg_string() == "[[")
|
if(in->firstarg_string() == "[[")
|
||||||
throw std::runtime_error("Cannot debashify '[[ ]]'");
|
{
|
||||||
|
// throw std::runtime_error("Cannot debashify '[[ ]]'");
|
||||||
|
brace* br = new brace(new list);
|
||||||
|
condlist* cl = new condlist;
|
||||||
|
br->lst->add(cl);
|
||||||
|
|
||||||
|
arg *a=nullptr;
|
||||||
|
uint32_t j=1;
|
||||||
|
bool or_op=false;
|
||||||
|
for(uint32_t i=1 ; i<in->args->size() ; i++)
|
||||||
|
{
|
||||||
|
a = in->args->args[i];
|
||||||
|
|
||||||
|
if(i >= in->args->size()-1 || a->string() == "&&" || a->string() == "||")
|
||||||
|
{
|
||||||
|
pipeline* tpl = gen_bashtest_cmd(std::vector<arg*>(in->args->args.begin()+j, in->args->args.begin()+i));
|
||||||
|
cl->add(tpl, or_op);
|
||||||
|
or_op = a->string() == "||";
|
||||||
|
j=i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete in->args->args[0];
|
||||||
|
delete in->args->args[in->args->args.size()-1];
|
||||||
|
in->args->args.resize(0);
|
||||||
|
delete in;
|
||||||
|
pl->cmds[0] = br;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -204,11 +297,11 @@ bool r_debashify(_obj* o, bool* need_random_func)
|
||||||
case _obj::_pipeline: {
|
case _obj::_pipeline: {
|
||||||
pipeline* t = dynamic_cast<pipeline*>(o);
|
pipeline* t = dynamic_cast<pipeline*>(o);
|
||||||
debashify_herestring(t);
|
debashify_herestring(t);
|
||||||
|
debashify_bashtest(t);
|
||||||
} break;
|
} break;
|
||||||
case _obj::block_cmd: {
|
case _obj::block_cmd: {
|
||||||
cmd* t = dynamic_cast<cmd*>(o);
|
cmd* t = dynamic_cast<cmd*>(o);
|
||||||
debashify_combined_redirects(t);
|
debashify_combined_redirects(t);
|
||||||
debashify_bashtest(t);
|
|
||||||
debashify_declare(t);
|
debashify_declare(t);
|
||||||
debashify_array_def(t);
|
debashify_array_def(t);
|
||||||
} break;
|
} break;
|
||||||
|
|
|
||||||
20
src/main.cpp
20
src/main.cpp
|
|
@ -20,12 +20,17 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "g_version.h"
|
#include "g_version.h"
|
||||||
|
|
||||||
|
#define ERR_HELP 1001
|
||||||
|
#define ERR_OPT 1002
|
||||||
|
#define ERR_PARSE 1003
|
||||||
|
#define ERR_RUNTIME 1004
|
||||||
|
|
||||||
void oneshot_opt_process(const char* arg0)
|
void oneshot_opt_process(const char* arg0)
|
||||||
{
|
{
|
||||||
if(options['h'])
|
if(options['h'])
|
||||||
{
|
{
|
||||||
print_help(arg0);
|
print_help(arg0);
|
||||||
exit(0);
|
exit(ERR_HELP);
|
||||||
}
|
}
|
||||||
else if(options["version"])
|
else if(options["version"])
|
||||||
{
|
{
|
||||||
|
|
@ -38,7 +43,7 @@ void oneshot_opt_process(const char* arg0)
|
||||||
print_include_help();
|
print_include_help();
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
print_resolve_help();
|
print_resolve_help();
|
||||||
exit(0);
|
exit(ERR_HELP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,7 +60,7 @@ int main(int argc, char* argv[])
|
||||||
catch(std::exception& e)
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
return 1;
|
return ERR_OPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
oneshot_opt_process(argv[0]);
|
oneshot_opt_process(argv[0]);
|
||||||
|
|
@ -78,7 +83,7 @@ int main(int argc, char* argv[])
|
||||||
if(isatty(fileno(stdin))) // stdin is interactive
|
if(isatty(fileno(stdin))) // stdin is interactive
|
||||||
{
|
{
|
||||||
print_help(argv[0]);
|
print_help(argv[0]);
|
||||||
return 1;
|
return ERR_HELP;
|
||||||
}
|
}
|
||||||
else // is piped
|
else // is piped
|
||||||
{
|
{
|
||||||
|
|
@ -132,7 +137,10 @@ int main(int argc, char* argv[])
|
||||||
continue;
|
continue;
|
||||||
tsh = parse_text(filecontents, file);
|
tsh = parse_text(filecontents, file);
|
||||||
if(shebang_is_bin) // resolve lxsh shebang to sh
|
if(shebang_is_bin) // resolve lxsh shebang to sh
|
||||||
|
{
|
||||||
|
options["debashify"].activated=true;
|
||||||
tsh->shebang="#!/bin/sh";
|
tsh->shebang="#!/bin/sh";
|
||||||
|
}
|
||||||
|
|
||||||
/* mid processing */
|
/* mid processing */
|
||||||
// resolve/include
|
// resolve/include
|
||||||
|
|
@ -211,7 +219,7 @@ int main(int argc, char* argv[])
|
||||||
delete tsh;
|
delete tsh;
|
||||||
delete sh;
|
delete sh;
|
||||||
printFormatError(e);
|
printFormatError(e);
|
||||||
return 100;
|
return ERR_PARSE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
catch(std::runtime_error& e)
|
catch(std::runtime_error& e)
|
||||||
|
|
@ -220,7 +228,7 @@ int main(int argc, char* argv[])
|
||||||
delete tsh;
|
delete tsh;
|
||||||
delete sh;
|
delete sh;
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
return 2;
|
return ERR_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete sh;
|
delete sh;
|
||||||
|
|
|
||||||
111
src/parse.cpp
111
src/parse.cpp
|
|
@ -510,7 +510,7 @@ std::pair<redirect*, uint32_t> parse_redirect(const char* in, uint32_t size, uin
|
||||||
else if(in[i] == '&') // >& bash operator
|
else if(in[i] == '&') // >& bash operator
|
||||||
{
|
{
|
||||||
if(!g_bash)
|
if(!g_bash)
|
||||||
throw PARSE_ERROR("bash specific: '>&'. Use --debashify to remove bashisms", i);
|
throw PARSE_ERROR("bash specific: '>&'", i);
|
||||||
i++;
|
i++;
|
||||||
needs_arg=true;
|
needs_arg=true;
|
||||||
}
|
}
|
||||||
|
|
@ -534,7 +534,7 @@ std::pair<redirect*, uint32_t> parse_redirect(const char* in, uint32_t size, uin
|
||||||
if(i<size && in[i] == '<')
|
if(i<size && in[i] == '<')
|
||||||
{
|
{
|
||||||
if(!g_bash)
|
if(!g_bash)
|
||||||
throw PARSE_ERROR("bash specific: '<<<'. Use --debashify to remove bashisms", i);
|
throw PARSE_ERROR("bash specific: '<<<'", i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -544,7 +544,7 @@ std::pair<redirect*, uint32_t> parse_redirect(const char* in, uint32_t size, uin
|
||||||
else if( word_eq("&>", in, size, i) ) // &> bash operator
|
else if( word_eq("&>", in, size, i) ) // &> bash operator
|
||||||
{
|
{
|
||||||
if(!g_bash)
|
if(!g_bash)
|
||||||
throw PARSE_ERROR("bash specific: '&>'. Use --debashify to remove bashisms", i);
|
throw PARSE_ERROR("bash specific: '&>'", i);
|
||||||
i+=2;
|
i+=2;
|
||||||
if(i<size && in[i] == '>')
|
if(i<size && in[i] == '>')
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -640,55 +640,86 @@ std::pair<arglist*, uint32_t> parse_arglist(const char* in, uint32_t size, uint3
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
if(is_in(in[i], SPECIAL_TOKENS) && !word_eq("&>", in, size, i))
|
;
|
||||||
|
if(word_eq("[[", in, size, i, ARG_END) ) // [[ bash specific parsing
|
||||||
|
{
|
||||||
|
if(!g_bash)
|
||||||
|
throw PARSE_ERROR("bash specific: '[['", i);
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
if(ret == nullptr)
|
||||||
|
ret = new arglist;
|
||||||
|
auto pp=parse_arg(in, size, i, SEPARATORS, NULL);
|
||||||
|
ret->add(pp.first);
|
||||||
|
i = pp.second;
|
||||||
|
i = skip_chars(in, size, i, SEPARATORS);
|
||||||
|
if(word_eq("]]", in, size, i, ARG_END))
|
||||||
|
{
|
||||||
|
ret->add(new arg("]]"));
|
||||||
|
i = skip_chars(in, size, i+2, SEPARATORS);
|
||||||
|
if( !is_in(in[i], ARGLIST_END) )
|
||||||
|
throw PARSE_ERROR("Unexpected argument after ']]'", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i>=size)
|
||||||
|
throw PARSE_ERROR( "Expecting ']]'", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(is_in(in[i], SPECIAL_TOKENS) && !word_eq("&>", in, size, i))
|
||||||
{
|
{
|
||||||
if(hard_error)
|
if(hard_error)
|
||||||
throw PARSE_ERROR( strf("Unexpected token '%c'", in[i]) , i);
|
throw PARSE_ERROR( strf("Unexpected token '%c'", in[i]) , i);
|
||||||
else
|
else
|
||||||
return std::make_pair(ret, i);
|
return std::make_pair(ret, i);
|
||||||
}
|
}
|
||||||
while(i<size)
|
else
|
||||||
{
|
{
|
||||||
if(i+1 < size && (in[i] == '<' || in[i] == '>') && in[i+1] == '(' ) // bash specific <()
|
while(i<size)
|
||||||
{
|
{
|
||||||
bool is_output = in[i] == '>';
|
if(i+1 < size && (in[i] == '<' || in[i] == '>') && in[i+1] == '(' ) // bash specific <()
|
||||||
i+=2;
|
|
||||||
if(ret == nullptr)
|
|
||||||
ret = new arglist;
|
|
||||||
auto ps = parse_subshell(in, size, i);
|
|
||||||
ret->add(new arg(new procsub_subarg(is_output, ps.first)));
|
|
||||||
i=ps.second;
|
|
||||||
}
|
|
||||||
else if(redirs!=nullptr)
|
|
||||||
{
|
|
||||||
auto pr = parse_redirect(in, size, i);
|
|
||||||
if(pr.first != nullptr)
|
|
||||||
{
|
{
|
||||||
redirs->push_back(pr.first);
|
bool is_output = in[i] == '>';
|
||||||
i=pr.second;
|
i+=2;
|
||||||
|
if(ret == nullptr)
|
||||||
|
ret = new arglist;
|
||||||
|
auto ps = parse_subshell(in, size, i);
|
||||||
|
ret->add(new arg(new procsub_subarg(is_output, ps.first)));
|
||||||
|
i=ps.second;
|
||||||
|
}
|
||||||
|
else if(redirs!=nullptr)
|
||||||
|
{
|
||||||
|
auto pr = parse_redirect(in, size, i);
|
||||||
|
if(pr.first != nullptr)
|
||||||
|
{
|
||||||
|
redirs->push_back(pr.first);
|
||||||
|
i=pr.second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto argparse;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto argparse;
|
{
|
||||||
|
argparse:
|
||||||
|
if(ret == nullptr)
|
||||||
|
ret = new arglist;
|
||||||
|
auto pp=parse_arg(in, size, i);
|
||||||
|
ret->add(pp.first);
|
||||||
|
i = pp.second;
|
||||||
|
}
|
||||||
|
i = skip_chars(in, size, i, SPACES);
|
||||||
|
if(word_eq("&>", in, size, i))
|
||||||
|
continue; // &> has to be managed in redirects
|
||||||
|
if(word_eq("|&", in, size, i))
|
||||||
|
throw PARSE_ERROR("Unsupported '|&', use '2>&1 |' instead", i);
|
||||||
|
if(i>=size)
|
||||||
|
return std::make_pair(ret, i);
|
||||||
|
if( is_in(in[i], SPECIAL_TOKENS) )
|
||||||
|
return std::make_pair(ret, i);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
argparse:
|
|
||||||
if(ret == nullptr)
|
|
||||||
ret = new arglist;
|
|
||||||
auto pp=parse_arg(in, size, i);
|
|
||||||
ret->add(pp.first);
|
|
||||||
i = pp.second;
|
|
||||||
}
|
|
||||||
i = skip_chars(in, size, i, SPACES);
|
|
||||||
if(word_eq("&>", in, size, i))
|
|
||||||
continue; // &> has to be managed in redirects
|
|
||||||
if(word_eq("|&", in, size, i))
|
|
||||||
throw PARSE_ERROR("Unsupported '|&', use '2>&1 |' instead", i);
|
|
||||||
if(i>=size)
|
|
||||||
return std::make_pair(ret, i);
|
|
||||||
if( is_in(in[i], SPECIAL_TOKENS) )
|
|
||||||
return std::make_pair(ret, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_PARSE_CATCH
|
#ifndef NO_PARSE_CATCH
|
||||||
}
|
}
|
||||||
catch(ztd::format_error& e)
|
catch(ztd::format_error& e)
|
||||||
|
|
@ -1437,7 +1468,7 @@ std::pair<block*, uint32_t> parse_block(const char* in, uint32_t size, uint32_t
|
||||||
else if( word == "function" ) // bash style function
|
else if( word == "function" ) // bash style function
|
||||||
{
|
{
|
||||||
if(!g_bash)
|
if(!g_bash)
|
||||||
throw PARSE_ERROR("bash specific: 'function'. Use --debashify to remove bashisms", i);
|
throw PARSE_ERROR("bash specific: 'function'", i);
|
||||||
auto wp2=get_word(in, size, skip_unread(in, size, wp.second), VARNAME_END);
|
auto wp2=get_word(in, size, skip_unread(in, size, wp.second), VARNAME_END);
|
||||||
if(!valid_name(wp2.first))
|
if(!valid_name(wp2.first))
|
||||||
throw PARSE_ERROR( strf("Bad function name: '%s'", word.c_str()), start );
|
throw PARSE_ERROR( strf("Bad function name: '%s'", word.c_str()), start );
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,21 @@ arg* make_arg(std::string const& in)
|
||||||
|
|
||||||
cmd* make_cmd(std::vector<std::string> const& args)
|
cmd* make_cmd(std::vector<std::string> const& args)
|
||||||
{
|
{
|
||||||
cmd* ret = new cmd();
|
cmd* ret = new cmd;
|
||||||
ret->args = new arglist();
|
ret->args = new arglist;
|
||||||
for(auto it: args)
|
for(auto it: args)
|
||||||
{
|
|
||||||
ret->args->add(new arg(it));
|
ret->args->add(new arg(it));
|
||||||
}
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd* make_cmd(std::vector<arg*> const& args)
|
||||||
|
{
|
||||||
|
cmd* ret = new cmd;
|
||||||
|
ret->args = new arglist;
|
||||||
|
for(auto it: args)
|
||||||
|
ret->args->add(it);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,11 +37,30 @@ cmd* make_cmd(std::string const& in)
|
||||||
return parse_cmd(in.c_str(), in.size(), 0).first;
|
return parse_cmd(in.c_str(), in.size(), 0).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pipeline* make_pipeline(std::vector<block*> const& bls)
|
||||||
|
{
|
||||||
|
pipeline* ret = new pipeline;
|
||||||
|
for(auto it: bls)
|
||||||
|
ret->add(it);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline* make_pipeline(std::string const& in)
|
||||||
|
{
|
||||||
|
return parse_pipeline(in.c_str(), in.size(), 0).first;
|
||||||
|
}
|
||||||
|
|
||||||
condlist* make_condlist(std::string const& in)
|
condlist* make_condlist(std::string const& in)
|
||||||
{
|
{
|
||||||
return parse_condlist(in.c_str(), in.size(), 0).first;
|
return parse_condlist(in.c_str(), in.size(), 0).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list* make_list(std::string const& in)
|
||||||
|
{
|
||||||
|
return parse_list_until(in.c_str(), in.size(), 0, 0).first;
|
||||||
|
}
|
||||||
|
|
||||||
// modifiers
|
// modifiers
|
||||||
|
|
||||||
void force_quotes(arg* in)
|
void force_quotes(arg* in)
|
||||||
|
|
@ -42,13 +70,38 @@ void force_quotes(arg* in)
|
||||||
if(!in->sa[i]->quoted && (in->sa[i]->type == _obj::subarg_variable || in->sa[i]->type == _obj::subarg_manipulation || in->sa[i]->type == _obj::subarg_subshell) )
|
if(!in->sa[i]->quoted && (in->sa[i]->type == _obj::subarg_variable || in->sa[i]->type == _obj::subarg_manipulation || in->sa[i]->type == _obj::subarg_subshell) )
|
||||||
{
|
{
|
||||||
in->sa[i]->quoted=true;
|
in->sa[i]->quoted=true;
|
||||||
|
in->insert(i+1, new string_subarg("\""));
|
||||||
in->insert(i, new string_subarg("\""));
|
in->insert(i, new string_subarg("\""));
|
||||||
i+=2;
|
i+=2;
|
||||||
in->insert(i, new string_subarg("\""));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_quotes(arg* in)
|
||||||
|
{
|
||||||
|
for(uint32_t i=0; i < in->sa.size() ; i++)
|
||||||
|
in->sa[i]->quoted=true;
|
||||||
|
|
||||||
|
in->insert(0, new string_subarg("\""));
|
||||||
|
in->add(new string_subarg("\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ** TESTERS ** //
|
||||||
|
|
||||||
|
bool arg_has_char(char c, arg* in)
|
||||||
|
{
|
||||||
|
for(auto it: in->sa)
|
||||||
|
{
|
||||||
|
if(it->type == _obj::subarg_string)
|
||||||
|
{
|
||||||
|
string_subarg* t = dynamic_cast<string_subarg*>(it);
|
||||||
|
if(t->val.find(c) != std::string::npos)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ** CLASS EXTENSIONS ** //
|
// ** CLASS EXTENSIONS ** //
|
||||||
|
|
||||||
/// GETTERS ///
|
/// GETTERS ///
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue