Compare commits

..

No commits in common. "master" and "v1.3.1" have entirely different histories.

52 changed files with 920 additions and 2444 deletions

6
.gitignore vendored
View file

@ -1,8 +1,10 @@
/obj /obj
/test
/run-tests.sh
/Zmakefile /Zmakefile
TODO /TODO
/lxsh /lxsh
gmon.out /gmon.out
/profiling/* /profiling/*
/profiling.* /profiling.*
/include/g_* /include/g_*

View file

@ -45,7 +45,7 @@ These commands can be placed anywhere within the script like regular commands.
Reduce code size to a minimum without changing functionality with the `-m` option. Reduce code size to a minimum without changing functionality with the `-m` option.
> This option should be safe to use in any situation, if this option changes behavior please report a bug > This option should be safe to use in any situation
#### Behaviors of the minify option #### Behaviors of the minify option
@ -53,9 +53,7 @@ Reduce code size to a minimum without changing functionality with the `-m` optio
- removes `;;` from the last value in a case - removes `;;` from the last value in a case
- removes unnecessary quotes on arguments - removes unnecessary quotes on arguments
- transforms unnecessary manipulations (e.g. `${VAR}`) into simple variable call - transforms unnecessary manipulations (e.g. `${VAR}`) into simple variable call
- brace blocks or subshells with a single command will be replaced by said command - Brace blocks or subshells with a single command will be replaced by said command
- reduces level 1 `$()` subshells to use backticks
- escaped dollarsigns are un-escaped
> These features only apply if they won't change behavior, for instance > These features only apply if they won't change behavior, for instance
removal of an unnecessary manipulation will not be made if the following character removal of an unnecessary manipulation will not be made if the following character

View file

@ -2,19 +2,12 @@
#define MINIFY_HPP #define MINIFY_HPP
#include "struc.hpp" #include "struc.hpp"
#include "processing.hpp"
#include <regex> #include <regex>
#include <string> #include <string>
std::string gen_minmap(strmap_t const& map, std::string const& prefix); void minify_var(_obj* in, std::regex const& exclude);
void read_minmap(std::string const& filepath, strmap_t* varmap, strmap_t* fctmap); void minify_fct(_obj* in, std::regex const& exclude);
bool r_replace_fct(_obj* in, strmap_t* fctmap);
bool r_replace_var(_obj* in, strmap_t* varmap);
strmap_t minify_var(_obj* in, std::regex const& exclude);
strmap_t minify_fct(_obj* in, std::regex const& exclude);
void delete_unused(_obj* in, std::regex const& var_exclude, std::regex const& fct_exclude); void delete_unused(_obj* in, std::regex const& var_exclude, std::regex const& fct_exclude);

View file

@ -11,7 +11,7 @@
#define SPACES " \t" #define SPACES " \t"
#define SEPARATORS " \t\n" #define SEPARATORS " \t\n"
#define ARG_END " \t\n;()&|<>" #define ARG_END " \t\n;#()&|<>"
#define VARNAME_END " \t\n;#()&|=\"'\\{}/-+" #define VARNAME_END " \t\n;#()&|=\"'\\{}/-+"
#define BLOCK_TOKEN_END " \t\n;#()&|=\"'\\" #define BLOCK_TOKEN_END " \t\n;#()&|=\"'\\"
#define BASH_BLOCK_END " \t\n;#()&|=\"'\\{}" #define BASH_BLOCK_END " \t\n;#()&|=\"'\\{}"
@ -32,7 +32,7 @@
#define ARG_OPTIMIZE_MANIP "$\\`}" #define ARG_OPTIMIZE_MANIP "$\\`}"
#define ARG_OPTIMIZE_DEFARR "$\\`)" #define ARG_OPTIMIZE_DEFARR "$\\`)"
#define ARG_OPTIMIZE_BASHTEST "$\\`] \t\n" #define ARG_OPTIMIZE_BASHTEST "$\\`] \t\n"
#define ARG_OPTIMIZE_ARG "$\\` \t\n;()&|<>\"'" #define ARG_OPTIMIZE_ARG "$\\` \t\n;#()&|<>\"'"
#define ARG_OPTIMIZE_ARRAY "$\\`\t\n&|}[]\"'" #define ARG_OPTIMIZE_ARRAY "$\\`\t\n&|}[]\"'"
#define ARG_OPTIMIZE_ALL "$\\` \t\n;#()&|<>}]\"'" #define ARG_OPTIMIZE_ALL "$\\` \t\n;#()&|<>}]\"'"
@ -97,32 +97,35 @@ inline uint32_t skip_unread_noline(parse_context const& ct) {
parse_context parse_heredocument(parse_context ctx); parse_context parse_heredocument(parse_context ctx);
// list // list
std::tuple<list_t*, parse_context, std::string> parse_list_until(parse_context ct, list_parse_options opts={}); // std::pair<list*, parse_context> parse_list_until(parse_context ct, char end_c, const char* expecting=NULL);
// std::pair<list*, parse_context> parse_list_until(parse_context ct, std::string const& end_word);
// std::tuple<list*, parse_context, std::string> parse_list_until(parse_context ct, std::vector<std::string> const& end_words, const char* expecting=NULL);
std::tuple<list*, parse_context, std::string> parse_list_until(parse_context ct, list_parse_options opts={});
// name // name
std::pair<variable_t*, parse_context> parse_var(parse_context ct, bool specialvars=true, bool array=false); std::pair<variable*, parse_context> parse_var(parse_context ct, bool specialvars=true, bool array=false);
// subarg parsers // subarg parsers
std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ct); std::pair<arithmetic*, parse_context> parse_arithmetic(parse_context ct);
std::pair<variable_t*, parse_context> parse_manipulation(parse_context ct); std::pair<variable*, parse_context> parse_manipulation(parse_context ct);
// arg parser // arg parser
std::pair<arg_t*, parse_context> parse_arg(parse_context ct, const char* end=ARG_END, const char* unexpected=ARGLIST_END, bool doquote=true, const char* optimize=ARG_OPTIMIZE_ARG); std::pair<arg*, parse_context> parse_arg(parse_context ct, const char* end=ARG_END, const char* unexpected=ARGLIST_END, bool doquote=true, const char* optimize=ARG_OPTIMIZE_ARG);
// redirect parser // redirect parser
std::pair<redirect_t*, parse_context> parse_redirect(parse_context ct); std::pair<redirect*, parse_context> parse_redirect(parse_context ct);
// arglist parser // arglist parser
std::pair<arglist_t*, parse_context> parse_arglist(parse_context ct, bool hard_error=false, std::vector<redirect_t*>* redirs=nullptr, bool stop_on_brace=false); std::pair<arglist*, parse_context> parse_arglist(parse_context ct, bool hard_error=false, std::vector<redirect*>* redirs=nullptr);
// block parsers // block parsers
std::pair<block_t*, parse_context> parse_block(parse_context ct); std::pair<block*, parse_context> parse_block(parse_context ct);
std::pair<cmd_t*, parse_context> parse_cmd(parse_context ct); std::pair<cmd*, parse_context> parse_cmd(parse_context ct);
std::pair<function_t*, parse_context> parse_function(parse_context ct, const char* after="()"); std::pair<function*, parse_context> parse_function(parse_context ct, const char* after="()");
std::pair<subshell_t*, parse_context> parse_subshell(parse_context ct); std::pair<subshell*, parse_context> parse_subshell(parse_context ct);
std::pair<brace_t*, parse_context> parse_brace(parse_context ct); std::pair<brace*, parse_context> parse_brace(parse_context ct);
std::pair<case_t*, parse_context> parse_case(parse_context ct); std::pair<case_block*, parse_context> parse_case(parse_context ct);
std::pair<if_t*, parse_context> parse_if(parse_context ct); std::pair<if_block*, parse_context> parse_if(parse_context ct);
std::pair<for_t*, parse_context> parse_for(parse_context ct); std::pair<for_block*, parse_context> parse_for(parse_context ct);
std::pair<while_t*, parse_context> parse_while(parse_context ct); std::pair<while_block*, parse_context> parse_while(parse_context ct);
// pipeline parser // pipeline parser
std::pair<pipeline_t*, parse_context> parse_pipeline(parse_context ct); std::pair<pipeline*, parse_context> parse_pipeline(parse_context ct);
// condlist parser // condlist parser
std::pair<condlist_t*, parse_context> parse_condlist(parse_context ct); std::pair<condlist*, parse_context> parse_condlist(parse_context ct);
#endif //PARSE_HPP #endif //PARSE_HPP

View file

@ -9,7 +9,7 @@
#include "struc.hpp" #include "struc.hpp"
// constants // constants
#define RESERVED_VARIABLES "HOME", "PATH", "SHELL", "PWD", "OPTIND", "OPTARG", "LC_.*", "LANG", "TERM", "RANDOM", "TMPDIR", "IFS" #define RESERVED_VARIABLES "HOME", "PATH", "SHELL", "PWD", "OPTIND", "OPTARG", "LC_.*", "LANG", "TERM", "RANDOM", "TMPDIR"
// types // types
typedef std::map<std::string,uint32_t> countmap_t; typedef std::map<std::string,uint32_t> countmap_t;
@ -60,7 +60,7 @@ std::regex fct_exclude_regex(std::string const& in);
// varnames // varnames
bool is_varname(std::string const& in); bool is_varname(std::string const& in);
std::string get_varname(std::string const& in); std::string get_varname(std::string const& in);
std::string get_varname(arg_t* in); std::string get_varname(arg* in);
// list objects // list objects
void list_map(countmap_t const& map); void list_map(countmap_t const& map);

View file

@ -19,58 +19,68 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
// recursive calls // recursive calls
switch(o->type) switch(o->type)
{ {
case _obj::variable : case _obj::_variable :
{ {
variable_t* t = dynamic_cast<variable_t*>(o); variable* t = dynamic_cast<variable*>(o);
recurse(fct, t->index, args...); recurse(fct, t->index, args...);
recurse(fct, t->manip, args...); recurse(fct, t->manip, args...);
break; break;
} }
case _obj::redirect : case _obj::_redirect :
{ {
redirect_t* t = dynamic_cast<redirect_t*>(o); redirect* t = dynamic_cast<redirect*>(o);
recurse(fct, t->target, args...); recurse(fct, t->target, args...);
recurse(fct, t->here_document, args...); recurse(fct, t->here_document, args...);
break; break;
} }
case _obj::arg : case _obj::_arg :
{ {
arg_t* t = dynamic_cast<arg_t*>(o); arg* t = dynamic_cast<arg*>(o);
for(auto it: t->sa) for(auto it: t->sa)
{
recurse(fct, it, args...); recurse(fct, it, args...);
}
break; break;
} }
case _obj::arglist : case _obj::_arglist :
{ {
arglist_t* t = dynamic_cast<arglist_t*>(o); arglist* t = dynamic_cast<arglist*>(o);
for(auto it: t->args) for(auto it: t->args)
{
recurse(fct, it, args...); recurse(fct, it, args...);
}
break; break;
} }
case _obj::pipeline : case _obj::_pipeline :
{ {
pipeline_t* t = dynamic_cast<pipeline_t*>(o); pipeline* t = dynamic_cast<pipeline*>(o);
for(auto it: t->cmds) for(auto it: t->cmds)
{
recurse(fct, it, args...); recurse(fct, it, args...);
}
break; break;
} }
case _obj::condlist : case _obj::_condlist :
{ {
condlist_t* t = dynamic_cast<condlist_t*>(o); condlist* t = dynamic_cast<condlist*>(o);
for(auto it: t->pls) for(auto it: t->pls)
{
recurse(fct, it, args...); recurse(fct, it, args...);
}
break; break;
} }
case _obj::list : case _obj::_list :
{ {
list_t* t = dynamic_cast<list_t*>(o); list* t = dynamic_cast<list*>(o);
for(auto it: t->cls) for(auto it: t->cls)
{
recurse(fct, it, args...); recurse(fct, it, args...);
}
break; break;
} }
case _obj::block_subshell : case _obj::block_subshell :
{ {
subshell_t* t = dynamic_cast<subshell_t*>(o); subshell* t = dynamic_cast<subshell*>(o);
recurse(fct, t->lst, args...); recurse(fct, t->lst, args...);
for(auto it: t->redirs) for(auto it: t->redirs)
@ -80,7 +90,7 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
case _obj::block_brace : case _obj::block_brace :
{ {
brace_t* t = dynamic_cast<brace_t*>(o); brace* t = dynamic_cast<brace*>(o);
recurse(fct, t->lst, args...); recurse(fct, t->lst, args...);
for(auto it: t->redirs) for(auto it: t->redirs)
@ -100,7 +110,7 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
case _obj::block_function : case _obj::block_function :
{ {
function_t* t = dynamic_cast<function_t*>(o); function* t = dynamic_cast<function*>(o);
recurse(fct, t->lst, args...); recurse(fct, t->lst, args...);
for(auto it: t->redirs) for(auto it: t->redirs)
@ -110,7 +120,7 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
case _obj::block_cmd : case _obj::block_cmd :
{ {
cmd_t* t = dynamic_cast<cmd_t*>(o); cmd* t = dynamic_cast<cmd*>(o);
recurse(fct, t->args, args...); recurse(fct, t->args, args...);
for(auto it: t->var_assigns) for(auto it: t->var_assigns)
{ {
@ -130,7 +140,7 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
case _obj::block_case : case _obj::block_case :
{ {
case_t* t = dynamic_cast<case_t*>(o); case_block* t = dynamic_cast<case_block*>(o);
// carg // carg
recurse(fct, t->carg, args...); recurse(fct, t->carg, args...);
// cases // cases
@ -150,7 +160,7 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
case _obj::block_if : case _obj::block_if :
{ {
if_t* t = dynamic_cast<if_t*>(o); if_block* t = dynamic_cast<if_block*>(o);
// ifs // ifs
for(auto sc: t->blocks) for(auto sc: t->blocks)
{ {
@ -169,7 +179,7 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
case _obj::block_for : case _obj::block_for :
{ {
for_t* t = dynamic_cast<for_t*>(o); for_block* t = dynamic_cast<for_block*>(o);
// variable // variable
recurse(fct, t->var, args...); recurse(fct, t->var, args...);
// iterations // iterations
@ -184,7 +194,7 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
case _obj::block_while : case _obj::block_while :
{ {
while_t* t = dynamic_cast<while_t*>(o); while_block* t = dynamic_cast<while_block*>(o);
// condition // condition
recurse(fct, t->cond, args...); recurse(fct, t->cond, args...);
// operations // operations
@ -197,50 +207,50 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
case _obj::subarg_variable : case _obj::subarg_variable :
{ {
subarg_variable_t* t = dynamic_cast<subarg_variable_t*>(o); variable_subarg* t = dynamic_cast<variable_subarg*>(o);
recurse(fct, t->var, args...); recurse(fct, t->var, args...);
break; break;
} }
case _obj::subarg_subshell : case _obj::subarg_subshell :
{ {
subarg_subshell_t* t = dynamic_cast<subarg_subshell_t*>(o); subshell_subarg* t = dynamic_cast<subshell_subarg*>(o);
recurse(fct, t->sbsh, args...); recurse(fct, t->sbsh, args...);
break; break;
} }
case _obj::subarg_procsub : case _obj::subarg_procsub :
{ {
subarg_procsub_t* t = dynamic_cast<subarg_procsub_t*>(o); procsub_subarg* t = dynamic_cast<procsub_subarg*>(o);
recurse(fct, t->sbsh, args...); recurse(fct, t->sbsh, args...);
break; break;
} }
case _obj::subarg_arithmetic : case _obj::subarg_arithmetic :
{ {
subarg_arithmetic_t* t = dynamic_cast<subarg_arithmetic_t*>(o); arithmetic_subarg* t = dynamic_cast<arithmetic_subarg*>(o);
recurse(fct, t->arith, args...); recurse(fct, t->arith, args...);
break; break;
} }
case _obj::arithmetic_variable : case _obj::arithmetic_variable :
{ {
arithmetic_variable_t* t = dynamic_cast<arithmetic_variable_t*>(o); variable_arithmetic* t = dynamic_cast<variable_arithmetic*>(o);
recurse(fct, t->var, args...); recurse(fct, t->var, args...);
break; break;
} }
case _obj::arithmetic_subshell : case _obj::arithmetic_subshell :
{ {
arithmetic_subshell_t* t = dynamic_cast<arithmetic_subshell_t*>(o); subshell_arithmetic* t = dynamic_cast<subshell_arithmetic*>(o);
recurse(fct, t->sbsh, args...); recurse(fct, t->sbsh, args...);
break; break;
} }
case _obj::arithmetic_operation : case _obj::arithmetic_operation :
{ {
arithmetic_operation_t* t = dynamic_cast<arithmetic_operation_t*>(o); operation_arithmetic* t = dynamic_cast<operation_arithmetic*>(o);
recurse(fct, t->val1, args...); recurse(fct, t->val1, args...);
recurse(fct, t->val2, args...); recurse(fct, t->val2, args...);
break; break;
} }
case _obj::arithmetic_parenthesis : case _obj::arithmetic_parenthesis :
{ {
arithmetic_parenthesis_t* t = dynamic_cast<arithmetic_parenthesis_t*>(o); parenthesis_arithmetic* t = dynamic_cast<parenthesis_arithmetic*>(o);
recurse(fct, t->val, args...); recurse(fct, t->val, args...);
break; break;
} }
@ -249,292 +259,5 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
} }
} }
// deep copy of object structure
template<class... Args>
_obj* obj_copy(_obj* o)
{
if(o == nullptr)
return nullptr;
// recursive calls
switch(o->type)
{
case _obj::variable :
{
variable_t* t = dynamic_cast<variable_t*>(o);
variable_t* ret = new variable_t(*t);
ret->index = dynamic_cast<arg_t*>(obj_copy(t->index));
ret->manip = dynamic_cast<arg_t*>(obj_copy(t->manip));
return ret;
}
case _obj::redirect :
{
redirect_t* t = dynamic_cast<redirect_t*>(o);
redirect_t* ret = new redirect_t(*t);
ret->target = dynamic_cast<arg_t*>(obj_copy(t->target));
ret->here_document = dynamic_cast<arg_t*>(obj_copy(t->here_document));
return ret;
}
case _obj::arg :
{
arg_t* t = dynamic_cast<arg_t*>(o);
arg_t* ret = new arg_t(*t);
for(uint32_t i=0; i<ret->sa.size(); i++)
ret->sa[i] = dynamic_cast<subarg_t*>(obj_copy(t->sa[i]));
return ret;
}
case _obj::arglist :
{
arglist_t* t = dynamic_cast<arglist_t*>(o);
arglist_t* ret = new arglist_t(*t);
for(uint32_t i=0; i<ret->args.size(); i++)
ret->args[i] = dynamic_cast<arg_t*>(obj_copy(t->args[i]));
return ret;
}
case _obj::pipeline :
{
pipeline_t* t = dynamic_cast<pipeline_t*>(o);
pipeline_t* ret = new pipeline_t(*t);
for(uint32_t i=0; i<ret->cmds.size(); i++)
ret->cmds[i] = dynamic_cast<block_t*>(obj_copy(t->cmds[i]));
return ret;
}
case _obj::condlist :
{
condlist_t* t = dynamic_cast<condlist_t*>(o);
condlist_t* ret = new condlist_t(*t);
for(uint32_t i=0; i<ret->pls.size(); i++)
ret->pls[i] = dynamic_cast<pipeline_t*>(obj_copy(t->pls[i]));
return ret;
}
case _obj::list :
{
list_t* t = dynamic_cast<list_t*>(o);
list_t* ret = new list_t(*t);
for(uint32_t i=0; i<ret->cls.size(); i++)
ret->cls[i] = dynamic_cast<condlist_t*>(obj_copy(t->cls[i]));
return ret;
}
case _obj::block_subshell :
{
subshell_t* t = dynamic_cast<subshell_t*>(o);
subshell_t* ret = new subshell_t(*t);
ret->lst = dynamic_cast<list_t*>(obj_copy(t->lst));
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::block_brace :
{
brace_t* t = dynamic_cast<brace_t*>(o);
brace_t* ret = new brace_t(*t);
ret->lst = dynamic_cast<list_t*>(obj_copy(t->lst));
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::block_main :
{
shmain* t = dynamic_cast<shmain*>(o);
shmain* ret = new shmain(*t);
ret->lst = dynamic_cast<list_t*>(obj_copy(t->lst));
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::block_function :
{
function_t* t = dynamic_cast<function_t*>(o);
function_t* ret = new function_t(*t);
ret->lst = dynamic_cast<list_t*>(obj_copy(t->lst));
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::block_cmd :
{
cmd_t* t = dynamic_cast<cmd_t*>(o);
cmd_t* ret = new cmd_t(*t);
ret->args = dynamic_cast<arglist_t*>(obj_copy(t->args));
for(uint32_t i=0; i<ret->var_assigns.size(); i++)
{
ret->var_assigns[i].first = dynamic_cast<variable_t*>(obj_copy(t->var_assigns[i].first));
ret->var_assigns[i].second = dynamic_cast<arg_t*>(obj_copy(t->var_assigns[i].second));
}
for(uint32_t i=0; i<ret->cmd_var_assigns.size(); i++)
{
ret->cmd_var_assigns[i].first = dynamic_cast<variable_t*>(obj_copy(t->cmd_var_assigns[i].first));
ret->cmd_var_assigns[i].second = dynamic_cast<arg_t*>(obj_copy(t->cmd_var_assigns[i].second));
}
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::block_case :
{
case_t* t = dynamic_cast<case_t*>(o);
case_t* ret = new case_t(*t);
// carg
ret->carg = dynamic_cast<arg_t*>(obj_copy(t->carg));
// cases
for(uint32_t i=0; i<ret->cases.size(); i++)
{
for(uint32_t j=0; j<ret->cases[i].first.size(); i++)
ret->cases[i].first[j] = dynamic_cast<arg_t*>(obj_copy(t->cases[i].first[j]));
ret->cases[i].second = dynamic_cast<list_t*>(obj_copy(t->cases[i].second));
}
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::block_if :
{
if_t* t = dynamic_cast<if_t*>(o);
if_t* ret = new if_t(*t);
// ifs
for(uint32_t i=0; i<ret->blocks.size(); i++)
{
// condition
ret->blocks[i].first = dynamic_cast<list_t*>(obj_copy(t->blocks[i].first));
// execution
ret->blocks[i].second = dynamic_cast<list_t*>(obj_copy(t->blocks[i].second));
}
// else
ret->else_lst = dynamic_cast<list_t*>(obj_copy(t->else_lst));
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::block_for :
{
for_t* t = dynamic_cast<for_t*>(o);
for_t* ret = new for_t(*t);
// variable
ret->var = dynamic_cast<variable_t*>(obj_copy(t->var));
// iterations
ret->iter = dynamic_cast<arglist_t*>(obj_copy(t->iter));
// for block
ret->ops = dynamic_cast<list_t*>(obj_copy(t->ops));
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::block_while :
{
while_t* t = dynamic_cast<while_t*>(o);
while_t* ret = new while_t(*t);
// condition
ret->cond = dynamic_cast<list_t*>(obj_copy(t->cond));
// for operations
ret->ops = dynamic_cast<list_t*>(obj_copy(t->ops));
for(uint32_t i=0; i<ret->redirs.size(); i++)
ret->redirs[i] = dynamic_cast<redirect_t*>(obj_copy(t->redirs[i]));
return ret;
}
case _obj::subarg_string :
{
subarg_string_t* t = dynamic_cast<subarg_string_t*>(o);
subarg_string_t* ret = new subarg_string_t(*t);
return ret;
}
case _obj::subarg_variable :
{
subarg_variable_t* t = dynamic_cast<subarg_variable_t*>(o);
subarg_variable_t* ret = new subarg_variable_t(*t);
ret->var = dynamic_cast<variable_t*>(obj_copy(t->var));
return ret;
}
case _obj::subarg_subshell :
{
subarg_subshell_t* t = dynamic_cast<subarg_subshell_t*>(o);
subarg_subshell_t* ret = new subarg_subshell_t(*t);
ret->sbsh = dynamic_cast<subshell_t*>(obj_copy(t->sbsh));
return ret;
}
case _obj::subarg_procsub :
{
subarg_procsub_t* t = dynamic_cast<subarg_procsub_t*>(o);
subarg_procsub_t* ret = new subarg_procsub_t(*t);
ret->sbsh = dynamic_cast<subshell_t*>(obj_copy(t->sbsh));
return ret;
}
case _obj::subarg_arithmetic :
{
subarg_arithmetic_t* t = dynamic_cast<subarg_arithmetic_t*>(o);
subarg_arithmetic_t* ret = new subarg_arithmetic_t(*t);
ret->arith = dynamic_cast<arithmetic_t*>(obj_copy(t->arith));
return ret;
}
case _obj::arithmetic_number :
{
arithmetic_number_t* t = dynamic_cast<arithmetic_number_t*>(o);
arithmetic_number_t* ret = new arithmetic_number_t(*t);
return ret;
}
case _obj::arithmetic_variable :
{
arithmetic_variable_t* t = dynamic_cast<arithmetic_variable_t*>(o);
arithmetic_variable_t* ret = new arithmetic_variable_t(*t);
ret->var = dynamic_cast<variable_t*>(obj_copy(t->var));
return ret;
}
case _obj::arithmetic_subshell :
{
arithmetic_subshell_t* t = dynamic_cast<arithmetic_subshell_t*>(o);
arithmetic_subshell_t* ret = new arithmetic_subshell_t(*t);
ret->sbsh = dynamic_cast<subshell_t*>(obj_copy(t->sbsh));
return ret;
}
case _obj::arithmetic_operation :
{
arithmetic_operation_t* t = dynamic_cast<arithmetic_operation_t*>(o);
arithmetic_operation_t* ret = new arithmetic_operation_t(*t);
ret->val1 = dynamic_cast<arithmetic_t*>(obj_copy(t->val1));
ret->val2 = dynamic_cast<arithmetic_t*>(obj_copy(t->val2));
return ret;
}
case _obj::arithmetic_parenthesis :
{
arithmetic_parenthesis_t* t = dynamic_cast<arithmetic_parenthesis_t*>(o);
arithmetic_parenthesis_t* ret = new arithmetic_parenthesis_t(*t);
ret->val = dynamic_cast<arithmetic_t*>(obj_copy(t->val));
return ret;
}
default: return nullptr; //dummy
}
}
#endif //RECURSIVE_HPP #endif //RECURSIVE_HPP

View file

@ -6,8 +6,8 @@
extern std::vector<std::string> included; extern std::vector<std::string> included;
std::vector<std::pair<std::string, std::string>> do_include_raw(condlist_t* cmd, parse_context ctx, std::string* ex_dir=nullptr); std::vector<std::pair<std::string, std::string>> do_include_raw(condlist* cmd, parse_context ctx, std::string* ex_dir=nullptr);
std::pair<std::string, std::string> do_resolve_raw(condlist_t* cmd, parse_context ctx, std::string* ex_dir=nullptr); std::pair<std::string, std::string> do_resolve_raw(condlist* cmd, parse_context ctx, std::string* ex_dir=nullptr);
bool add_include(std::string const& file); bool add_include(std::string const& file);

View file

@ -67,13 +67,13 @@ subarg: can be one of
#define AND_OP false #define AND_OP false
#define OR_OP true #define OR_OP true
class condlist_t; class condlist;
class block_t; class block;
class pipeline_t; class pipeline;
class arg_t; class arg;
class subarg_t; class subarg;
class cmd_t; class cmd;
class redirect_t; class redirect;
// structs // structs
@ -88,12 +88,12 @@ struct parse_context {
const char* here_doc=""; const char* here_doc="";
const char operator[](uint64_t a) { return data[a]; } const char operator[](uint64_t a) { return data[a]; }
bool has_errored=false; bool has_errored=false;
redirect_t* here_document=nullptr; redirect* here_document=nullptr;
char* here_delimitor=NULL; char* here_delimitor=NULL;
}; };
struct generate_context { struct generate_context {
arg_t* here_document=nullptr; arg* here_document=nullptr;
}; };
// exceptions // exceptions
@ -124,19 +124,24 @@ private:
// objects // objects
// type pack of condlist
typedef std::vector<arg*> arglist_t;
extern std::string g_origin;
// meta object type // meta object type
class _obj class _obj
{ {
public: public:
enum _objtype { enum _objtype {
subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_procsub, subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_procsub,
variable, _variable,
redirect, _redirect,
arg, _arg,
arglist, _arglist,
pipeline, _pipeline,
condlist, _condlist,
list, _list,
arithmetic_operation, arithmetic_number, arithmetic_variable, arithmetic_parenthesis, arithmetic_subshell, arithmetic_operation, arithmetic_number, arithmetic_variable, arithmetic_parenthesis, arithmetic_subshell,
block_subshell, block_brace, block_main, block_cmd, block_function, block_case, block_if, block_for, block_while }; block_subshell, block_brace, block_main, block_cmd, block_function, block_case, block_if, block_for, block_while };
_objtype type; _objtype type;
@ -146,44 +151,41 @@ public:
}; };
// meta arithmetic type // meta arithmetic type
class arithmetic_t : public _obj class arithmetic : public _obj
{ {
public: public:
virtual std::string generate(int ind)=0; virtual std::string generate(int ind)=0;
}; };
// meta subarg type // meta subarg type
class subarg_t : public _obj class subarg : public _obj
{ {
public: public:
virtual ~subarg_t() {;} virtual ~subarg() {;}
virtual std::string generate(int ind)=0; virtual std::string generate(int ind)=0;
bool quoted; bool quoted;
}; };
class arg_t : public _obj class arg : public _obj
{ {
public: public:
arg_t() { type=_obj::arg; forcequoted=false; } arg() { type=_obj::_arg; }
arg_t(std::string const& str, bool fquote=false) { type=_obj::arg; this->set(str); forcequoted=fquote; } arg(std::string const& str) { type=_obj::_arg; this->set(str);}
arg_t(subarg_t* in, bool fquote=false) { type=_obj::arg; sa.push_back(in); forcequoted=fquote; } arg(subarg* in) { type=_obj::_arg; sa.push_back(in); }
~arg_t() { for(auto it: sa) delete it; } ~arg() { for(auto it: sa) delete it; }
void set(std::string const& str); void set(std::string const& str);
void insert(uint32_t i, subarg_t* val); void insert(uint32_t i, subarg* val);
void insert(uint32_t i, arg_t const& a); void insert(uint32_t i, arg const& a);
void insert(uint32_t i, std::string const& in); void insert(uint32_t i, std::string const& in);
inline void add(subarg_t* in) { sa.push_back(in); } inline void add(subarg* in) { sa.push_back(in); }
void add(std::string const& in); void add(std::string const& in);
inline size_t size() { return sa.size(); } inline size_t size() { return sa.size(); }
std::vector<subarg_t*> sa; std::vector<subarg*> sa;
// is forcequoted: var assign
bool forcequoted;
bool is_string(); bool is_string();
// return if is a string and only one subarg // return if is a string and only one subarg
@ -199,61 +201,59 @@ public:
std::string generate(int ind); std::string generate(int ind);
}; };
class variable_t : public _obj class variable : public _obj
{ {
public: public:
variable_t(std::string const& in="", arg_t* i=nullptr, bool def=false, bool ismanip=false, arg_t* m=nullptr) { type=_obj::variable; varname=in; index=i; definition=def; is_manip=ismanip; precedence=false; manip=m; } variable(std::string const& in="", arg* i=nullptr, bool def=false, bool ismanip=false, arg* m=nullptr) { type=_obj::_variable; varname=in; index=i; definition=def; is_manip=ismanip; precedence=false; manip=m; }
~variable_t() { ~variable() {
if(index!=nullptr) delete index; if(index!=nullptr) delete index;
if(manip!=nullptr) delete manip; if(manip!=nullptr) delete manip;
} }
std::string varname; std::string varname;
bool definition; bool definition;
arg_t* index; // for bash specific arg* index; // for bash specific
bool is_manip; bool is_manip;
bool precedence; bool precedence;
arg_t* manip; arg* manip;
std::string generate(int ind); std::string generate(int ind);
}; };
// arglist // arglist
class arglist_t : public _obj class arglist : public _obj
{ {
public: public:
arglist_t() { type=_obj::arglist; } arglist() { type=_obj::_arglist; }
arglist_t(arg_t* in) { type=_obj::arglist; this->add(in); } arglist(arg* in) { type=_obj::_arglist; this->add(in); }
~arglist_t() { for( auto it: args ) delete it; } ~arglist() { for( auto it: args ) delete it; }
inline void add(arg_t* in) { args.push_back(in); } inline void add(arg* in) { args.push_back(in); }
std::vector<arg_t*> args; std::vector<arg*> args;
std::vector<std::string> strargs(uint32_t start); std::vector<std::string> strargs(uint32_t start);
// get first argument as string
std::string first_arg_string();
// potentially expands into more arguments than its size // potentially expands into more arguments than its size
bool can_expand(); bool can_expand();
void insert(uint32_t i, arg_t* val); void insert(uint32_t i, arg* val);
void insert(uint32_t i, arglist_t const& lst); void insert(uint32_t i, arglist const& lst);
inline size_t size() { return args.size(); } inline size_t size() { return args.size(); }
std::string generate(int ind); std::string generate(int ind);
}; };
class redirect_t : public _obj class redirect : public _obj
{ {
public: public:
redirect_t(std::string strop="") { type=_obj::redirect; op=strop; target=nullptr; here_document=nullptr; } redirect(std::string strop="") { type=_obj::_redirect; op=strop; target=nullptr; here_document=nullptr; }
redirect_t(arg_t* in) { type=_obj::redirect; target=in; here_document=nullptr; } redirect(arg* in) { type=_obj::_redirect; target=in; here_document=nullptr; }
redirect_t(std::string strop, arg_t* in) { type=_obj::redirect; op=strop; target=in; here_document=nullptr; } redirect(std::string strop, arg* in) { type=_obj::_redirect; op=strop; target=in; here_document=nullptr; }
redirect_t(std::string strop, arg_t* in, arg_t* doc) { type=_obj::redirect; op=strop; target=in; here_document=doc; } redirect(std::string strop, arg* in, arg* doc) { type=_obj::_redirect; op=strop; target=in; here_document=doc; }
~redirect_t() { ~redirect() {
if(target != nullptr) delete target; if(target != nullptr) delete target;
if(here_document != nullptr) delete here_document; if(here_document != nullptr) delete here_document;
} }
@ -261,21 +261,21 @@ public:
std::string generate(int ind); std::string generate(int ind);
std::string op; std::string op;
arg_t* target; arg* target;
arg_t* here_document; arg* here_document;
}; };
// Meta block // Meta block
class block_t : public _obj class block : public _obj
{ {
public: public:
block_t() { ; } block() { ; }
virtual ~block_t() { for(auto it: redirs) delete it; } virtual ~block() { for(auto it: redirs) delete it; }
// cmd // cmd
std::vector<redirect_t*> redirs; std::vector<redirect*> redirs;
// subshell: return the containing cmd, if it is a single command // subshell: return the containing cmd, if it is a single command
cmd_t* single_cmd(); cmd* single_cmd();
std::string generate_redirs(int ind, std::string const& _str, generate_context* ctx); std::string generate_redirs(int ind, std::string const& _str, generate_context* ctx);
@ -284,16 +284,15 @@ public:
// PL // PL
class pipeline_t : public _obj class pipeline : public _obj
{ {
public: public:
pipeline_t(block_t* bl=nullptr) { type=_obj::pipeline; if(bl!=nullptr) cmds.push_back(bl); negated=false; bash_time=false; } pipeline(block* bl=nullptr) { type=_obj::_pipeline; if(bl!=nullptr) cmds.push_back(bl); negated=false; }
~pipeline_t() { for(auto it: cmds) delete it; } ~pipeline() { for(auto it: cmds) delete it; }
inline void add(block_t* bl) { this->cmds.push_back(bl); } inline void add(block* bl) { this->cmds.push_back(bl); }
std::vector<block_t*> cmds; std::vector<block*> cmds;
bool negated; // negated return value (! at start) bool negated; // negated return value (! at start)
bool bash_time; // has bash time command
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); }; std::string generate(int ind) { return this->generate(ind, nullptr); };
@ -301,49 +300,49 @@ public:
// CL // CL
class condlist_t : public _obj class condlist : public _obj
{ {
public: public:
condlist_t() { type=_obj::condlist; parallel=false; } condlist() { type=_obj::_condlist; parallel=false; }
condlist_t(pipeline_t* pl) { type=_obj::condlist; parallel=false; this->add(pl); } condlist(pipeline* pl) { type=_obj::_condlist; parallel=false; this->add(pl); }
condlist_t(block_t* bl); condlist(block* bl);
~condlist_t() { for(auto it: pls) delete it; } ~condlist() { for(auto it: pls) delete it; }
bool parallel; // & at the end bool parallel; // & at the end
void add(pipeline_t* pl, bool or_op=false); void add(pipeline* pl, bool or_op=false);
// don't push_back here, use add() instead // don't push_back here, use add() instead
std::vector<pipeline_t*> pls; std::vector<pipeline*> pls;
std::vector<bool> or_ops; // size of 1 less than pls, defines separator between pipelines std::vector<bool> or_ops; // size of 1 less than pls, defines separator between pipelines
void prune_first_cmd(); void prune_first_cmd();
block_t* first_block(); block* first_block();
cmd_t* first_cmd(); cmd* first_cmd();
cmd_t* get_cmd(std::string const& cmdname); cmd* get_cmd(std::string const& cmdname);
void negate(); void negate();
std::string generate(int ind); std::string generate(int ind);
}; };
class list_t : public _obj class list : public _obj
{ {
public: public:
list_t() { type=_obj::list; } list() { type=_obj::_list; }
list_t(condlist_t* in) { type=_obj::list; this->add(in); } list(condlist* in) { type=_obj::_list; this->add(in); }
~list_t() { for(auto it: cls) delete it; } ~list() { for(auto it: cls) delete it; }
void clear() { for(auto it: cls) delete it; cls.resize(0); } void clear() { for(auto it: cls) delete it; cls.resize(0); }
std::vector<condlist_t*> cls; std::vector<condlist*> cls;
inline void add(condlist_t* in) { cls.push_back(in); } inline void add(condlist* in) { cls.push_back(in); }
condlist_t* last_cond() { return cls[cls.size()-1]; } condlist* last_cond() { return cls[cls.size()-1]; }
void insert(uint32_t i, condlist_t* val); void insert(uint32_t i, condlist* val);
void insert(uint32_t i, list_t const& lst); void insert(uint32_t i, list const& lst);
size_t size() { return cls.size(); } size_t size() { return cls.size(); }
@ -351,13 +350,22 @@ public:
std::string generate(int ind) { return this->generate(ind, true); } std::string generate(int ind) { return this->generate(ind, true); }
}; };
// class redir
// {
// public:
// enum redirtype { none, write, append, read, raw } ;
// redir(redirtype in=none) { type=in; }
// redirtype type;
// arg val;
// };
// block subtypes // // block subtypes //
class cmd_t : public block_t class cmd : public block
{ {
public: public:
cmd_t(arglist_t* in=nullptr) { type=_obj::block_cmd; args=in; is_cmdvar=false; } cmd(arglist* in=nullptr) { type=_obj::block_cmd; args=in; is_cmdvar=false; }
~cmd_t() { ~cmd() {
if(args!=nullptr) delete args; if(args!=nullptr) delete args;
for(auto it: var_assigns) { for(auto it: var_assigns) {
delete it.first; delete it.first;
@ -375,36 +383,36 @@ public:
size_t arglist_size(); size_t arglist_size();
void add(arg_t* in); void add(arg* in);
// preceding var assigns // preceding var assigns
std::vector<std::pair<variable_t*,arg_t*>> var_assigns; std::vector<std::pair<variable*,arg*>> var_assigns;
// is a cmdvar type // is a cmdvar type
bool is_cmdvar; bool is_cmdvar;
// var assigns on cmdvar // var assigns on cmdvar
std::vector<std::pair<variable_t*,arg_t*>> cmd_var_assigns; std::vector<std::pair<variable*,arg*>> cmd_var_assigns;
// check if cmd is this (ex: unset) // check if cmd is this (ex: unset)
bool is(std::string const& in); bool is(std::string const& in);
// for var assigns in special cmds (export, unset, read, local) // for var assigns in special cmds (export, unset, read, local)
bool is_argvar(); bool is_argvar();
std::vector<subarg_t*> subarg_vars(); std::vector<subarg*> subarg_vars();
// returns true if command performs env var changes // returns true if command performs env var changes
bool has_var_assign(); bool has_var_assign();
arglist_t* args; arglist* args;
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
}; };
class shmain : public block_t class shmain : public block
{ {
public: public:
shmain(list_t* in=nullptr) { type=_obj::block_main; if(in == nullptr) lst = new list_t; else lst=in; } shmain(list* in=nullptr) { type=_obj::block_main; lst=in; }
~shmain() { ~shmain() {
if(lst!=nullptr) delete lst; if(lst!=nullptr) delete lst;
} }
@ -413,66 +421,66 @@ public:
std::string filename; std::string filename;
std::string shebang; std::string shebang;
list_t* lst; list* lst;
std::string generate(bool print_shebang=true, int ind=0); std::string generate(bool print_shebang=true, int ind=0);
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
}; };
class subshell_t : public block_t class subshell : public block
{ {
public: public:
subshell_t(list_t* in=nullptr) { type=_obj::block_subshell; lst=in; } subshell(list* in=nullptr) { type=_obj::block_subshell; lst=in; }
subshell_t(block_t* in) { type=_obj::block_subshell; lst=new list_t(new condlist_t(in)); } subshell(block* in) { type=_obj::block_subshell; lst=new list(new condlist(in)); }
~subshell_t() { ~subshell() {
if(lst!=nullptr) delete lst; if(lst!=nullptr) delete lst;
} }
cmd_t* single_cmd(); cmd* single_cmd();
list_t* lst; list* lst;
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
}; };
class brace_t : public block_t class brace : public block
{ {
public: public:
brace_t(list_t* in=nullptr) { type=_obj::block_brace; lst=in; } brace(list* in=nullptr) { type=_obj::block_brace; lst=in; }
~brace_t() { ~brace() {
if(lst!=nullptr) delete lst; if(lst!=nullptr) delete lst;
} }
cmd_t* single_cmd(); cmd* single_cmd();
list_t* lst; list* lst;
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
}; };
class function_t : public block_t class function : public block
{ {
public: public:
function_t(list_t* in=nullptr) { type=_obj::block_function; lst=in; } function(list* in=nullptr) { type=_obj::block_function; lst=in; }
~function_t() { ~function() {
if(lst!=nullptr) delete lst; if(lst!=nullptr) delete lst;
} }
std::string name; std::string name;
list_t* lst; list* lst;
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
}; };
class case_t : public block_t class case_block : public block
{ {
public: public:
case_t(arg_t* in=nullptr) { type=_obj::block_case; carg=in; } case_block(arg* in=nullptr) { type=_obj::block_case; carg=in; }
~case_t() { ~case_block() {
if(carg!=nullptr) delete carg; if(carg!=nullptr) delete carg;
for( auto cit : cases ) for( auto cit : cases )
{ {
@ -482,18 +490,18 @@ public:
} }
} }
arg_t* carg; arg* carg;
std::vector< std::pair<std::vector<arg_t*>, list_t*> > cases; std::vector< std::pair<std::vector<arg*>, list*> > cases;
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
}; };
class if_t : public block_t class if_block : public block
{ {
public: public:
if_t() { type=_obj::block_if; else_lst=nullptr; } if_block() { type=_obj::block_if; else_lst=nullptr; }
~if_t() { ~if_block() {
for(auto ifb: blocks) for(auto ifb: blocks)
{ {
if(ifb.first!=nullptr) delete ifb.first; if(ifb.first!=nullptr) delete ifb.first;
@ -502,28 +510,28 @@ public:
if(else_lst!=nullptr) delete else_lst; if(else_lst!=nullptr) delete else_lst;
} }
std::vector< std::pair<list_t*,list_t*> > blocks; std::vector< std::pair<list*,list*> > blocks;
list_t* else_lst; list* else_lst;
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
}; };
class for_t : public block_t class for_block : public block
{ {
public: public:
for_t(variable_t* in=nullptr, arglist_t* args=nullptr, list_t* lst=nullptr, bool ii=false) { type=_obj::block_for; var=in; iter=args; ops=lst; in_val=ii; } for_block(variable* in=nullptr, arglist* args=nullptr, list* lst=nullptr, bool ii=false) { type=_obj::block_for; var=in; iter=args; ops=lst; in_val=ii; }
~for_t() { ~for_block() {
if(iter!=nullptr) delete iter; if(iter!=nullptr) delete iter;
if(ops!=nullptr) delete ops; if(ops!=nullptr) delete ops;
if(var!=nullptr) delete var; if(var!=nullptr) delete var;
} }
variable_t* var; variable* var;
arglist_t* iter; arglist* iter;
list_t* ops; list* ops;
bool in_val; bool in_val;
@ -531,19 +539,19 @@ public:
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
}; };
class while_t : public block_t class while_block : public block
{ {
public: public:
while_t(list_t* a=nullptr, list_t* b=nullptr) { type=_obj::block_while; cond=a; ops=b; } while_block(list* a=nullptr, list* b=nullptr) { type=_obj::block_while; cond=a; ops=b; }
~while_t() { ~while_block() {
if(cond!=nullptr) delete cond; if(cond!=nullptr) delete cond;
if(ops!=nullptr) delete ops; if(ops!=nullptr) delete ops;
} }
condlist_t* real_condition() { return cond->last_cond(); } condlist* real_condition() { return cond->last_cond(); }
list_t* cond; list* cond;
list_t* ops; list* ops;
std::string generate(int ind, generate_context* ctx); std::string generate(int ind, generate_context* ctx);
std::string generate(int ind) { return this->generate(ind, nullptr); } std::string generate(int ind) { return this->generate(ind, nullptr); }
@ -551,130 +559,129 @@ public:
// Subarg subtypes // // Subarg subtypes //
class subarg_string_t : public subarg_t class string_subarg : public subarg
{ {
public: public:
subarg_string_t(std::string const& in="") { type=_obj::subarg_string; val=in; } string_subarg(std::string const& in="") { type=_obj::subarg_string; val=in; }
~subarg_string_t() {;} ~string_subarg() {;}
std::string val; std::string val;
std::string generate(int ind) { return val; } std::string generate(int ind) { return val; }
}; };
class subarg_variable_t : public subarg_t class variable_subarg : public subarg
{ {
public: public:
subarg_variable_t(variable_t* in=nullptr, bool inq=false) { type=_obj::subarg_variable; var=in; quoted=inq; } variable_subarg(variable* in=nullptr, bool inq=false) { type=_obj::subarg_variable; var=in; quoted=inq; }
~subarg_variable_t() { ~variable_subarg() {
if(var!=nullptr) delete var; if(var!=nullptr) delete var;
} }
variable_t* var; variable* var;
std::string generate(int ind) { return "$" + var->generate(ind); } std::string generate(int ind) { return "$" + var->generate(ind); }
}; };
class subarg_arithmetic_t : public subarg_t class arithmetic_subarg : public subarg
{ {
public: public:
subarg_arithmetic_t(arithmetic_t* a=nullptr) { type=_obj::subarg_arithmetic; arith=a; } arithmetic_subarg(arithmetic* a=nullptr) { type=_obj::subarg_arithmetic; arith=a; }
~subarg_arithmetic_t() { ~arithmetic_subarg() {
if(arith!=nullptr) delete arith; if(arith!=nullptr) delete arith;
} }
arithmetic_t* arith; arithmetic* arith;
std::string generate(int ind); std::string generate(int ind);
}; };
class subarg_subshell_t : public subarg_t class subshell_subarg : public subarg
{ {
public: public:
subarg_subshell_t(subshell_t* in=nullptr, bool inq=false, bool is_backtick=false) { type=_obj::subarg_subshell; sbsh=in; quoted=inq; backtick=is_backtick; } subshell_subarg(subshell* in=nullptr, bool inq=false) { type=_obj::subarg_subshell; sbsh=in; quoted=inq; }
~subarg_subshell_t() { if(sbsh != nullptr) delete sbsh; } ~subshell_subarg() { if(sbsh != nullptr) delete sbsh; }
subshell_t* sbsh; subshell* sbsh;
bool backtick;
std::string generate(int ind); std::string generate(int ind);
}; };
class subarg_procsub_t : public subarg_t class procsub_subarg : public subarg
{ {
public: public:
subarg_procsub_t() { type=_obj::subarg_procsub; sbsh=nullptr; is_output=false; } procsub_subarg() { type=_obj::subarg_procsub; sbsh=nullptr; is_output=false; }
subarg_procsub_t(bool output, subshell_t* in) { type=_obj::subarg_procsub; sbsh=in; is_output=output; } procsub_subarg(bool output, subshell* in) { type=_obj::subarg_procsub; sbsh=in; is_output=output; }
~subarg_procsub_t() { if(sbsh!=nullptr) delete sbsh; } ~procsub_subarg() { if(sbsh!=nullptr) delete sbsh; }
bool is_output; bool is_output;
subshell_t* sbsh; subshell* sbsh;
std::string generate(int ind); std::string generate(int ind);
}; };
// Arithmetic subtypes // // Arithmetic subtypes //
class arithmetic_operation_t : public arithmetic_t class operation_arithmetic : public arithmetic
{ {
public: public:
arithmetic_operation_t(std::string op="", arithmetic_t* a=nullptr, arithmetic_t* b=nullptr, bool pre=false) { type=_obj::arithmetic_operation; oper=op; val1=a; val2=b; precedence=pre; } operation_arithmetic(std::string op="", arithmetic* a=nullptr, arithmetic* b=nullptr, bool pre=false) { type=_obj::arithmetic_operation; oper=op; val1=a; val2=b; precedence=pre; }
~arithmetic_operation_t() { ~operation_arithmetic() {
if(val1 != nullptr) delete val1; if(val1 != nullptr) delete val1;
if(val2 != nullptr) delete val2; if(val2 != nullptr) delete val2;
} }
std::string oper; std::string oper;
bool precedence; bool precedence;
arithmetic_t *val1, *val2; arithmetic *val1, *val2;
std::string generate(int ind); std::string generate(int ind);
}; };
class arithmetic_subshell_t : public arithmetic_t class subshell_arithmetic : public arithmetic
{ {
public: public:
arithmetic_subshell_t(subshell_t* a=nullptr) { type=_obj::arithmetic_subshell; sbsh=a; } subshell_arithmetic(subshell* a=nullptr) { type=_obj::arithmetic_subshell; sbsh=a; }
~arithmetic_subshell_t() { ~subshell_arithmetic() {
if(sbsh!=nullptr) delete sbsh; if(sbsh!=nullptr) delete sbsh;
} }
subshell_t* sbsh; subshell* sbsh;
std::string generate(int ind); std::string generate(int ind);
}; };
class arithmetic_parenthesis_t : public arithmetic_t class parenthesis_arithmetic : public arithmetic
{ {
public: public:
arithmetic_parenthesis_t(arithmetic_t* a=nullptr) { type=_obj::arithmetic_parenthesis; val=a; } parenthesis_arithmetic(arithmetic* a=nullptr) { type=_obj::arithmetic_parenthesis; val=a; }
~arithmetic_parenthesis_t() { ~parenthesis_arithmetic() {
if(val!=nullptr) delete val; if(val!=nullptr) delete val;
} }
arithmetic_t* val; arithmetic* val;
std::string generate(int ind); std::string generate(int ind);
}; };
class arithmetic_number_t : public arithmetic_t class number_arithmetic : public arithmetic
{ {
public: public:
arithmetic_number_t(std::string const& a) { type=_obj::arithmetic_number; val=a; } number_arithmetic(std::string const& a) { type=_obj::arithmetic_number; val=a; }
std::string val; std::string val;
std::string generate(int ind) { return val; } std::string generate(int ind) { return val; }
}; };
class arithmetic_variable_t : public arithmetic_t class variable_arithmetic : public arithmetic
{ {
public: public:
arithmetic_variable_t(variable_t* in=nullptr) { type=_obj::arithmetic_variable; var=in; } variable_arithmetic(variable* in=nullptr) { type=_obj::arithmetic_variable; var=in; }
~arithmetic_variable_t() { ~variable_arithmetic() {
if(var!=nullptr) delete var; if(var!=nullptr) delete var;
} }
variable_t* var; variable* var;
std::string generate(int ind); std::string generate(int ind);
}; };

View file

@ -4,43 +4,43 @@
#include "struc.hpp" #include "struc.hpp"
// makers // makers
arg_t* make_arg(std::string const& in); arg* make_arg(std::string const& in);
cmd_t* make_cmd(std::vector<const char*> const& args); cmd* make_cmd(std::vector<const char*> const& args);
cmd_t* make_cmd(std::vector<std::string> const& args); cmd* make_cmd(std::vector<std::string> const& args);
cmd_t* make_cmd(std::vector<arg_t*> const& args); cmd* make_cmd(std::vector<arg*> const& args);
cmd_t* make_cmd(std::string const& in); cmd* make_cmd(std::string const& in);
pipeline_t* make_pipeline(std::vector<block_t*> const& bls); pipeline* make_pipeline(std::vector<block*> const& bls);
pipeline_t* make_pipeline(std::string const& in); pipeline* make_pipeline(std::string const& in);
condlist_t* make_condlist(std::string const& in); condlist* make_condlist(std::string const& in);
list_t* make_list(std::string const& in); list* make_list(std::string const& in);
block_t* make_block(std::string const& in); block* make_block(std::string const& in);
// copy // copy
arg_t* copy(arg_t* in); arg* copy(arg* in);
variable_t* copy(variable_t* in); variable* copy(variable* in);
// testers // testers
bool arg_has_char(char c, arg_t* in); bool arg_has_char(char c, arg* in);
bool possibly_expands(arg_t* in); bool possibly_expands(arg* in);
bool possibly_expands(arglist_t* in); bool possibly_expands(arglist* in);
// modifiers // modifiers
void force_quotes(arg_t* in); void force_quotes(arg* in);
void add_quotes(arg_t* in); void add_quotes(arg* in);
cmd_t* make_printf(arg_t* in); cmd* make_printf(arg* in);
inline cmd_t* make_printf_variable(std::string const& name) { inline cmd* make_printf_variable(std::string const& name) {
return make_printf(new arg_t(new subarg_variable_t(new variable_t(name)))); return make_printf(new arg(new variable_subarg(new variable(name))));
} }
arithmetic_t* make_arithmetic(arg_t* a); arithmetic* make_arithmetic(arg* a);
arithmetic_t* make_arithmetic(arg_t* arg1, std::string op, arg_t* arg2); arithmetic* make_arithmetic(arg* arg1, std::string op, arg* arg2);
// operators // operators
inline bool operator==(arg_t 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

View file

@ -1,6 +1,6 @@
#ifndef VERSION_H #ifndef VERSION_H
#define VERSION_H #define VERSION_H
#define VERSION_STRING "v1.5" #define VERSION_STRING "v1.3.1"
#endif //VERSION_H #endif //VERSION_H

View file

@ -1,233 +0,0 @@
#!/bin/bash
bin=${1-./lxsh}
echo_red()
{
printf "\033[1;31m%s\033[0m\n" "$*"
exit 1
}
err=0
# $1 = file , $2 = extra print
# _LXSH_OPT : lxsh options
compile_test()
{
printf "%s%s: " "$1" "$2"
if errout=$($bin $_LXSH_OPT "$1" 2>&1 >/dev/null)
then
echo "Ok"
else
echo_red "Error"
echo "$errout"
return 1
fi
}
# $1 = runner , $2 = file , $3 = extra print , $4 = runtime for lxsh
# _LXSH_OPT : lxsh options
exec_test()
{
run=$1
lxshrun=${4-$run}
ret1=$($run "$2")
stat1=$?
ret2=$($bin $_LXSH_OPT "$2" | $lxshrun)
stat2=$?
printf "%s%s: " "$2" "$3"
if [ "$ret1" = "$ret2" ] && [ $stat1 -eq $stat2 ]
then echo "Ok"
else
echo_red "Error"
echo ">> original stat $stat1
$ret1
>> compiled stat $stat2
$ret2"
return 1
fi
}
size_test()
{
shebang=$(head -n1 "$1" | grep '^#!')
c1=$($bin --no-shebang -m "$1" | wc -c)
c2=$($bin -m "$1" | shfmt -mn | wc -c)
printf "%s%s: " "$1" "$2"
if [ $c1 -lt $c2 ]
then echo "Ok"
else
echo_red "Too big"
return 1
fi
}
# $1 = file , $2 = extra print , $3 = list , $@ = run options
list_test()
{
printf "%s%s: " "$1" "$2"
file=$1
varlist=$3
shift 3
diffout=$(diff <($bin "$file" "$@" | sort -k2) <(echo "$varlist" | sed '/^$/d' | sort -k2) )
if [ -z "$diffout" ] ; then
echo "Ok"
else
echo_red "Variable mismatch"
echo "$diffout"
return 1
fi
}
resolve="test/include.sh test/resolve.sh"
exec_exclude="test/prompt.sh $resolve"
echo "
============
| sh |
============
"
echo "== Parse =="
for I in test/*.sh
do
compile_test "$I" || err=$((err+1))
done
echo "== Exec =="
for I in $( echo test/*.sh $exec_exclude | tr -s ' \n' '\n' | sort | uniq -u )
do
exec_test sh "$I" || err=$((err+1))
_LXSH_OPT=-M exec_test sh "$I" " (minify)" || err=$((err+1))
done
echo "== Size =="
for I in test/*.sh
do
size_test "$I" || err=$((err+1))
done
echo "== Resolve =="
for I in $resolve
do
printf "%s: " "$I"
if errmsg=$($bin "$I" | sh 2>&1 >/dev/null) && [ -z "$errmsg" ]
then echo "Ok"
else
echo_red "Error"
echo ">> stderr
$errmsg"
err=$((err+1))
fi
done
varlist="
2 nul
2 ABCD
1 AYE
1 BAR
3 FOO
2 TATA
1 TITI
4 TOTO
1 TUTU
4 somevar
"
vardefs="
1 ABCD
1 BAR
2 FOO
1 TATA
1 TOTO
1 TUTU
1 nul
2 somevar
"
varcalls="
1 AYE
1 ABCD
1 FOO
1 TATA
1 TITI
3 TOTO
1 nul
2 somevar
"
varlist_used="
1 AYE
2 ABCD
3 FOO
2 TATA
1 TITI
4 TOTO
2 nul
4 somevar
"
echo "== Variables =="
{
list_test test/var.sh " (list)" "$varlist" --list-var || err=$((err+1))
list_test test/var.sh " (list-def)" "$vardefs" --list-var-def || err=$((err+1))
list_test test/var.sh " (list-call)" "$varcalls" --list-var-call || err=$((err+1))
list_test test/var.sh " (remove unused)" "$varlist_used" --remove-unused --list-var || err=$((err+1))
}
fctlist="
1 toto
1 tata
"
fctlist_used="
1 toto
"
cmdlist="
2 echo
1 toto
"
echo "== Functions =="
{
list_test test/fct.sh " (list-fct)" "$fctlist" --list-fct || err=$((err+1))
list_test test/fct.sh " (list-cmd)" "$cmdlist" --list-cmd || err=$((err+1))
list_test test/fct.sh " (remove unused)" "$fctlist_used" --remove-unused --list-fct || err=$((err+1))
}
echo "
============
| bash |
============
"
echo "== Parse =="
for I in test/*.bash
do
compile_test "$I" || err=$((err+1))
done
echo "== Exec =="
for I in test/*.bash
do
exec_test bash "$I" || err=$((err+1))
_LXSH_OPT=-m exec_test bash "$I" " (minify)" || err=$((err+1))
done
echo "== Size =="
for I in test/*.bash
do
size_test "$I" || err=$((err+1))
done
echo "== Debashify =="
for I in test/{debashify.bash,array.bash,echo.bash}
do
_LXSH_OPT=--debashify exec_test bash "$I" "" sh || err=$((err+1))
_LXSH_OPT="-m --debashify" exec_test bash "$I" " (minify)" sh || err=$((err+1))
done
exit $err

View file

@ -1,6 +1,6 @@
_lxsh_array_create() { _lxsh_array_create() {
printf "%s" "$1" printf "%s" "$1"
shift 1 2>/dev/null || return shift 1
for N ; do for N ; do
printf "\t%s" "$N" printf "\t%s" "$N"
done done

File diff suppressed because it is too large Load diff

View file

@ -18,9 +18,9 @@
#define PIPE_READ 0 #define PIPE_READ 0
#define PIPE_WRITE 1 #define PIPE_WRITE 1
std::vector<condlist_t*> do_include_exec(condlist_t* cmd, parse_context ctx, FILE* fd) std::vector<condlist*> do_include_exec(condlist* cmd, parse_context ctx, FILE* fd)
{ {
std::vector<condlist_t*> ret; std::vector<condlist*> ret;
std::string dir; std::string dir;
auto incs=do_include_raw(cmd, ctx, &dir); auto incs=do_include_raw(cmd, ctx, &dir);
@ -36,9 +36,9 @@ std::vector<condlist_t*> do_include_exec(condlist_t* cmd, parse_context ctx, FIL
} }
// if first is nullptr: is a string // if first is nullptr: is a string
std::vector<condlist_t*> do_resolve_exec(condlist_t* cmd, parse_context ctx, FILE* fd) std::vector<condlist*> do_resolve_exec(condlist* cmd, parse_context ctx, FILE* fd)
{ {
std::vector<condlist_t*> ret; std::vector<condlist*> ret;
std::pair<std::string,std::string> p; std::pair<std::string,std::string> p;
try try
@ -61,9 +61,9 @@ std::vector<condlist_t*> do_resolve_exec(condlist_t* cmd, parse_context ctx, FIL
// -- OBJECT CALLS -- // -- OBJECT CALLS --
bool resolve_condlist_exec(condlist_t* in, parse_context ctx, FILE* fd) bool resolve_condlist_exec(condlist* in, parse_context ctx, FILE* fd)
{ {
cmd_t* tc = in->first_cmd(); cmd* tc = in->first_cmd();
if(tc == nullptr) if(tc == nullptr)
return false; return false;
@ -83,7 +83,7 @@ bool resolve_condlist_exec(condlist_t* in, parse_context ctx, FILE* fd)
} }
bool resolve_exec(condlist_t* in, parse_context ctx, FILE* fd) bool resolve_exec(condlist* in, parse_context ctx, FILE* fd)
{ {
if(!resolve_condlist_exec(in, ctx, fd)) if(!resolve_condlist_exec(in, ctx, fd))
{ {
@ -143,7 +143,7 @@ void parse_exec(FILE* fd, parse_context ctx)
ctx.i=skip_unread(ctx); ctx.i=skip_unread(ctx);
debashify_params debash_params; debashify_params debash_params;
list_t* t_lst=new list_t; list* t_lst=new list;
if(t_lst == nullptr) if(t_lst == nullptr)
throw std::runtime_error("Alloc error"); throw std::runtime_error("Alloc error");
while(ctx.i<ctx.size) while(ctx.i<ctx.size)
@ -236,11 +236,6 @@ int exec_process(std::string const& runtime, std::vector<std::string> const& arg
if(mkfifo(fifopath.c_str(), 0700)<0) if(mkfifo(fifopath.c_str(), 0700)<0)
throw std::runtime_error("Cannot create fifo "+fifopath); throw std::runtime_error("Cannot create fifo "+fifopath);
pid_t pid=0;
FILE* ffd=0;
try
{
for(uint32_t i=0; i<strargs.size(); i++) for(uint32_t i=0; i<strargs.size(); i++)
runargs.push_back((char*) strargs[i].c_str()); runargs.push_back((char*) strargs[i].c_str());
runargs.push_back((char*) fifopath.c_str()); runargs.push_back((char*) fifopath.c_str());
@ -248,6 +243,10 @@ int exec_process(std::string const& runtime, std::vector<std::string> const& arg
runargs.push_back((char*) args[i].c_str()); runargs.push_back((char*) args[i].c_str());
runargs.push_back(NULL); runargs.push_back(NULL);
pid_t pid=0;
FILE* ffd=0;
try
{
pid = forkexec(runargs[0], runargs.data()); pid = forkexec(runargs[0], runargs.data());
ffd = fopen(fifopath.c_str(), "w"); ffd = fopen(fifopath.c_str(), "w");
if(options["debashify"]) if(options["debashify"])
@ -261,10 +260,10 @@ int exec_process(std::string const& runtime, std::vector<std::string> const& arg
} }
catch(std::runtime_error& e) catch(std::runtime_error& e)
{ {
if(pid != 0)
kill(pid, SIGINT);
fclose(ffd); fclose(ffd);
unlink(fifopath.c_str()); unlink(fifopath.c_str());
if(pid != 0)
kill(pid, SIGINT);
throw e; throw e;
} }

View file

@ -22,7 +22,7 @@ std::string indented(std::string const& in, uint32_t ind)
return in; return in;
} }
std::string arg_t::generate(int ind) std::string arg::generate(int ind)
{ {
std::string ret; std::string ret;
for(auto it: sa) for(auto it: sa)
@ -32,7 +32,7 @@ std::string arg_t::generate(int ind)
return ret; return ret;
} }
std::string arglist_t::generate(int ind) std::string arglist::generate(int ind)
{ {
std::string ret; std::string ret;
@ -47,7 +47,7 @@ std::string arglist_t::generate(int ind)
return ret; return ret;
} }
std::string pipeline_t::generate(int ind, generate_context* ctx) std::string pipeline::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
@ -56,10 +56,6 @@ std::string pipeline_t::generate(int ind, generate_context* ctx)
if(negated) if(negated)
ret += "! "; ret += "! ";
if(bash_time)
ret += "time ";
ret += cmds[0]->generate(ind, ctx); ret += cmds[0]->generate(ind, ctx);
for(uint32_t i=1 ; i<cmds.size() ; i++) for(uint32_t i=1 ; i<cmds.size() ; i++)
{ {
@ -70,7 +66,7 @@ std::string pipeline_t::generate(int ind, generate_context* ctx)
return ret; return ret;
} }
std::string condlist_t::generate(int ind) std::string condlist::generate(int ind)
{ {
std::string ret; std::string ret;
if(pls.size() <= 0) if(pls.size() <= 0)
@ -94,7 +90,6 @@ std::string condlist_t::generate(int ind)
ret += '&'; ret += '&';
ret += '\n'; ret += '\n';
ret += ctx.here_document->generate(0); ret += ctx.here_document->generate(0);
ret += '\n';
prev_is_heredoc=true; prev_is_heredoc=true;
} }
else if(parallel) else if(parallel)
@ -106,7 +101,7 @@ std::string condlist_t::generate(int ind)
return ret; return ret;
} }
std::string list_t::generate(int ind, bool first_indent) std::string list::generate(int ind, bool first_indent)
{ {
std::string ret; std::string ret;
if(cls.size() <= 0) if(cls.size() <= 0)
@ -131,22 +126,21 @@ std::string list_t::generate(int ind, bool first_indent)
return ret; return ret;
} }
std::string redirect_t::generate(int ind) std::string redirect::generate(int ind)
{ {
std::string ret=op; std::string ret=op;
if(target!=nullptr) if(target!=nullptr)
{ {
std::string targetret=target->generate(0); if(!opt_minify)
if(!(opt_minify && !is_in(targetret[0], "<>")))
ret += ' '; ret += ' ';
ret += targetret; ret += target->generate(0);
} }
return ret; return ret;
} }
// BLOCK // BLOCK
std::string block_t::generate_redirs(int ind, std::string const& _str, generate_context* ctx=nullptr) std::string block::generate_redirs(int ind, std::string const& _str, generate_context* ctx=nullptr)
{ {
std::string ret=" "; std::string ret=" ";
bool previous_isnt_num = _str.size()>0 && !is_num(_str[_str.size()-1]); bool previous_isnt_num = _str.size()>0 && !is_num(_str[_str.size()-1]);
@ -168,7 +162,7 @@ std::string block_t::generate_redirs(int ind, std::string const& _str, generate_
return ret; return ret;
} }
std::string if_t::generate(int ind, generate_context* ctx) std::string if_block::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
@ -202,7 +196,7 @@ std::string if_t::generate(int ind, generate_context* ctx)
return ret; return ret;
} }
std::string for_t::generate(int ind, generate_context* ctx) std::string for_block::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
@ -223,7 +217,7 @@ std::string for_t::generate(int ind, generate_context* ctx)
return ret; return ret;
} }
std::string while_t::generate(int ind, generate_context* ctx) std::string while_block::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
@ -243,7 +237,7 @@ std::string while_t::generate(int ind, generate_context* ctx)
return ret; return ret;
} }
std::string subshell_t::generate(int ind, generate_context* ctx) std::string subshell::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
// open subshell // open subshell
@ -276,7 +270,7 @@ std::string shmain::generate(bool print_shebang, int ind)
return ret; return ret;
} }
std::string brace_t::generate(int ind, generate_context* ctx) std::string brace::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
@ -288,7 +282,7 @@ std::string brace_t::generate(int ind, generate_context* ctx)
return ret; return ret;
} }
std::string function_t::generate(int ind, generate_context* ctx) std::string function::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
// function definition // function definition
@ -303,7 +297,7 @@ std::string function_t::generate(int ind, generate_context* ctx)
return ret; return ret;
} }
std::string case_t::generate(int ind, generate_context* ctx) std::string case_block::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
ret += "case " + carg->generate(ind) + " in\n"; ret += "case " + carg->generate(ind) + " in\n";
@ -344,7 +338,7 @@ std::string case_t::generate(int ind, generate_context* ctx)
return ret; return ret;
} }
std::string cmd_t::generate(int ind, generate_context* ctx) std::string cmd::generate(int ind, generate_context* ctx)
{ {
std::string ret; std::string ret;
@ -402,19 +396,12 @@ std::string cmd_t::generate(int ind, generate_context* ctx)
// SUBARG // SUBARG
std::string subarg_subshell_t::generate(int ind) std::string subshell_subarg::generate(int ind)
{ {
std::string r = sbsh->generate(ind); return '$' + sbsh->generate(ind);
if(backtick) {
r[0] = '`';
r[r.size()-1] = '`';
return r;
}
else
return '$' + r;
} }
std::string subarg_procsub_t::generate(int ind) std::string procsub_subarg::generate(int ind)
{ {
if(is_output) if(is_output)
return '>' + sbsh->generate(ind); return '>' + sbsh->generate(ind);
@ -422,7 +409,7 @@ std::string subarg_procsub_t::generate(int ind)
return '<' + sbsh->generate(ind); return '<' + sbsh->generate(ind);
} }
std::string subarg_arithmetic_t::generate(int ind) std::string arithmetic_subarg::generate(int ind)
{ {
std::string ret; std::string ret;
ret += "$(("; ret += "$((";
@ -435,7 +422,7 @@ std::string subarg_arithmetic_t::generate(int ind)
// ARITHMETIC // ARITHMETIC
std::string arithmetic_operation_t::generate(int ind) std::string operation_arithmetic::generate(int ind)
{ {
std::string ret; std::string ret;
if(precedence) if(precedence)
@ -455,7 +442,7 @@ std::string arithmetic_operation_t::generate(int ind)
return ret; return ret;
} }
std::string arithmetic_parenthesis_t::generate(int ind) std::string parenthesis_arithmetic::generate(int ind)
{ {
std::string ret; std::string ret;
ret += '('; ret += '(';
@ -466,12 +453,12 @@ std::string arithmetic_parenthesis_t::generate(int ind)
return ret; return ret;
} }
std::string arithmetic_subshell_t::generate(int ind) std::string subshell_arithmetic::generate(int ind)
{ {
return '$' + sbsh->generate(ind); return '$' + sbsh->generate(ind);
} }
std::string arithmetic_variable_t::generate(int ind) std::string variable_arithmetic::generate(int ind)
{ {
std::string ret=var->generate(ind); std::string ret=var->generate(ind);
if(is_num(ret[0]) || is_in(ret[0], SPECIAL_VARS) || var->is_manip) if(is_num(ret[0]) || is_in(ret[0], SPECIAL_VARS) || var->is_manip)
@ -479,7 +466,7 @@ std::string arithmetic_variable_t::generate(int ind)
return ret; return ret;
} }
std::string variable_t::generate(int ind) std::string variable::generate(int ind)
{ {
std::string ret; std::string ret;
if(is_manip) if(is_manip)

View file

@ -72,7 +72,7 @@ int main(int argc, char* argv[])
// parsing // parsing
sh = new shmain; sh = new shmain(new list);
bool is_exec = false; bool is_exec = false;
bool first_run = true; bool first_run = true;
@ -94,14 +94,7 @@ int main(int argc, char* argv[])
{ {
first_run=false; first_run=false;
// resolve shebang // resolve shebang
if(options["lxsh"]) if(options["bash"])
{
shebang_is_bin = true;
parse_bash = true;
binshebang = basename(shebang);
shebang = "#!/usr/bin/env lxsh";
}
else if(options["bash"])
{ {
parse_bash=true; parse_bash=true;
shebang = "#!/usr/bin/env bash"; shebang = "#!/usr/bin/env bash";
@ -138,6 +131,7 @@ int main(int argc, char* argv[])
} }
// parse // parse
g_origin=file;
if(!add_include(file)) if(!add_include(file))
continue; continue;
@ -146,8 +140,6 @@ int main(int argc, char* argv[])
ctx = make_context(filecontents, file, parse_bash); ctx = make_context(filecontents, file, parse_bash);
if(is_exec) if(is_exec)
{ {
delete sh;
sh = nullptr;
args.erase(args.begin()); args.erase(args.begin());
return exec_process(shebang.substr(2), args, ctx); return exec_process(shebang.substr(2), args, ctx);
} }
@ -203,38 +195,27 @@ int main(int argc, char* argv[])
// processing before output // processing before output
// minify // minify
strmap_t varmap, fctmap;
if(options['m']) if(options['m'])
{ {
opt_minify=true; opt_minify=true;
minify_generic(sh); minify_generic(sh);
} }
if(options['A']) { if(options["minify-var"] && options["minify-fct"]) {
read_minmap(options['A'].argument, &varmap, &fctmap);
recurse(r_replace_var, sh, &varmap);
recurse(r_replace_fct, sh, &fctmap);
}
else if(options["minify-var"] && options["minify-fct"]) {
// optimization: get everything in one go // optimization: get everything in one go
allmaps_get(sh, re_var_exclude, re_fct_exclude, regex_null); allmaps_get(sh, re_var_exclude, re_fct_exclude, regex_null);
varmap = minify_var( sh, re_var_exclude ); minify_var( sh, re_var_exclude );
fctmap = minify_fct( sh, re_fct_exclude ); minify_fct( sh, re_fct_exclude );
} }
else if(options["minify-var"]) { else if(options["minify-var"]) {
varmap = minify_var( sh, re_var_exclude ); minify_var( sh, re_var_exclude );
} }
else if(options["minify-fct"]) { else if(options["minify-fct"]) {
fctmap = minify_fct( sh, re_fct_exclude ); minify_fct( sh, re_fct_exclude );
} }
// other processing // other processing
if(options["unset-var"]) if(options["unset-var"])
add_unset_variables( sh, re_var_exclude ); add_unset_variables( sh, re_var_exclude );
if(options['P']) {
std::ofstream(options['P'].argument) << gen_minmap(varmap, "var") << gen_minmap(fctmap, "fct");
}
#ifdef DEBUG_MODE #ifdef DEBUG_MODE
if(options['J']) if(options['J'])
{ {

View file

@ -1,15 +1,14 @@
#include "minify.hpp" #include "minify.hpp"
#include <fstream>
#include "parse.hpp" #include "parse.hpp"
#include "recursive.hpp" #include "recursive.hpp"
#include "processing.hpp" #include "processing.hpp"
#include "util.hpp" #include "util.hpp"
std::vector<subarg_t*> cmd_t::subarg_vars() std::vector<subarg*> cmd::subarg_vars()
{ {
std::vector<subarg_t*> ret; std::vector<subarg*> ret;
if(args==nullptr || args->size()<=0) if(args==nullptr || args->size()<=0)
return ret; return ret;
@ -17,7 +16,7 @@ std::vector<subarg_t*> cmd_t::subarg_vars()
{ {
for(uint32_t i=1; i<args->size(); i++) for(uint32_t i=1; i<args->size(); i++)
{ {
arg_t* ta = args->args[i]; arg* ta = args->args[i];
if(ta->sa.size() < 1 || ta->sa[0]->type != _obj::subarg_string) if(ta->sa.size() < 1 || ta->sa[0]->type != _obj::subarg_string)
continue; continue;
if(ta->sa.size() >= 1 && is_varname(ta->sa[0]->generate(0))) if(ta->sa.size() >= 1 && is_varname(ta->sa[0]->generate(0)))
@ -35,19 +34,19 @@ bool r_replace_fct(_obj* in, strmap_t* fctmap)
switch(in->type) switch(in->type)
{ {
case _obj::block_function: { case _obj::block_function: {
function_t* t = dynamic_cast<function_t*>(in); function* t = dynamic_cast<function*>(in);
auto el=fctmap->find(t->name); auto el=fctmap->find(t->name);
if(el!=fctmap->end()) if(el!=fctmap->end())
t->name = el->second; t->name = el->second;
}; break; }; break;
case _obj::block_cmd: { case _obj::block_cmd: {
cmd_t* t = dynamic_cast<cmd_t*>(in); cmd* t = dynamic_cast<cmd*>(in);
std::string cmdname = t->arg_string(0); std::string cmdname = t->arg_string(0);
auto el=fctmap->find(cmdname); auto el=fctmap->find(cmdname);
if(el!=fctmap->end()) if(el!=fctmap->end())
{ {
delete t->args->args[0]; delete t->args->args[0];
t->args->args[0] = new arg_t(el->second); t->args->args[0] = new arg(el->second);
} }
}; break; }; break;
default: break; default: break;
@ -59,8 +58,8 @@ bool r_replace_var(_obj* in, strmap_t* varmap)
{ {
switch(in->type) switch(in->type)
{ {
case _obj::variable: { case _obj::_variable: {
variable_t* t = dynamic_cast<variable_t*>(in); variable* t = dynamic_cast<variable*>(in);
auto el=varmap->find(t->varname); auto el=varmap->find(t->varname);
if(el!=varmap->end()) if(el!=varmap->end())
t->varname = el->second; t->varname = el->second;
@ -70,20 +69,8 @@ bool r_replace_var(_obj* in, strmap_t* varmap)
return true; return true;
} }
const char* singlequote_escape_char=" \\\t!\"()|&*?~><#$"; const char* singlequote_escape_char=" \\\t!\"()|&*?~><#";
const char* doublequote_escape_char=" \t'|&\\*()?~><#$"; const char* doublequote_escape_char=" \t'|&\\*()?~><#";
uint32_t count_escape_char(std::string& in, uint32_t i, bool doublequote, std::string** estr, uint32_t* ei) {
if( ( doublequote && is_in(in[i], doublequote_escape_char) ) ||
( !doublequote && is_in(in[i], singlequote_escape_char) ) ) {
*estr = &in;
*ei = i;
return 1;
}
else if(in[i] == '\n') // \n: can't remove quotes
return 2;
return 0;
}
uint32_t count_escape_chars(std::string const& in, bool doublequote) uint32_t count_escape_chars(std::string const& in, bool doublequote)
{ {
uint32_t r=0; uint32_t r=0;
@ -118,203 +105,123 @@ bool is_this_quote(char c, bool is_doublequote)
return c == '\''; return c == '\'';
} }
bool is_varname(const char c) { void do_one_minify_quotes(string_subarg* in, bool prev_is_var, bool start_quoted)
return is_alphanum(c) || c == '_'; {
} std::string& val = in->val;
if(val.size() <= 1)
return;
if(start_quoted) // don't handle start quoted for now
return;
if(val[0] == '"' && prev_is_var && (is_alphanum(val[1]) || val[1] == '_') ) // removing quote would change varname: skip
return;
if(val[0] == '\'' && prev_is_var && (is_alphanum(val[1]) || val[1] == '_') ) // removing quote would change varname: skip
return;
void do_minify_quotes(arg_t* in) uint32_t i=0, j=0;
{ while( i < val.size() )
auto t = in->sa.begin();
// global loop
while(true)
{
uint32_t i=0;
// one iteration loop
while(true)
{ {
bool doublequote=false; bool doublequote=false;
bool prev_is_var=false;
bool end_is_var=false;
bool has_substitution=false;
std::string* strstart = nullptr;
uint32_t quotestart=0;
std::string* strend = nullptr;
uint32_t quoteend=0;
std::string* escapestr = nullptr;
uint32_t escapepos=0;
uint32_t ce=0;
// loop to find start of quote
while(true)
{
// reached end: quit
if(t == in->sa.end())
return;
while((*t)->type != _obj::subarg_string)
{
// previous is alphanum var: removing quote can change varname
if((*t)->type == _obj::subarg_variable) {
subarg_variable_t* vs = dynamic_cast<subarg_variable_t*>(*t);
if(vs->var != nullptr && !vs->var->is_manip && vs->var->varname.size()>0 && !(is_in(vs->var->varname[0], SPECIAL_VARS) || is_num(vs->var->varname[0]) ) )
prev_is_var = true;
}
else
prev_is_var = false;
t++;
// quit when reached end of arg
if(t == in->sa.end())
return;
i=0;
}
std::string& val = dynamic_cast<subarg_string_t*>(*t)->val;
// don't attempt if <= 2 chars
if(in->sa.size() == 1 && val.size() <= 2)
return;
while(i<val.size() && !( val[i] == '\'' || val[i] == '"') ) while(i<val.size() && !( val[i] == '\'' || val[i] == '"') )
{ {
if(val[i] == '\\') if(val[i] == '\\')
i++; i++;
i++; i++;
} }
// if found: break and go to next step if(i>=val.size()) // end before finding quote: exit
if(i<val.size()) { return;
if(val[i] == '"') if(val[i] == '"')
doublequote=true; doublequote=true;
strstart=&val;
quotestart=i; j=i;
i++; i++;
break;
}
else {
t++;
i=0;
}
} // end of quote start loop
// loop to end of quote
while(true)
{
// reached end: quit
if(t == in->sa.end())
return;
while((*t)->type != _obj::subarg_string)
{
// previous is alphanum var: removing quote can change varname
if((*t)->type == _obj::subarg_variable) {
subarg_variable_t* vs = dynamic_cast<subarg_variable_t*>(*t);
if(vs->var != nullptr && !vs->var->is_manip && vs->var->varname.size()>0 && !(is_in(vs->var->varname[0], SPECIAL_VARS) || is_num(vs->var->varname[0]) ) )
end_is_var = true;
}
else
end_is_var = false;
has_substitution=true;
t++;
// quit when reached end of arg
if(t == in->sa.end())
return;
i=0;
}
std::string& val = dynamic_cast<subarg_string_t*>(*t)->val;
if(doublequote) if(doublequote)
{ {
while(i<val.size() && val[i] != '"') while(i<val.size() && val[i] != '"')
{ {
if(val[i] == '\\') { if(val[i] == '\\')
ce += count_escape_char(val, i++, doublequote, &escapestr, &escapepos); i++;
} i++;
ce += count_escape_char(val, i++, doublequote, &escapestr, &escapepos);
}
if(i>=val.size()) { // end before finding quote: continue looping
t++;
i=0;
continue;
} }
if(i>=val.size()) // end before finding quote: exit
return;
} }
else else
{ {
while(i<val.size() && val[i] != '\'') while(i<val.size() && val[i] != '\'')
ce += count_escape_char(val, i++, doublequote, &escapestr, &escapepos);
if(i>=val.size()) { // end before finding quote: continue looping
t++;
i=0;
continue;
}
}
strend=&val;
quoteend=i;
break;
} // end of quote end loop
// has a substitution that can expand: don't dequote
if(!in->forcequoted && has_substitution) {
i++; i++;
continue; if(i>=val.size()) // end before finding quote: exit
} return;
// too many escapes: don't dequote
if(ce > 1) {
i++;
continue;
}
// removing quotes changes variable name: don't dequote
if( ( prev_is_var && quotestart == 0 && strstart->size()>1 && is_varname((*strstart)[1]) ) ||
( end_is_var && quoteend == 0 && strend->size()>1 && is_varname((*strend)[1])) ) {
i++;
continue;
}
// prev char is a $ would create variable names: don't dequote
if( quotestart >= 1 && (*strstart)[quotestart-1] == '$' && (!doublequote ||
( strstart->size()>2 && is_varname((*strstart)[quotestart+1])))
) {
i++;
continue;
}
// do dequote
strend->erase(quoteend, 1);
// needs one escape
if(ce == 1) {
escapestr->insert(escapepos, "\\");
}
strstart->erase(quotestart, 1);
} }
} uint32_t ce = count_escape_chars(val.substr(j+1, i-j-1), doublequote);
if(ce == 0)
}
void do_minify_dollar(subarg_string_t* in)
{ {
std::string& val = in->val; val.erase(val.begin()+i);
for(uint32_t i=0; i<val.size(); i++) { val.erase(val.begin()+j);
// skip singlequote strings
if(val[i] == '\'') {
i++;
while(val[i] != '\'')
i++;
} }
// has \$ else if(ce == 1) // only one char to escape: can save some space
if(i+1<val.size() && val[i] == '\\' && val[i+1] == '$') { {
// char after $ is a varname val.erase(val.begin()+i);
if(i+2<val.size() && (is_varname(val[i+2]) || is_in(val[i+2], SPECIAL_VARS) || val[i+2] == '{') ) val.erase(val.begin()+j);
continue; uint32_t k;
val.erase(i, 1); if(doublequote)
{
for(k=j; k<i-1; k++)
{
if( is_in(val[k], doublequote_escape_char) )
break;
} }
} }
else
{
for(k=j; k<i-1; k++)
{
if( is_in(val[k], singlequote_escape_char) )
break;
if( k+1<val.size() && val[k] == '$' && ( is_in(val[k+1], SPECIAL_VARS) || is_alpha(val[k+1]) || val[k+1] == '_' ) )
break;
}
}
if(k<i-1)
val.insert(val.begin()+k, '\\');
}
}
} }
bool r_minify_useless_quotes(_obj* in) bool r_minify_useless_quotes(_obj* in)
{ {
switch(in->type) switch(in->type)
{ {
case _obj::arg: { case _obj::_arg: {
arg_t* t = dynamic_cast<arg_t*>(in); arg* t = dynamic_cast<arg*>(in);
do_minify_quotes(t); for(uint32_t i=0; i<t->sa.size(); i++)
{
// iterate subargs
if(t->sa[i]->type == _obj::subarg_string)
{
// has to be a string
string_subarg* ss = dynamic_cast<string_subarg*>(t->sa[i]);
bool prev_is_var=false;
if(i>0 && t->sa[i-1]->type == _obj::subarg_variable)
{
// previous subarg is a direct variable (removing a quote could change variable name)
variable_subarg* vs = dynamic_cast<variable_subarg*>(t->sa[i-1]);
if(vs->var != nullptr && vs->var->is_manip == false && vs->var->varname.size()>0 && !(is_in(vs->var->varname[0], SPECIAL_VARS) || is_alpha(vs->var->varname[0]) ) )
prev_is_var=true;
}
if(t->sa.size()==1 && (ss->val=="\"\"" || ss->val=="''") ) // single argument as "" or '': don't minify
continue;
do_one_minify_quotes(ss, prev_is_var, i>0 && t->sa[i-1]->quoted);
}
//if()
}
}; break; }; break;
case _obj::subarg_string: { case _obj::_redirect: {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(in);
do_minify_dollar(t);
}; break;
case _obj::redirect: {
// for redirects: don't minify quotes on here documents // for redirects: don't minify quotes on here documents
redirect_t* t = dynamic_cast<redirect_t*>(in); redirect* t = dynamic_cast<redirect*>(in);
if(t->here_document != nullptr) if(t->here_document != nullptr)
{ {
recurse(r_minify_useless_quotes, t->target); recurse(r_minify_useless_quotes, t->target);
@ -394,7 +301,7 @@ strmap_t gen_minimal_map(countmap_t const& vars, set_t const& excluded)
// calls // calls
strmap_t minify_var(_obj* in, std::regex const& exclude) void minify_var(_obj* in, std::regex const& exclude)
{ {
// countmap_t vars; // countmap_t vars;
set_t excluded; set_t excluded;
@ -409,10 +316,9 @@ strmap_t minify_var(_obj* in, std::regex const& exclude)
// perform replace // perform replace
recurse(r_replace_var, in, &varmap); recurse(r_replace_var, in, &varmap);
require_rescan_var(); require_rescan_var();
return varmap;
} }
strmap_t minify_fct(_obj* in, std::regex const& exclude) void minify_fct(_obj* in, std::regex const& exclude)
{ {
// countmap_t fcts, cmdmap; // countmap_t fcts, cmdmap;
set_t excluded, unsets; set_t excluded, unsets;
@ -433,7 +339,6 @@ strmap_t minify_fct(_obj* in, std::regex const& exclude)
recurse(r_replace_fct, in, &fctmap); recurse(r_replace_fct, in, &fctmap);
require_rescan_fct(); require_rescan_fct();
require_rescan_cmd(); require_rescan_cmd();
return fctmap;
} }
bool delete_unused_fct(_obj* in, std::regex const& exclude) bool delete_unused_fct(_obj* in, std::regex const& exclude)
@ -517,14 +422,14 @@ bool r_minify_empty_manip(_obj* in)
{ {
switch(in->type) switch(in->type)
{ {
case _obj::arg: { case _obj::_arg: {
arg_t* t = dynamic_cast<arg_t*>(in); arg* t = dynamic_cast<arg*>(in);
for(uint32_t i=0; i<t->sa.size(); i++) for(uint32_t i=0; i<t->sa.size(); i++)
{ {
if(t->sa[i]->type == _obj::subarg_variable) if(t->sa[i]->type == _obj::subarg_variable)
{ {
// has to be a variable // has to be a variable
subarg_variable_t* ss = dynamic_cast<subarg_variable_t*>(t->sa[i]); variable_subarg* ss = dynamic_cast<variable_subarg*>(t->sa[i]);
if(ss->var->is_manip) if(ss->var->is_manip)
{ {
// if is a manip: possibility to skip it // if is a manip: possibility to skip it
@ -533,7 +438,7 @@ bool r_minify_empty_manip(_obj* in)
if(i+1<t->sa.size() && t->sa[i+1]->type == _obj::subarg_string) if(i+1<t->sa.size() && t->sa[i+1]->type == _obj::subarg_string)
{ {
// if next subarg is a string: check its first char // if next subarg is a string: check its first char
subarg_string_t* ss = dynamic_cast<subarg_string_t*>(t->sa[i+1]); string_subarg* ss = dynamic_cast<string_subarg*>(t->sa[i+1]);
char c = ss->val[0]; char c = ss->val[0];
// if its first would extend the var name: skip // if its first would extend the var name: skip
if(is_alphanum(c) || c == '_') if(is_alphanum(c) || c == '_')
@ -551,34 +456,28 @@ bool r_minify_empty_manip(_obj* in)
return true; return true;
} }
pipeline_t* do_one_minify_single_block(block_t* in) block* do_one_minify_single_block(block* in)
{ {
pipeline_t* ret=nullptr; block* ret=nullptr;
list_t* l=nullptr; list* l=nullptr;
if(in->type == _obj::block_brace) if(in->type == _obj::block_brace)
l = dynamic_cast<brace_t*>(in)->lst; l = dynamic_cast<brace*>(in)->lst;
else if(in->type == _obj::block_subshell) else if(in->type == _obj::block_subshell)
l = dynamic_cast<subshell_t*>(in)->lst; l = dynamic_cast<subshell*>(in)->lst;
if(l == nullptr) if(l == nullptr)
return nullptr; return nullptr;
// not a single pipeline: not applicable // not a single cmd/block: not applicable
if(l->cls.size() != 1 || l->cls[0]->pls.size() != 1) if(l->cls.size() != 1 || l->cls[0]->pls.size() != 1 || l->cls[0]->pls[0]->cmds.size() != 1)
return nullptr; return nullptr;
ret = l->cls[0]->pls[0]; ret = l->cls[0]->pls[0]->cmds[0];
// if is a subshell and has some env set: don't remove it // if is a subshell and has some env set: don't remove it
if(in->type == _obj::block_subshell && has_env_set(ret)) if(in->type == _obj::block_subshell && has_env_set(ret))
return nullptr; return nullptr;
// has a non-stdout/stdin redirect: not applicable
for(auto it: in->redirs) {
if(!is_in(it->op[0], "<>") )
return nullptr;
}
return ret; return ret;
} }
@ -586,47 +485,32 @@ bool r_minify_single_block(_obj* in)
{ {
switch(in->type) switch(in->type)
{ {
case _obj::pipeline: { case _obj::_pipeline: {
bool has_operated=false; bool has_operated=false;
do do
{ {
// loop operating on current // loop operating on current
// (if has operated, current object has changed) // (if has operated, current object has changed)
has_operated=false; has_operated=false;
pipeline_t* t = dynamic_cast<pipeline_t*>(in); pipeline* t = dynamic_cast<pipeline*>(in);
for(uint32_t i=0; i<t->cmds.size(); i++) for(uint32_t i=0; i<t->cmds.size(); i++)
{ {
pipeline_t* ret = do_one_minify_single_block(t->cmds[i]); block* ret = do_one_minify_single_block(t->cmds[i]);
if(ret != nullptr) { if(ret != nullptr) {
// concatenate redirects // concatenate redirects
block_t* firstb = ret->cmds[0]; for(uint32_t j=0; j<t->cmds[i]->redirs.size(); j++)
block_t* lastb = ret->cmds[ret->cmds.size()-1]; ret->redirs.insert(ret->redirs.begin()+j, t->cmds[i]->redirs[j]);
uint32_t j1=0, j2=0;
for(uint32_t j=0; j<t->cmds[i]->redirs.size(); j++) {
if(t->cmds[i]->redirs[j]->op[0] == '<') {
firstb->redirs.insert(firstb->redirs.begin()+j1, t->cmds[i]->redirs[j]);
j1++;
}
else {
lastb->redirs.insert(lastb->redirs.begin()+j2, t->cmds[i]->redirs[j]);
j2++;
}
}
// deindex // deindex
t->cmds[i]->redirs.resize(0); t->cmds[i]->redirs.resize(0);
if(t->cmds[i]->type == _obj::block_brace) if(t->cmds[i]->type == _obj::block_brace)
dynamic_cast<brace_t*>(t->cmds[i])->lst->cls[0]->pls[0] = nullptr; dynamic_cast<brace*>(t->cmds[i])->lst->cls[0]->pls[0]->cmds[0] = nullptr;
else if(t->cmds[i]->type == _obj::block_subshell) else if(t->cmds[i]->type == _obj::block_subshell)
dynamic_cast<subshell_t*>(t->cmds[i])->lst->cls[0]->pls[0] = nullptr; dynamic_cast<subshell*>(t->cmds[i])->lst->cls[0]->pls[0]->cmds[0] = nullptr;
// replace value // replace value
delete t->cmds[i]; delete t->cmds[i];
t->cmds.erase(t->cmds.begin()+i); t->cmds[i] = ret;
for(auto it: ret->cmds) {
t->cmds.insert(t->cmds.begin()+i, it);
i++;
}
has_operated=true; has_operated=true;
} }
@ -639,54 +523,11 @@ bool r_minify_single_block(_obj* in)
return true; return true;
} }
bool r_has_backtick(_obj* in, bool* r)
{
if(*r)
return false;
switch(in->type)
{
case _obj::subarg_subshell: {
subarg_subshell_t* t = dynamic_cast<subarg_subshell_t*>(in);
if(t->backtick) {
*r = true;
return false;
}
}; break;
case _obj::subarg_string: {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(in);
if(t->val.find('\\') != std::string::npos)
*r = true;
}; break;
default: break;
}
return true;
}
bool r_minify_backtick(_obj* in)
{
switch(in->type)
{
case _obj::subarg_subshell: {
subarg_subshell_t* t = dynamic_cast<subarg_subshell_t*>(in);
if(!t->backtick) {
bool has_backtick_child=false;
recurse(r_has_backtick, t->sbsh, &has_backtick_child);
if(has_backtick_child)
return false;
t->backtick = true;
}
return false;
}; break;
default: break;
}
return true;
}
// optimisation for processors that don't have recurse-cancellation
bool r_minify(_obj* in) bool r_minify(_obj* in)
{ {
r_minify_empty_manip(in); r_minify_empty_manip(in);
r_minify_single_block(in); r_minify_single_block(in);
r_minify_useless_quotes(in);
r_do_string_processor(in); r_do_string_processor(in);
return true; return true;
} }
@ -694,34 +535,4 @@ bool r_minify(_obj* in)
void minify_generic(_obj* in) void minify_generic(_obj* in)
{ {
recurse(r_minify, in); recurse(r_minify, in);
recurse(r_minify_backtick, in);
recurse(r_minify_useless_quotes, in);
}
std::string gen_minmap(strmap_t const& map, std::string const& prefix)
{
std::string ret;
for(auto it: map) {
ret += strf("%s %s %s\n", prefix.c_str(), it.second.c_str(), it.first.c_str());
}
return ret;
}
void read_minmap(std::string const& filepath, strmap_t* varmap, strmap_t* fctmap)
{
std::ifstream file(filepath);
std::string ln;
while(std::getline(file, ln)) {
size_t s1, s2, s3;
s1 = ln.find(' ');
s2 = ln.find(' ', s1+1);
s3 = ln.find(' ', s2+1);
std::string type = ln.substr(0, s1);
std::string from = ln.substr(s1+1, s2-s1-1);
std::string to = ln.substr(s2+1, s3-s2-1);
if(type == "var")
varmap->insert(std::make_pair(from, to));
else if(type == "fct")
fctmap->insert(std::make_pair(from, to));
}
} }

View file

@ -20,7 +20,6 @@ ztd::option_set options( {
ztd::option('c', "stdout", false, "Output result script to stdout"), ztd::option('c', "stdout", false, "Output result script to stdout"),
ztd::option('e', "exec", false, "Directly execute script"), ztd::option('e', "exec", false, "Directly execute script"),
ztd::option("no-shebang", false, "Don't output shebang"), ztd::option("no-shebang", false, "Don't output shebang"),
ztd::option('P', "map", true , "Output var and fct minify map to given file", "file"),
#ifdef DEBUG_MODE #ifdef DEBUG_MODE
ztd::option("\r [Debugging]"), ztd::option("\r [Debugging]"),
ztd::option('J', "json", false, "Output the json structure"), ztd::option('J', "json", false, "Output the json structure"),
@ -28,13 +27,11 @@ ztd::option_set options( {
ztd::option("\r [Processing]"), ztd::option("\r [Processing]"),
ztd::option('m', "minify", false, "Minify code without changing functionality"), ztd::option('m', "minify", false, "Minify code without changing functionality"),
ztd::option('M', "minify-full", false, "Enable all minifying features: -m --minify-var --minify-fct --remove-unused"), ztd::option('M', "minify-full", false, "Enable all minifying features: -m --minify-var --minify-fct --remove-unused"),
ztd::option('A', "apply-map", true , "Apply var/fct minify map from given file", "file"),
ztd::option('C', "no-cd", false, "Don't cd when doing %include and %resolve"), ztd::option('C', "no-cd", false, "Don't cd when doing %include and %resolve"),
ztd::option('I', "no-include", false, "Don't resolve %include commands"), ztd::option('I', "no-include", false, "Don't resolve %include commands"),
ztd::option('R', "no-resolve", false, "Don't resolve %resolve commands"), ztd::option('R', "no-resolve", false, "Don't resolve %resolve commands"),
ztd::option("no-extend", false, "Don't add lxsh extension functions"), ztd::option("no-extend", false, "Don't add lxsh extension functions"),
ztd::option("bash", false, "Force bash parsing"), ztd::option("bash", false, "Force bash parsing"),
ztd::option("lxsh", false, "Force lxsh parsing"),
ztd::option("debashify", false, "Attempt to turn a bash-specific script into a POSIX shell script"), ztd::option("debashify", false, "Attempt to turn a bash-specific script into a POSIX shell script"),
ztd::option("remove-unused", false, "Remove unused functions and variables"), ztd::option("remove-unused", false, "Remove unused functions and variables"),
ztd::option("list-cmd", false, "List all commands invoked in the script"), ztd::option("list-cmd", false, "List all commands invoked in the script"),
@ -76,34 +73,26 @@ void get_opts()
options["minify-fct"].activated=true; options["minify-fct"].activated=true;
options["remove-unused"].activated=true; options["remove-unused"].activated=true;
} }
if(options['o'].argument == "-")
options['o'].argument = "/dev/stdout";
if(options['P'].argument == "-")
options['P'].argument = "/dev/stdout";
if(options['A'].argument == "-")
options['A'].argument = "/dev/stdin";
if(
options['A'] && ( options['P'] || options["minify-var"] || options["minify-fct"] )
) {
printf("Incompatible options\n");
exit(ERR_OPT);
}
} }
ztd::option_set create_include_opts() ztd::option_set create_include_opts()
{ {
return std::vector<ztd::option>({ ztd::option_set opts;
opts.add(
ztd::option('C', false, "Don't cd to folder the file is in"), ztd::option('C', false, "Don't cd to folder the file is in"),
ztd::option('f', false, "Force include even if already included. Don't count as included") ztd::option('f', false, "Force include even if already included. Don't count as included")
}); );
return opts;
} }
ztd::option_set create_resolve_opts() ztd::option_set create_resolve_opts()
{ {
return std::vector<ztd::option>({ ztd::option_set opts;
opts.add(
ztd::option('C', false, "Don't cd to folder this file is in"), ztd::option('C', false, "Don't cd to folder this file is in"),
ztd::option('f', false, "Ignore non-zero return values") ztd::option('f', false, "Ignore non-zero return values")
}); );
return opts;
} }
void print_help(const char* arg0) void print_help(const char* arg0)
@ -136,7 +125,7 @@ void print_resolve_help()
printf("Execute shell command and substitute output, from folder of current file\n"); printf("Execute shell command and substitute output, from folder of current file\n");
printf(" - Default behaviour is to parse contents as shell code\n"); printf(" - Default behaviour is to parse contents as shell code\n");
printf(" - Fails if return value is not 0. Can be ignored with -f\n"); printf(" - Fails if return value is not 0. Can be ignored with -f\n");
printf(" - `%%resolve` inside substitutions replaces the substitution and puts raw response\n"); printf(" - `%%include` inside substitutions replaces the substitution and puts raw response\n");
printf("\n"); printf("\n");
ztd::option_set opts=create_resolve_opts(); ztd::option_set opts=create_resolve_opts();

View file

@ -18,7 +18,7 @@ const std::set<std::string> posix_cmdvar = { "export", "unset", "local", "read",
const std::set<std::string> bash_cmdvar = { "readonly", "declare", "typeset" }; const std::set<std::string> bash_cmdvar = { "readonly", "declare", "typeset" };
const std::set<std::string> arithmetic_precedence_operators = { "!", "~", "+", "-" }; const std::set<std::string> arithmetic_precedence_operators = { "!", "~", "+", "-" };
const std::set<std::string> arithmetic_operators = { "+", "-", "*", "/", "%", "+=", "-=", "*=", "/=", "=", "==", "!=", "&", "|", "^", "<<", ">>", "&&", "||" }; const std::set<std::string> arithmetic_operators = { "+", "-", "*", "/", "+=", "-=", "*=", "/=", "=", "==", "!=", "&", "|", "^", "<<", ">>", "&&", "||" };
const std::set<std::string> all_reserved_words = { "if", "then", "else", "fi", "case", "esac", "for", "while", "do", "done", "{", "}" }; const std::set<std::string> all_reserved_words = { "if", "then", "else", "fi", "case", "esac", "for", "while", "do", "done", "{", "}" };
const std::set<std::string> out_reserved_words = { "then", "else", "fi", "esac", "do", "done", "}" }; const std::set<std::string> out_reserved_words = { "then", "else", "fi", "esac", "do", "done", "}" };
@ -102,10 +102,12 @@ parse_context make_context(std::string const& in, std::string const& filename, b
} }
parse_context make_context(parse_context ctx, std::string const& in, std::string const& filename, bool bash) parse_context make_context(parse_context ctx, std::string const& in, std::string const& filename, bool bash)
{
if(in != "")
{ {
ctx.data = in.c_str(); ctx.data = in.c_str();
ctx.size = in.size(); ctx.size = in.size();
}
if(filename != "") if(filename != "")
ctx.filename = filename.c_str(); ctx.filename = filename.c_str();
if(bash) if(bash)
@ -205,9 +207,9 @@ std::pair<std::string,uint32_t> get_word(parse_context ctx, const char* end_set)
// parse fcts // parse fcts
std::pair<variable_t*, parse_context> parse_var(parse_context ctx, bool specialvars, bool array) std::pair<variable*, parse_context> parse_var(parse_context ctx, bool specialvars, bool array)
{ {
variable_t* ret=nullptr; variable* ret=nullptr;
std::string varname; std::string varname;
uint32_t start=ctx.i; uint32_t start=ctx.i;
@ -225,7 +227,7 @@ std::pair<variable_t*, parse_context> parse_var(parse_context ctx, bool specialv
} }
if(varname != "") if(varname != "")
{ {
ret = new variable_t(varname); ret = new variable(varname);
if(ctx.bash && array && ctx[ctx.i]=='[') if(ctx.bash && array && ctx[ctx.i]=='[')
{ {
ctx.i++; ctx.i++;
@ -262,9 +264,9 @@ std::pair<std::string, uint32_t> get_operator(parse_context ctx)
// parse an arithmetic // parse an arithmetic
// ends at )) // ends at ))
// temporary, to improve // temporary, to improve
std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ctx) std::pair<arithmetic*, parse_context> parse_arithmetic(parse_context ctx)
{ {
arithmetic_t* ret = nullptr; arithmetic* ret = nullptr;
ctx.i = skip_chars(ctx, SEPARATORS); ctx.i = skip_chars(ctx, SEPARATORS);
if(ctx.i>ctx.size || ctx[ctx.i] == ')') if(ctx.i>ctx.size || ctx[ctx.i] == ')')
@ -278,12 +280,12 @@ std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ctx)
{ {
ctx.i = po.second; ctx.i = po.second;
auto pa = parse_arithmetic(ctx); auto pa = parse_arithmetic(ctx);
ret = new arithmetic_operation_t(po.first, pa.first, nullptr, true); ret = new operation_arithmetic(po.first, pa.first, nullptr, true);
ctx=pa.second; ctx=pa.second;
} }
else else
{ {
arithmetic_variable_t* ttvar=nullptr; // for categorizing definitions variable_arithmetic* ttvar=nullptr; // for categorizing definitions
if(ctx[ctx.i]=='-' || is_num(ctx[ctx.i])) if(ctx[ctx.i]=='-' || is_num(ctx[ctx.i]))
{ {
uint32_t j=ctx.i; uint32_t j=ctx.i;
@ -291,40 +293,27 @@ std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ctx)
ctx.i++; ctx.i++;
while(is_num(ctx[ctx.i])) while(is_num(ctx[ctx.i]))
ctx.i++; ctx.i++;
ret = new arithmetic_number_t( std::string(ctx.data+j, ctx.i-j) ); ret = new number_arithmetic( std::string(ctx.data+j, ctx.i-j) );
}
else if(word_eq("$((", ctx)) // arithmetics in arithmetics: equivalent to ()
{
ctx.i += 3;
auto pa = parse_arithmetic(ctx);
ret = new arithmetic_parenthesis_t(pa.first);
ctx = pa.second;
ctx.i++;
if(ctx.i >= ctx.size || ctx[ctx.i] != ')') {
parse_error( "Unexpected ')', Expecting '))'", ctx );
return std::make_pair(ret, ctx);
}
ctx.i++;
} }
else if(word_eq("$(", ctx)) else if(word_eq("$(", ctx))
{ {
ctx.i+=2; ctx.i+=2;
auto ps = parse_subshell(ctx); auto ps = parse_subshell(ctx);
ret = new arithmetic_subshell_t(ps.first); ret = new subshell_arithmetic(ps.first);
ctx=ps.second; ctx=ps.second;
} }
else if(word_eq("${", ctx)) else if(word_eq("${", ctx))
{ {
ctx.i+=2; ctx.i+=2;
auto pm = parse_manipulation(ctx); auto pm = parse_manipulation(ctx);
ret = new arithmetic_variable_t(pm.first); ret = new variable_arithmetic(pm.first);
ctx=pm.second; ctx=pm.second;
} }
else if(ctx[ctx.i] == '(') else if(ctx[ctx.i] == '(')
{ {
ctx.i++; ctx.i++;
auto pa = parse_arithmetic(ctx); auto pa = parse_arithmetic(ctx);
ret = new arithmetic_parenthesis_t(pa.first); ret = pa.first;
ctx = pa.second; ctx = pa.second;
ctx.i++; ctx.i++;
} }
@ -337,7 +326,7 @@ std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ctx)
ctx.i++; ctx.i++;
} }
auto pp = parse_var(ctx, specialvars, true); auto pp = parse_var(ctx, specialvars, true);
ttvar = new arithmetic_variable_t(pp.first); ttvar = new variable_arithmetic(pp.first);
ret = ttvar; ret = ttvar;
ctx=pp.second; ctx=pp.second;
} }
@ -350,12 +339,12 @@ std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ctx)
{ {
parse_error( "Unknown arithmetic operator: "+po.first, ctx); parse_error( "Unknown arithmetic operator: "+po.first, ctx);
} }
arithmetic_t* val1 = ret; arithmetic* val1 = ret;
ctx.i=po.second; ctx.i=po.second;
auto pa = parse_arithmetic(ctx); auto pa = parse_arithmetic(ctx);
arithmetic_t* val2 = pa.first; arithmetic* val2 = pa.first;
ctx = pa.second; ctx = pa.second;
ret = new arithmetic_operation_t(po.first, val1, val2); ret = new operation_arithmetic(po.first, val1, val2);
ctx.i = skip_chars(ctx, SEPARATORS); ctx.i = skip_chars(ctx, SEPARATORS);
} }
@ -377,10 +366,10 @@ std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ctx)
return std::make_pair(ret, ctx); return std::make_pair(ret, ctx);
} }
std::pair<variable_t*, parse_context> parse_manipulation(parse_context ctx) std::pair<variable*, parse_context> parse_manipulation(parse_context ctx)
{ {
variable_t* ret = nullptr; variable* ret = nullptr;
arg_t* precede = nullptr; arg* precede = nullptr;
uint32_t start=ctx.i; uint32_t start=ctx.i;
@ -393,7 +382,7 @@ std::pair<variable_t*, parse_context> parse_manipulation(parse_context ctx)
} }
std::string t; std::string t;
t+=ctx[ctx.i]; t+=ctx[ctx.i];
precede = new arg_t( t ); precede = new arg( t );
ctx.i++; ctx.i++;
} }
@ -429,10 +418,8 @@ std::pair<variable_t*, parse_context> parse_manipulation(parse_context ctx)
return std::make_pair(ret, ctx); return std::make_pair(ret, ctx);
} }
inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t& j, bool is_quoted) inline parse_context do_one_subarg_step(arg* ret, parse_context ctx, uint32_t& j, bool is_quoted)
{ {
if( ctx.i >= ctx.size)
return ctx;
if( ctx[ctx.i] == '`' ) if( ctx[ctx.i] == '`' )
{ {
// add previous subarg // add previous subarg
@ -453,12 +440,10 @@ inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t&
} }
// get subshell // get subshell
parse_context newct = ctx; parse_context newct = ctx;
newct.size=k; ctx.size=k;
auto r=parse_list_until(newct); auto r=parse_list_until(newct);
ret->add(new subarg_subshell_t(new subshell_t(std::get<0>(r)), is_quoted, true)); ret->add(new subshell_subarg(new subshell(std::get<0>(r)), is_quoted));
uint64_t tsize=ctx.size;
ctx = std::get<1>(r); ctx = std::get<1>(r);
ctx.size = tsize;
ctx.i++; ctx.i++;
j = ctx.i; j = ctx.i;
} }
@ -470,7 +455,7 @@ inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t&
// get arithmetic // get arithmetic
ctx.i+=3; ctx.i+=3;
auto r=parse_arithmetic(ctx); auto r=parse_arithmetic(ctx);
subarg_arithmetic_t* tt = new subarg_arithmetic_t(r.first); arithmetic_subarg* tt = new arithmetic_subarg(r.first);
tt->quoted=is_quoted; tt->quoted=is_quoted;
ret->add(tt); ret->add(tt);
ctx = r.second; ctx = r.second;
@ -492,7 +477,7 @@ inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t&
// get subshell // get subshell
ctx.i+=2; ctx.i+=2;
auto r=parse_subshell(ctx); auto r=parse_subshell(ctx);
ret->add(new subarg_subshell_t(r.first, is_quoted)); ret->add(new subshell_subarg(r.first, is_quoted));
ctx = r.second; ctx = r.second;
j = ctx.i; j = ctx.i;
} }
@ -504,7 +489,7 @@ inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t&
// get manipulation // get manipulation
ctx.i+=2; ctx.i+=2;
auto r=parse_manipulation(ctx); auto r=parse_manipulation(ctx);
ret->add(new subarg_variable_t(r.first, is_quoted)); ret->add(new variable_subarg(r.first, is_quoted));
ctx = r.second; ctx = r.second;
j = ctx.i; j = ctx.i;
} }
@ -519,7 +504,7 @@ inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t&
if(ctx.i-j>0) if(ctx.i-j>0)
ret->add(std::string(ctx.data+j, ctx.i-j)); ret->add(std::string(ctx.data+j, ctx.i-j));
// add var // add var
ret->add(new subarg_variable_t(r.first, is_quoted)); ret->add(new variable_subarg(r.first, is_quoted));
ctx = r.second; ctx = r.second;
j = ctx.i; j = ctx.i;
} }
@ -554,9 +539,9 @@ bool _optimize_skip_arg(parse_context& ctx, const char* str) {
// parse one argument // parse one argument
// must start at a read char // must start at a read char
// ends at either " \t|&;\n()" // ends at either " \t|&;\n()"
std::pair<arg_t*, parse_context> parse_arg(parse_context ctx, const char* end, const char* unexpected, bool doquote, const char* optimize) std::pair<arg*, parse_context> parse_arg(parse_context ctx, const char* end, const char* unexpected, bool doquote, const char* optimize)
{ {
arg_t* ret = new arg_t; arg* ret = new arg;
// j : start of subarg , q = start of quote // j : start of subarg , q = start of quote
uint32_t j=ctx.i,q=ctx.i; uint32_t j=ctx.i,q=ctx.i;
@ -649,6 +634,7 @@ parse_context parse_heredocument(parse_context ctx)
{ {
ctx.i = ctx.size; ctx.i = ctx.size;
} }
// std::string tmpparse=std::string(ctx.data+j, ctx.i-j);
parse_context newctx = make_context(ctx, j); parse_context newctx = make_context(ctx, j);
newctx.size = ctx.i; newctx.size = ctx.i;
auto pval = parse_arg(newctx , NULL, NULL, false, ARG_OPTIMIZE_NULL); auto pval = parse_arg(newctx , NULL, NULL, false, ARG_OPTIMIZE_NULL);
@ -664,19 +650,7 @@ parse_context parse_heredocument(parse_context ctx)
return ctx; return ctx;
} }
std::pair<arg_t*, parse_context> parse_bash_procsub(parse_context ctx) std::pair<redirect*, parse_context> parse_redirect(parse_context ctx)
{
if(!ctx.bash)
{
parse_error(strf("bash specific: %c()", ctx[ctx.i]), ctx);
}
bool is_output = ctx[ctx.i] == '>';
ctx.i+=2;
auto ps = parse_subshell(ctx);
return std::make_pair(new arg_t(new subarg_procsub_t(is_output, ps.first)), ps.second);
}
std::pair<redirect_t*, parse_context> parse_redirect(parse_context ctx)
{ {
bool is_redirect=false; bool is_redirect=false;
bool needs_arg=false; bool needs_arg=false;
@ -763,9 +737,9 @@ std::pair<redirect_t*, parse_context> parse_redirect(parse_context ctx)
if(is_redirect) if(is_redirect)
{ {
redirect_t* ret=nullptr; redirect* ret=nullptr;
ret = new redirect_t; ret = new redirect;
ret->op = std::string(ctx.data+start, ctx.i-start); ret->op = std::string(ctx.data+start, ctx.i-start);
if(needs_arg) if(needs_arg)
{ {
@ -801,11 +775,7 @@ std::pair<redirect_t*, parse_context> parse_redirect(parse_context ctx)
} }
else else
{ {
std::pair<arg_t*, parse_context> pa; auto pa = parse_arg(ctx);
if(ctx.i+1 < ctx.size && (ctx[ctx.i] == '<' || ctx[ctx.i] == '>') && ctx[ctx.i+1] == '(' ) // bash specific <()
pa = parse_bash_procsub(ctx);
else
pa = parse_arg(ctx);
ret->target = pa.first; ret->target = pa.first;
ctx=pa.second; ctx=pa.second;
} }
@ -823,9 +793,9 @@ std::pair<redirect_t*, parse_context> parse_redirect(parse_context ctx)
// must start at a read char // must start at a read char
// first char has to be read // first char has to be read
// ends at either &|;\n#() // ends at either &|;\n#()
std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_error, std::vector<redirect_t*>* redirs, bool stop_on_brace) std::pair<arglist*, parse_context> parse_arglist(parse_context ctx, bool hard_error, std::vector<redirect*>* redirs)
{ {
arglist_t* ret = nullptr; arglist* ret = nullptr;
if(word_eq("[[", ctx, ARG_END) ) // [[ bash specific parsing if(word_eq("[[", ctx, ARG_END) ) // [[ bash specific parsing
{ {
@ -836,14 +806,14 @@ std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_
while(true) while(true)
{ {
if(ret == nullptr) if(ret == nullptr)
ret = new arglist_t; ret = new arglist;
auto pp=parse_arg(ctx, SEPARATORS, NULL, true, ARG_OPTIMIZE_BASHTEST); auto pp=parse_arg(ctx, SEPARATORS, NULL, true, ARG_OPTIMIZE_BASHTEST);
ret->add(pp.first); ret->add(pp.first);
ctx = pp.second; ctx = pp.second;
ctx.i = skip_chars(ctx, SEPARATORS); ctx.i = skip_chars(ctx, SEPARATORS);
if(word_eq("]]", ctx, ARG_END)) if(word_eq("]]", ctx, ARG_END))
{ {
ret->add(new arg_t("]]")); ret->add(new arg("]]"));
ctx.i+=2; ctx.i+=2;
ctx.i = skip_chars(ctx, SPACES); ctx.i = skip_chars(ctx, SPACES);
if( !is_in(ctx[ctx.i], ARGLIST_END) ) if( !is_in(ctx[ctx.i], ARGLIST_END) )
@ -876,11 +846,17 @@ std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_
{ {
if(ctx.i+1 < ctx.size && (ctx[ctx.i] == '<' || ctx[ctx.i] == '>') && ctx[ctx.i+1] == '(' ) // bash specific <() if(ctx.i+1 < ctx.size && (ctx[ctx.i] == '<' || ctx[ctx.i] == '>') && ctx[ctx.i+1] == '(' ) // bash specific <()
{ {
auto pa=parse_bash_procsub(ctx); if(!ctx.bash)
{
parse_error(strf("bash specific: %c()", ctx[ctx.i]), ctx);
}
bool is_output = ctx[ctx.i] == '>';
ctx.i+=2;
if(ret == nullptr) if(ret == nullptr)
ret = new arglist_t; ret = new arglist;
ret->add(pa.first); auto ps = parse_subshell(ctx);
ctx=pa.second; ret->add(new arg(new procsub_subarg(is_output, ps.first)));
ctx=ps.second;
} }
else if(redirs!=nullptr) else if(redirs!=nullptr)
{ {
@ -895,12 +871,10 @@ std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_
} }
else else
{ {
argparse: ; argparse:
auto pp=parse_arg(ctx);
if(stop_on_brace && pp.first!=nullptr && pp.first->string() == "}")
return std::make_pair(ret, ctx);
if(ret == nullptr) if(ret == nullptr)
ret = new arglist_t; ret = new arglist;
auto pp=parse_arg(ctx);
ret->add(pp.first); ret->add(pp.first);
ctx = pp.second; ctx = pp.second;
} }
@ -927,33 +901,23 @@ std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_
// must start at a read char // must start at a read char
// separated by | // separated by |
// ends at either &;\n#) // ends at either &;\n#)
std::pair<pipeline_t*, parse_context> parse_pipeline(parse_context ctx) std::pair<pipeline*, parse_context> parse_pipeline(parse_context ctx)
{ {
pipeline_t* ret = new pipeline_t; pipeline* ret = new pipeline;
while(true) {
auto wp = get_word(ctx, ARG_END);
if(ctx[ctx.i] == '!' && ctx.i+1<ctx.size && is_in(ctx[ctx.i+1], SPACES)) if(ctx[ctx.i] == '!' && ctx.i+1<ctx.size && is_in(ctx[ctx.i+1], SPACES))
{ {
ret->negated = ret->negated ? false : true; ret->negated = true;
ctx.i++; ctx.i++;
ctx.i=skip_chars(ctx, SPACES); ctx.i=skip_chars(ctx, SPACES);
} else if(ctx.bash && wp.first == "time" ) {
ret->bash_time = true;
ctx.i+=4;
ctx.i=skip_chars(ctx, SPACES);
} else {
break;
} }
}
while(ctx.i<ctx.size) while(ctx.i<ctx.size)
{ {
auto pp=parse_block(ctx); auto pp=parse_block(ctx);
ret->add(pp.first); ret->add(pp.first);
ctx = pp.second; ctx = pp.second;
ctx.i = skip_chars(ctx, SPACES); ctx.i = skip_chars(ctx, SPACES);
if( ctx.i>=ctx.size || is_in(ctx[ctx.i], PIPELINE_END) || word_eq("||", ctx) || ctx[ctx.i] == '}' ) if( ctx.i>=ctx.size || is_in(ctx[ctx.i], PIPELINE_END) || word_eq("||", ctx) )
return std::make_pair(ret, ctx); return std::make_pair(ret, ctx);
else if( ctx[ctx.i] != '|' ) else if( ctx[ctx.i] != '|' )
{ {
@ -977,9 +941,9 @@ std::pair<pipeline_t*, parse_context> parse_pipeline(parse_context ctx)
// must start at a read char // must start at a read char
// separated by && or || // separated by && or ||
// ends at either ;\n)# // ends at either ;\n)#
std::pair<condlist_t*, parse_context> parse_condlist(parse_context ctx) std::pair<condlist*, parse_context> parse_condlist(parse_context ctx)
{ {
condlist_t* ret = new condlist_t; condlist* ret = new condlist;
ctx.i = skip_unread(ctx); ctx.i = skip_unread(ctx);
bool optype=AND_OP; bool optype=AND_OP;
@ -988,7 +952,7 @@ std::pair<condlist_t*, parse_context> parse_condlist(parse_context ctx)
auto pp=parse_pipeline(ctx); auto pp=parse_pipeline(ctx);
ret->add(pp.first, optype); ret->add(pp.first, optype);
ctx = pp.second; ctx = pp.second;
if(ctx.i>=ctx.size || is_in(ctx[ctx.i], CONTROL_END) || is_in(ctx[ctx.i], COMMAND_SEPARATOR) || ctx[ctx.i] == '}') // end here exactly: used for control later if(ctx.i>=ctx.size || is_in(ctx[ctx.i], CONTROL_END) || is_in(ctx[ctx.i], COMMAND_SEPARATOR)) // end here exactly: used for control later
{ {
return std::make_pair(ret, ctx); return std::make_pair(ret, ctx);
} }
@ -1030,9 +994,9 @@ std::pair<condlist_t*, parse_context> parse_condlist(parse_context ctx)
return std::make_pair(ret, ctx); return std::make_pair(ret, ctx);
} }
std::tuple<list_t*, parse_context, std::string> parse_list_until(parse_context ctx, list_parse_options opts) std::tuple<list*, parse_context, std::string> parse_list_until(parse_context ctx, list_parse_options opts)
{ {
list_t* ret = new list_t; list* ret = new list;
ctx.i=skip_unread(ctx); ctx.i=skip_unread(ctx);
std::string found_end_word; std::string found_end_word;
@ -1105,35 +1069,27 @@ std::tuple<list_t*, parse_context, std::string> parse_list_until(parse_context c
if(ctx.here_document != nullptr) if(ctx.here_document != nullptr)
{ {
bool has_parsed=false; uint8_t do_twice=2;
parse_context t_ctx=ctx; // case of : cat << EOF ;
if(t_ctx[t_ctx.i] == '\n') while(do_twice>0)
{ {
t_ctx = parse_heredocument(t_ctx+1); if(ctx[ctx.i] == '\n')
has_parsed=true;
}
else if(t_ctx[t_ctx.i] == '#')
{ {
t_ctx.i = skip_until(t_ctx, "\n"); //skip to endline ctx = parse_heredocument(ctx+1);
t_ctx = parse_heredocument(t_ctx+1); break;
has_parsed=true;
} }
else if(t_ctx[t_ctx.i] == ';') { else if(ctx[ctx.i] == '#')
t_ctx.i = skip_chars(t_ctx+1, SPACES);
if(t_ctx[t_ctx.i] == '\n')
{ {
t_ctx = parse_heredocument(t_ctx+1); ctx.i = skip_until(ctx, "\n"); //skip to endline
has_parsed=true; ctx = parse_heredocument(ctx+1);
break;
} }
else if(t_ctx[t_ctx.i] == '#') skip_chars(ctx, SPACES);
{ do_twice--;
t_ctx.i = skip_until(t_ctx, "\n"); //skip to endline
t_ctx = parse_heredocument(t_ctx+1);
has_parsed=true;
} }
} // case of : cat << EOF ; ;
if(has_parsed) if(do_twice==0 && is_in(ctx[ctx.i], COMMAND_SEPARATOR))
ctx = t_ctx; parse_error( unexpected_token(ctx[ctx.i]), ctx);
} }
if(is_in(ctx[ctx.i], COMMAND_SEPARATOR)) if(is_in(ctx[ctx.i], COMMAND_SEPARATOR))
@ -1160,9 +1116,9 @@ std::tuple<list_t*, parse_context, std::string> parse_list_until(parse_context c
// parse a subshell // parse a subshell
// must start right after the opening ( // must start right after the opening (
// ends at ) and nothing else // ends at ) and nothing else
std::pair<subshell_t*, parse_context> parse_subshell(parse_context ctx) std::pair<subshell*, parse_context> parse_subshell(parse_context ctx)
{ {
subshell_t* ret = new subshell_t; subshell* ret = new subshell;
uint32_t start=ctx.i; uint32_t start=ctx.i;
ctx.i = skip_unread(ctx); ctx.i = skip_unread(ctx);
@ -1182,9 +1138,9 @@ std::pair<subshell_t*, parse_context> parse_subshell(parse_context ctx)
// parse a brace block // parse a brace block
// must start right after the opening { // must start right after the opening {
// ends at } and nothing else // ends at } and nothing else
std::pair<brace_t*, parse_context> parse_brace(parse_context ctx) std::pair<brace*, parse_context> parse_brace(parse_context ctx)
{ {
brace_t* ret = new brace_t; brace* ret = new brace;
uint32_t start=ctx.i; uint32_t start=ctx.i;
ctx.i = skip_unread(ctx); ctx.i = skip_unread(ctx);
@ -1204,9 +1160,9 @@ std::pair<brace_t*, parse_context> parse_brace(parse_context ctx)
// parse a function // parse a function
// must start right after the () // must start right after the ()
// then parses a brace block // then parses a brace block
std::pair<function_t*, parse_context> parse_function(parse_context ctx, const char* after) std::pair<function*, parse_context> parse_function(parse_context ctx, const char* after)
{ {
function_t* ret = new function_t; function* ret = new function;
ctx.i=skip_unread(ctx); ctx.i=skip_unread(ctx);
if(ctx[ctx.i] != '{') if(ctx[ctx.i] != '{')
@ -1232,7 +1188,7 @@ std::pair<function_t*, parse_context> parse_function(parse_context ctx, const ch
} }
// parse only var assigns // parse only var assigns
parse_context parse_cmd_varassigns(cmd_t* in, parse_context ctx, bool cmdassign=false, std::string const& cmd="") parse_context parse_cmd_varassigns(cmd* in, parse_context ctx, bool cmdassign=false, std::string const& cmd="")
{ {
bool forbid_assign=false; bool forbid_assign=false;
bool forbid_special=false; bool forbid_special=false;
@ -1241,7 +1197,7 @@ parse_context parse_cmd_varassigns(cmd_t* in, parse_context ctx, bool cmdassign=
if(cmdassign && (forbid_special || cmd == "export") ) if(cmdassign && (forbid_special || cmd == "export") )
forbid_special=true; forbid_special=true;
std::vector<std::pair<variable_t*,arg_t*>>* ret=&in->var_assigns; std::vector<std::pair<variable*,arg*>>* ret=&in->var_assigns;
if(cmdassign) if(cmdassign)
ret=&in->cmd_var_assigns; ret=&in->cmd_var_assigns;
@ -1277,7 +1233,7 @@ parse_context parse_cmd_varassigns(cmd_t* in, parse_context ctx, bool cmdassign=
else else
ctx.i++; ctx.i++;
arg_t* ta=nullptr; arg* ta=nullptr;
if(ctx[ctx.i] == '(') // bash var=() if(ctx[ctx.i] == '(') // bash var=()
{ {
if(!ctx.bash) if(!ctx.bash)
@ -1289,7 +1245,7 @@ parse_context parse_cmd_varassigns(cmd_t* in, parse_context ctx, bool cmdassign=
parse_error("Unallowed special assign", ctx); parse_error("Unallowed special assign", ctx);
} }
ctx.i++; ctx.i++;
auto pp=parse_arg(ctx, ")", "", false, ARG_OPTIMIZE_DEFARR); auto pp=parse_arg(ctx, ")", ARG_OPTIMIZE_DEFARR);
ta=pp.first; ta=pp.first;
ta->insert(0,"("); ta->insert(0,"(");
ta->add(")"); ta->add(")");
@ -1298,7 +1254,7 @@ parse_context parse_cmd_varassigns(cmd_t* in, parse_context ctx, bool cmdassign=
} }
else if( is_in(ctx[ctx.i], ARG_END) ) // no value : give empty value else if( is_in(ctx[ctx.i], ARG_END) ) // no value : give empty value
{ {
ta = new arg_t; ta = new arg;
} }
else else
{ {
@ -1307,7 +1263,6 @@ parse_context parse_cmd_varassigns(cmd_t* in, parse_context ctx, bool cmdassign=
ctx=pp.second; ctx=pp.second;
} }
ta->insert(0, strop); ta->insert(0, strop);
ta->forcequoted = !cmdassign;
ret->push_back(std::make_pair(vp.first, ta)); ret->push_back(std::make_pair(vp.first, ta));
ctx.i=skip_chars(ctx, SPACES); ctx.i=skip_chars(ctx, SPACES);
} }
@ -1341,9 +1296,9 @@ parse_context parse_cmd_varassigns(cmd_t* in, parse_context ctx, bool cmdassign=
} }
// must start at read char // must start at read char
std::pair<cmd_t*, parse_context> parse_cmd(parse_context ctx) std::pair<cmd*, parse_context> parse_cmd(parse_context ctx)
{ {
cmd_t* ret = new cmd_t; cmd* ret = new cmd;
ctx = parse_cmd_varassigns(ret, ctx); ctx = parse_cmd_varassigns(ret, ctx);
@ -1356,8 +1311,8 @@ std::pair<cmd_t*, parse_context> parse_cmd(parse_context ctx)
parse_error("bash specific: "+wp.first, ctx); parse_error("bash specific: "+wp.first, ctx);
} }
ret->args = new arglist_t; ret->args = new arglist;
ret->args->add(new arg_t(wp.first)); ret->args->add(new arg(wp.first));
ret->is_cmdvar=true; ret->is_cmdvar=true;
ctx.i = wp.second; ctx.i = wp.second;
ctx.i = skip_chars(ctx, SPACES); ctx.i = skip_chars(ctx, SPACES);
@ -1382,9 +1337,9 @@ std::pair<cmd_t*, parse_context> parse_cmd(parse_context ctx)
// parse a case block // parse a case block
// must start right after the case // must start right after the case
// ends at } and nothing else // ends at } and nothing else
std::pair<case_t*, parse_context> parse_case(parse_context ctx) std::pair<case_block*, parse_context> parse_case(parse_context ctx)
{ {
case_t* ret = new case_t; case_block* ret = new case_block;
ctx.i=skip_chars(ctx, SPACES); ctx.i=skip_chars(ctx, SPACES);
// get the treated argument // get the treated argument
@ -1406,7 +1361,7 @@ std::pair<case_t*, parse_context> parse_case(parse_context ctx)
while(ctx.i<ctx.size && !word_eq("esac", ctx, ARG_END) ) while(ctx.i<ctx.size && !word_eq("esac", ctx, ARG_END) )
{ {
// add one element // add one element
ret->cases.push_back( std::make_pair(std::vector<arg_t*>(), nullptr) ); ret->cases.push_back( std::make_pair(std::vector<arg*>(), nullptr) );
// iterator to last element // iterator to last element
auto cc = ret->cases.end()-1; auto cc = ret->cases.end()-1;
@ -1472,9 +1427,9 @@ std::pair<case_t*, parse_context> parse_case(parse_context ctx)
return std::make_pair(ret, ctx); return std::make_pair(ret, ctx);
} }
std::pair<if_t*, parse_context> parse_if(parse_context ctx) std::pair<if_block*, parse_context> parse_if(parse_context ctx)
{ {
if_t* ret = new if_t; if_block* ret = new if_block;
while(true) while(true)
{ {
@ -1531,9 +1486,9 @@ std::pair<if_t*, parse_context> parse_if(parse_context ctx)
return std::make_pair(ret, ctx); return std::make_pair(ret, ctx);
} }
std::pair<for_t*, parse_context> parse_for(parse_context ctx) std::pair<for_block*, parse_context> parse_for(parse_context ctx)
{ {
for_t* ret = new for_t; for_block* ret = new for_block;
ctx.i = skip_chars(ctx, SPACES); ctx.i = skip_chars(ctx, SPACES);
auto wp = get_word(ctx, ARG_END); auto wp = get_word(ctx, ARG_END);
@ -1542,7 +1497,7 @@ std::pair<for_t*, parse_context> parse_for(parse_context ctx)
{ {
parse_error( strf("Bad variable name in for clause: '%s'", wp.first.c_str()), ctx ); parse_error( strf("Bad variable name in for clause: '%s'", wp.first.c_str()), ctx );
} }
ret->var = new variable_t(wp.first, nullptr, true); ret->var = new variable(wp.first, nullptr, true);
ctx.i = wp.second; ctx.i = wp.second;
ctx.i=skip_chars(ctx, SPACES); ctx.i=skip_chars(ctx, SPACES);
@ -1595,9 +1550,9 @@ std::pair<for_t*, parse_context> parse_for(parse_context ctx)
return std::make_pair(ret, ctx); return std::make_pair(ret, ctx);
} }
std::pair<while_t*, parse_context> parse_while(parse_context ctx) std::pair<while_block*, parse_context> parse_while(parse_context ctx)
{ {
while_t* ret = new while_t; while_block* ret = new while_block;
// cond // cond
parse_context oldctx = ctx; parse_context oldctx = ctx;
@ -1627,10 +1582,10 @@ std::pair<while_t*, parse_context> parse_while(parse_context ctx)
} }
// detect if brace, subshell, case or other // detect if brace, subshell, case or other
std::pair<block_t*, parse_context> parse_block(parse_context ctx) std::pair<block*, parse_context> parse_block(parse_context ctx)
{ {
ctx.i = skip_chars(ctx, SEPARATORS); ctx.i = skip_chars(ctx, SEPARATORS);
block_t* ret = nullptr; block* ret = nullptr;
if(ctx.i>=ctx.size) if(ctx.i>=ctx.size)
{ {
@ -1746,11 +1701,11 @@ std::pair<block_t*, parse_context> parse_block(parse_context ctx)
} }
if(ret!=nullptr && ret->type != block_t::block_cmd) if(ret!=nullptr && ret->type != block::block_cmd)
{ {
uint32_t j=skip_chars(ctx, SPACES); uint32_t j=skip_chars(ctx, SPACES);
ctx.i=j; ctx.i=j;
auto pp=parse_arglist(ctx, false, &ret->redirs, true); // in case of redirects auto pp=parse_arglist(ctx, false, &ret->redirs); // in case of redirects
if(pp.first != nullptr) if(pp.first != nullptr)
{ {
delete pp.first; delete pp.first;

View file

@ -155,7 +155,7 @@ std::string get_varname(std::string const& in)
return in; return in;
} }
std::string get_varname(arg_t* in) std::string get_varname(arg* in)
{ {
if(in->sa.size() < 1 || in->sa[0]->type != _obj::subarg_string) if(in->sa.size() < 1 || in->sa[0]->type != _obj::subarg_string)
return ""; return "";
@ -170,12 +170,12 @@ bool cmd_is_argvar(std::string const& in)
return is_in_set(in, posix_cmdvar) || is_in_set(in, bash_cmdvar); return is_in_set(in, posix_cmdvar) || is_in_set(in, bash_cmdvar);
} }
bool cmd_t::is_argvar() bool cmd::is_argvar()
{ {
return is_cmdvar; return is_cmdvar;
} }
bool cmd_t::is(std::string const& in) bool cmd::is(std::string const& in)
{ {
return in == this->arg_string(0); return in == this->arg_string(0);
} }
@ -285,14 +285,14 @@ void add_unset_variables(shmain* sh, std::regex const& exclude)
varmap_get(sh, exclude); varmap_get(sh, exclude);
if(m_vars.size()>0) if(m_vars.size()>0)
{ {
cmd_t* unset_cmd = new cmd_t; cmd* unset_cmd = new cmd;
unset_cmd->add(new arg_t("unset")); unset_cmd->add(new arg("unset"));
unset_cmd->is_cmdvar=true; unset_cmd->is_cmdvar=true;
for(auto it: m_vars) for(auto it: m_vars)
{ {
unset_cmd->cmd_var_assigns.push_back(std::make_pair(new variable_t(it.first), nullptr)); unset_cmd->cmd_var_assigns.push_back(std::make_pair(new variable(it.first), nullptr));
} }
condlist_t* cl = new condlist_t(unset_cmd); condlist* cl = new condlist(unset_cmd);
sh->lst->cls.insert(sh->lst->cls.begin(), cl); sh->lst->cls.insert(sh->lst->cls.begin(), cl);
} }
} }
@ -315,7 +315,7 @@ bool r_has_env_set(_obj* in, bool* result)
return false; return false;
}; break; }; break;
case _obj::block_cmd: { case _obj::block_cmd: {
cmd_t* t = dynamic_cast<cmd_t*>(in); cmd* t = dynamic_cast<cmd*>(in);
if(t->has_var_assign() || t->arg_string(0) == "cd") if(t->has_var_assign() || t->arg_string(0) == "cd")
*result = true; *result = true;
} }
@ -330,8 +330,8 @@ bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap)
{ {
switch(in->type) switch(in->type)
{ {
case _obj::variable: { case _obj::_variable: {
variable_t* t = dynamic_cast<variable_t*>(in); variable* t = dynamic_cast<variable*>(in);
if(t->definition) if(t->definition)
{ {
if(!defmap->insert( std::make_pair(t->varname, 1) ).second) if(!defmap->insert( std::make_pair(t->varname, 1) ).second)
@ -353,7 +353,7 @@ bool r_get_unsets(_obj* in, set_t* unsets)
switch(in->type) switch(in->type)
{ {
case _obj::block_cmd: { case _obj::block_cmd: {
cmd_t* t = dynamic_cast<cmd_t*>(in); cmd* t = dynamic_cast<cmd*>(in);
if(t->is("unset")) if(t->is("unset"))
{ {
for(auto it: t->cmd_var_assigns) for(auto it: t->cmd_var_assigns)
@ -373,7 +373,7 @@ bool r_get_cmd(_obj* in, countmap_t* all_cmds)
switch(in->type) switch(in->type)
{ {
case _obj::block_cmd: { case _obj::block_cmd: {
cmd_t* t = dynamic_cast<cmd_t*>(in); cmd* t = dynamic_cast<cmd*>(in);
std::string cmdname = t->arg_string(0); std::string cmdname = t->arg_string(0);
if(cmdname != "" && !all_cmds->insert( std::make_pair(cmdname, 1) ).second) if(cmdname != "" && !all_cmds->insert( std::make_pair(cmdname, 1) ).second)
(*all_cmds)[cmdname]++; (*all_cmds)[cmdname]++;
@ -388,7 +388,7 @@ bool r_get_fct(_obj* in, countmap_t* fct_map)
switch(in->type) switch(in->type)
{ {
case _obj::block_function: { case _obj::block_function: {
function_t* t = dynamic_cast<function_t*>(in); function* t = dynamic_cast<function*>(in);
if(!fct_map->insert( std::make_pair(t->name, 1) ).second) if(!fct_map->insert( std::make_pair(t->name, 1) ).second)
(*fct_map)[t->name]++; (*fct_map)[t->name]++;
}; break; }; break;
@ -418,14 +418,14 @@ bool r_delete_fct(_obj* in, set_t* fcts)
{ {
switch(in->type) switch(in->type)
{ {
case _obj::list: { case _obj::_list: {
list_t* t = dynamic_cast<list_t*>(in); list* t = dynamic_cast<list*>(in);
for(uint32_t i=0; i<t->cls.size(); i++) for(uint32_t i=0; i<t->cls.size(); i++)
{ {
block_t* tb = t->cls[i]->first_block(); block* tb = t->cls[i]->first_block();
if(tb != nullptr && tb->type == _obj::block_function) if(tb != nullptr && tb->type == _obj::block_function)
{ {
function_t* fc = dynamic_cast<function_t*>(tb); function* fc = dynamic_cast<function*>(tb);
if(fcts->find(fc->name)!=fcts->end()) if(fcts->find(fc->name)!=fcts->end())
{ {
delete t->cls[i]; delete t->cls[i];
@ -444,16 +444,16 @@ bool r_delete_var(_obj* in, set_t* vars)
{ {
switch(in->type) switch(in->type)
{ {
case _obj::list: { case _obj::_list: {
list_t* t = dynamic_cast<list_t*>(in); list* t = dynamic_cast<list*>(in);
for(uint32_t i=0; i<t->cls.size(); i++) for(uint32_t i=0; i<t->cls.size(); i++)
{ {
block_t* tb = t->cls[i]->first_block(); block* tb = t->cls[i]->first_block();
bool to_delete=false; bool to_delete=false;
bool has_deleted=false; bool has_deleted=false;
if(tb != nullptr && tb->type == _obj::block_cmd) if(tb != nullptr && tb->type == _obj::block_cmd)
{ {
cmd_t* c = dynamic_cast<cmd_t*>(tb); cmd* c = dynamic_cast<cmd*>(tb);
for(uint32_t j=0; j<c->var_assigns.size(); j++) for(uint32_t j=0; j<c->var_assigns.size(); j++)
{ {
@ -549,7 +549,7 @@ bool r_do_string_processor(_obj* in)
{ {
if(in->type == _obj::subarg_string) if(in->type == _obj::subarg_string)
{ {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(in); string_subarg* t = dynamic_cast<string_subarg*>(in);
auto v = get_processors(t->val); auto v = get_processors(t->val);
if(v.find("LXSH_PARSE_MINIFY") != v.end()) if(v.find("LXSH_PARSE_MINIFY") != v.end())
{ {
@ -634,9 +634,9 @@ std::string gen_json_struc(_obj* o)
std::vector<std::pair<std::string,std::string>> vec; std::vector<std::pair<std::string,std::string>> vec;
switch(o->type) switch(o->type)
{ {
case _obj::variable : case _obj::_variable :
{ {
variable_t* t = dynamic_cast<variable_t*>(o); variable* t = dynamic_cast<variable*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("variable") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("variable") ) );
vec.push_back(std::make_pair(quote_string("varname"), quote_string(t->varname))); vec.push_back(std::make_pair(quote_string("varname"), quote_string(t->varname)));
vec.push_back(std::make_pair(quote_string("definition"), boolstring(t->definition))); vec.push_back(std::make_pair(quote_string("definition"), boolstring(t->definition)));
@ -646,29 +646,28 @@ std::string gen_json_struc(_obj* o)
vec.push_back(std::make_pair(quote_string("manip"), gen_json_struc(t->manip) ) ); vec.push_back(std::make_pair(quote_string("manip"), gen_json_struc(t->manip) ) );
break; break;
} }
case _obj::redirect : case _obj::_redirect :
{ {
redirect_t* t = dynamic_cast<redirect_t*>(o); redirect* t = dynamic_cast<redirect*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("redirect") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("redirect") ) );
vec.push_back(std::make_pair(quote_string("op"), quote_string(t->op))); vec.push_back(std::make_pair(quote_string("op"), quote_string(t->op)));
vec.push_back(std::make_pair(quote_string("target"), gen_json_struc(t->target))); vec.push_back(std::make_pair(quote_string("target"), gen_json_struc(t->target)));
vec.push_back(std::make_pair(quote_string("here_document"), gen_json_struc(t->here_document))); vec.push_back(std::make_pair(quote_string("here_document"), gen_json_struc(t->here_document)));
break; break;
} }
case _obj::arg : case _obj::_arg :
{ {
arg_t* t = dynamic_cast<arg_t*>(o); arg* t = dynamic_cast<arg*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("arg") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("arg") ) );
vec.push_back(std::make_pair(quote_string("forcequoted"), boolstring(t->forcequoted)));
std::vector<std::string> tvec; std::vector<std::string> tvec;
for(auto it: t->sa) for(auto it: t->sa)
tvec.push_back(gen_json_struc(it)); tvec.push_back(gen_json_struc(it));
vec.push_back(std::make_pair(quote_string("sa"), gen_json(tvec))); vec.push_back(std::make_pair(quote_string("sa"), gen_json(tvec)));
break; break;
} }
case _obj::arglist : case _obj::_arglist :
{ {
arglist_t* t = dynamic_cast<arglist_t*>(o); arglist* t = dynamic_cast<arglist*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("arglist") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("arglist") ) );
std::vector<std::string> tvec; std::vector<std::string> tvec;
for(auto it: t->args) for(auto it: t->args)
@ -676,9 +675,9 @@ std::string gen_json_struc(_obj* o)
vec.push_back(std::make_pair(quote_string("args"), gen_json(tvec))); vec.push_back(std::make_pair(quote_string("args"), gen_json(tvec)));
break; break;
} }
case _obj::pipeline : case _obj::_pipeline :
{ {
pipeline_t* t = dynamic_cast<pipeline_t*>(o); pipeline* t = dynamic_cast<pipeline*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("pipeline") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("pipeline") ) );
vec.push_back(std::make_pair(quote_string("negated"), boolstring(t->negated) ) ); vec.push_back(std::make_pair(quote_string("negated"), boolstring(t->negated) ) );
std::vector<std::string> tvec; std::vector<std::string> tvec;
@ -687,9 +686,9 @@ std::string gen_json_struc(_obj* o)
vec.push_back(std::make_pair(quote_string("cmds"), gen_json(tvec))); vec.push_back(std::make_pair(quote_string("cmds"), gen_json(tvec)));
break; break;
} }
case _obj::condlist : case _obj::_condlist :
{ {
condlist_t* t = dynamic_cast<condlist_t*>(o); condlist* t = dynamic_cast<condlist*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("condlist") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("condlist") ) );
vec.push_back(std::make_pair(quote_string("parallel"), boolstring(t->parallel) ) ); vec.push_back(std::make_pair(quote_string("parallel"), boolstring(t->parallel) ) );
std::vector<std::string> tvec; std::vector<std::string> tvec;
@ -705,9 +704,9 @@ std::string gen_json_struc(_obj* o)
vec.push_back(std::make_pair(quote_string("or_ops"), gen_json(ttvec))); vec.push_back(std::make_pair(quote_string("or_ops"), gen_json(ttvec)));
break; break;
} }
case _obj::list : case _obj::_list :
{ {
list_t* t = dynamic_cast<list_t*>(o); list* t = dynamic_cast<list*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("list") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("list") ) );
std::vector<std::string> tvec; std::vector<std::string> tvec;
for(auto it: t->cls) for(auto it: t->cls)
@ -717,7 +716,7 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::block_subshell : case _obj::block_subshell :
{ {
subshell_t* t = dynamic_cast<subshell_t*>(o); subshell* t = dynamic_cast<subshell*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("subshell") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("subshell") ) );
vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst)));
@ -731,7 +730,7 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::block_brace : case _obj::block_brace :
{ {
brace_t* t = dynamic_cast<brace_t*>(o); brace* t = dynamic_cast<brace*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("brace") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("brace") ) );
vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst)));
@ -760,7 +759,7 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::block_function : case _obj::block_function :
{ {
function_t* t = dynamic_cast<function_t*>(o); function* t = dynamic_cast<function*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("function") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("function") ) );
vec.push_back(std::make_pair(quote_string("name"), quote_string(t->name) ) ); vec.push_back(std::make_pair(quote_string("name"), quote_string(t->name) ) );
@ -775,7 +774,7 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::block_cmd : case _obj::block_cmd :
{ {
cmd_t* t = dynamic_cast<cmd_t*>(o); cmd* t = dynamic_cast<cmd*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("cmd") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("cmd") ) );
vec.push_back(std::make_pair(quote_string("args"), gen_json_struc(t->args))); vec.push_back(std::make_pair(quote_string("args"), gen_json_struc(t->args)));
@ -809,7 +808,7 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::block_case : case _obj::block_case :
{ {
case_t* t = dynamic_cast<case_t*>(o); case_block* t = dynamic_cast<case_block*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("case") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("case") ) );
vec.push_back(std::make_pair(quote_string("carg"), gen_json_struc(t->carg))); vec.push_back(std::make_pair(quote_string("carg"), gen_json_struc(t->carg)));
@ -838,7 +837,7 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::block_if : case _obj::block_if :
{ {
if_t* t = dynamic_cast<if_t*>(o); if_block* t = dynamic_cast<if_block*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("if") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("if") ) );
std::vector<std::string> condblocks; std::vector<std::string> condblocks;
@ -863,7 +862,7 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::block_for : case _obj::block_for :
{ {
for_t* t = dynamic_cast<for_t*>(o); for_block* t = dynamic_cast<for_block*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("for") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("for") ) );
vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var))); vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var)));
vec.push_back(std::make_pair(quote_string("iter"), gen_json_struc(t->iter))); vec.push_back(std::make_pair(quote_string("iter"), gen_json_struc(t->iter)));
@ -878,7 +877,7 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::block_while : case _obj::block_while :
{ {
while_t* t = dynamic_cast<while_t*>(o); while_block* t = dynamic_cast<while_block*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("while") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("while") ) );
vec.push_back(std::make_pair(quote_string("cond"), gen_json_struc(t->cond) ) ); vec.push_back(std::make_pair(quote_string("cond"), gen_json_struc(t->cond) ) );
vec.push_back(std::make_pair(quote_string("ops"), gen_json_struc(t->ops) ) ); vec.push_back(std::make_pair(quote_string("ops"), gen_json_struc(t->ops) ) );
@ -892,21 +891,21 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::subarg_variable : case _obj::subarg_variable :
{ {
subarg_variable_t* t = dynamic_cast<subarg_variable_t*>(o); variable_subarg* t = dynamic_cast<variable_subarg*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_variable") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_variable") ) );
vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) ); vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) );
break; break;
} }
case _obj::subarg_subshell : case _obj::subarg_subshell :
{ {
subarg_subshell_t* t = dynamic_cast<subarg_subshell_t*>(o); subshell_subarg* t = dynamic_cast<subshell_subarg*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_subshell") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_subshell") ) );
vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) );
break; break;
} }
case _obj::subarg_procsub : case _obj::subarg_procsub :
{ {
subarg_procsub_t* t = dynamic_cast<subarg_procsub_t*>(o); procsub_subarg* t = dynamic_cast<procsub_subarg*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_procsub") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_procsub") ) );
vec.push_back(std::make_pair(quote_string("is_output"), boolstring(t->is_output) ) ); vec.push_back(std::make_pair(quote_string("is_output"), boolstring(t->is_output) ) );
vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) );
@ -914,35 +913,35 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::subarg_arithmetic : case _obj::subarg_arithmetic :
{ {
subarg_arithmetic_t* t = dynamic_cast<subarg_arithmetic_t*>(o); arithmetic_subarg* t = dynamic_cast<arithmetic_subarg*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_arithmetic") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_arithmetic") ) );
vec.push_back(std::make_pair(quote_string("arith"), gen_json_struc(t->arith) ) ); vec.push_back(std::make_pair(quote_string("arith"), gen_json_struc(t->arith) ) );
break; break;
} }
case _obj::subarg_string : case _obj::subarg_string :
{ {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(o); string_subarg* t = dynamic_cast<string_subarg*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_string") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_string") ) );
vec.push_back(std::make_pair(quote_string("val"), quote_string(t->val) ) ); vec.push_back(std::make_pair(quote_string("val"), quote_string(t->val) ) );
break; break;
} }
case _obj::arithmetic_variable : case _obj::arithmetic_variable :
{ {
arithmetic_variable_t* t = dynamic_cast<arithmetic_variable_t*>(o); variable_arithmetic* t = dynamic_cast<variable_arithmetic*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_variable") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_variable") ) );
vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) ); vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) );
break; break;
} }
case _obj::arithmetic_subshell : case _obj::arithmetic_subshell :
{ {
arithmetic_subshell_t* t = dynamic_cast<arithmetic_subshell_t*>(o); subshell_arithmetic* t = dynamic_cast<subshell_arithmetic*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_subshell") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_subshell") ) );
vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) );
break; break;
} }
case _obj::arithmetic_operation : case _obj::arithmetic_operation :
{ {
arithmetic_operation_t* t = dynamic_cast<arithmetic_operation_t*>(o); operation_arithmetic* t = dynamic_cast<operation_arithmetic*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_operation") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_operation") ) );
vec.push_back(std::make_pair(quote_string("val1"), gen_json_struc(t->val1) ) ); vec.push_back(std::make_pair(quote_string("val1"), gen_json_struc(t->val1) ) );
vec.push_back(std::make_pair(quote_string("val2"), gen_json_struc(t->val2) ) ); vec.push_back(std::make_pair(quote_string("val2"), gen_json_struc(t->val2) ) );
@ -950,14 +949,14 @@ std::string gen_json_struc(_obj* o)
} }
case _obj::arithmetic_parenthesis : case _obj::arithmetic_parenthesis :
{ {
arithmetic_parenthesis_t* t = dynamic_cast<arithmetic_parenthesis_t*>(o); parenthesis_arithmetic* t = dynamic_cast<parenthesis_arithmetic*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_parenthesis") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_parenthesis") ) );
vec.push_back(std::make_pair(quote_string("val"), gen_json_struc(t->val) ) ); vec.push_back(std::make_pair(quote_string("val"), gen_json_struc(t->val) ) );
break; break;
} }
case _obj::arithmetic_number : case _obj::arithmetic_number :
{ {
arithmetic_number_t* t = dynamic_cast<arithmetic_number_t*>(o); number_arithmetic* t = dynamic_cast<number_arithmetic*>(o);
vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_number") ) ); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_number") ) );
vec.push_back(std::make_pair(quote_string("val"), quote_string(t->val) ) ); vec.push_back(std::make_pair(quote_string("val"), quote_string(t->val) ) );
break; break;

View file

@ -59,7 +59,7 @@ void _cd(std::string const& dir)
// -- COMMANDS -- // -- COMMANDS --
// return <name, contents>[] // return <name, contents>[]
std::vector<std::pair<std::string, std::string>> do_include_raw(condlist_t* cmd, parse_context ctx, std::string* ex_dir) std::vector<std::pair<std::string, std::string>> do_include_raw(condlist* cmd, parse_context ctx, std::string* ex_dir)
{ {
std::vector<std::pair<std::string, std::string>> ret; std::vector<std::pair<std::string, std::string>> ret;
@ -105,7 +105,7 @@ std::vector<std::pair<std::string, std::string>> do_include_raw(condlist_t* cmd,
} }
// //
std::pair<std::string, std::string> do_resolve_raw(condlist_t* cmd, parse_context ctx, std::string* ex_dir) std::pair<std::string, std::string> do_resolve_raw(condlist* cmd, parse_context ctx, std::string* ex_dir)
{ {
std::pair<std::string, std::string> ret; std::pair<std::string, std::string> ret;
@ -152,9 +152,9 @@ std::pair<std::string, std::string> do_resolve_raw(condlist_t* cmd, parse_contex
return ret; return ret;
} }
std::vector<condlist_t*> do_include_parse(condlist_t* cmd, parse_context ctx) std::vector<condlist*> do_include_parse(condlist* cmd, parse_context ctx)
{ {
std::vector<condlist_t*> ret; std::vector<condlist*> ret;
std::string dir; std::string dir;
auto incs=do_include_raw(cmd, ctx, &dir); auto incs=do_include_raw(cmd, ctx, &dir);
@ -186,9 +186,9 @@ std::vector<condlist_t*> do_include_parse(condlist_t* cmd, parse_context ctx)
} }
// if first is nullptr: is a string // if first is nullptr: is a string
std::vector<condlist_t*> do_resolve_parse(condlist_t* cmd, parse_context ctx) std::vector<condlist*> do_resolve_parse(condlist* cmd, parse_context ctx)
{ {
std::vector<condlist_t*> ret; std::vector<condlist*> ret;
std::pair<std::string,std::string> p; std::pair<std::string,std::string> p;
try try
@ -220,11 +220,11 @@ std::vector<condlist_t*> do_resolve_parse(condlist_t* cmd, parse_context ctx)
// -- OBJECT CALLS -- // -- OBJECT CALLS --
std::pair< std::vector<condlist_t*> , bool > resolve_condlist(condlist_t* in, parse_context ctx) std::pair< std::vector<condlist*> , bool > resolve_condlist(condlist* in, parse_context ctx)
{ {
cmd_t* tc = in->first_cmd(); cmd* tc = in->first_cmd();
if(tc == nullptr) if(tc == nullptr)
return std::make_pair(std::vector<condlist_t*>(), false); return std::make_pair(std::vector<condlist*>(), false);
std::string const& strcmd=tc->arg_string(0); std::string const& strcmd=tc->arg_string(0);
@ -233,17 +233,17 @@ std::pair< std::vector<condlist_t*> , bool > resolve_condlist(condlist_t* in, pa
else if(g_resolve && strcmd == "%resolve") else if(g_resolve && strcmd == "%resolve")
return std::make_pair(do_resolve_parse(in, ctx), true); return std::make_pair(do_resolve_parse(in, ctx), true);
else else
return std::make_pair(std::vector<condlist_t*>(), false); return std::make_pair(std::vector<condlist*>(), false);
} }
std::pair< std::vector<arg_t*> , bool > resolve_arg(arg_t* in, parse_context ctx, bool forcequote=false) std::pair< std::vector<arg*> , bool > resolve_arg(arg* in, parse_context ctx, bool forcequote=false)
{ {
std::vector<arg_t*> ret; std::vector<arg*> ret;
if(in == nullptr) if(in == nullptr)
{ {
return std::make_pair(ret, false); return std::make_pair(ret, false);
} }
arg_t* ta=nullptr; arg* ta=nullptr;
bool has_resolved=false; bool has_resolved=false;
uint32_t j=0; uint32_t j=0;
for(uint32_t i=0 ; i<in->size() ; i++) for(uint32_t i=0 ; i<in->size() ; i++)
@ -251,11 +251,11 @@ std::pair< std::vector<arg_t*> , bool > resolve_arg(arg_t* in, parse_context ctx
if(in->sa[i]->type != _obj::subarg_subshell) // skip if not subshell if(in->sa[i]->type != _obj::subarg_subshell) // skip if not subshell
continue; continue;
subarg_subshell_t* tsh = dynamic_cast<subarg_subshell_t*>(in->sa[i]); subshell_subarg* tsh = dynamic_cast<subshell_subarg*>(in->sa[i]);
if(tsh->sbsh->lst->cls.size() != 1) // skip if not one cl if(tsh->sbsh->lst->cls.size() != 1) // skip if not one cl
continue; continue;
condlist_t* tc = tsh->sbsh->lst->cls[0]; condlist* tc = tsh->sbsh->lst->cls[0];
cmd_t* c = tc->first_cmd(); cmd* c = tc->first_cmd();
if(c == nullptr) // skip if not cmd if(c == nullptr) // skip if not cmd
continue; continue;
std::string strcmd=c->arg_string(0); std::string strcmd=c->arg_string(0);
@ -294,7 +294,7 @@ std::pair< std::vector<arg_t*> , bool > resolve_arg(arg_t* in, parse_context ctx
{ {
// replace with new subarg // replace with new subarg
delete in->sa[i]; delete in->sa[i];
in->sa[i] = new subarg_string_t(fulltext); in->sa[i] = new string_subarg(fulltext);
} }
else else
{ {
@ -305,21 +305,21 @@ std::pair< std::vector<arg_t*> , bool > resolve_arg(arg_t* in, parse_context ctx
if(strargs.size() == 1) if(strargs.size() == 1)
val = strargs[0]; val = strargs[0];
delete in->sa[i]; delete in->sa[i];
in->sa[i] = new subarg_string_t(val); in->sa[i] = new string_subarg(val);
} }
else // pack else // pack
{ {
if(ta == nullptr) if(ta == nullptr)
ta = new arg_t; ta = new arg;
ta->sa.insert(ta->sa.end(), in->sa.begin()+j, in->sa.begin()+i); ta->sa.insert(ta->sa.end(), in->sa.begin()+j, in->sa.begin()+i);
ta->add(new subarg_string_t(strargs[i])); ta->add(new string_subarg(strargs[i]));
j=i+1; j=i+1;
delete in->sa[i]; delete in->sa[i];
for(uint32_t li=1 ; li<strargs.size() ; li++) for(uint32_t li=1 ; li<strargs.size() ; li++)
{ {
ret.push_back(ta); ret.push_back(ta);
ta = new arg_t; ta = new arg;
ta->add(new subarg_string_t(strargs[li])); ta->add(new string_subarg(strargs[li]));
} }
} // end pack } // end pack
@ -350,9 +350,9 @@ bool r_resolve(_obj* o, parse_context* ct)
// check every sub-object // check every sub-object
// execute resolve manually // execute resolve manually
// instruct parent resolve to not resolve // instruct parent resolve to not resolve
case _obj::list : case _obj::_list :
{ {
auto t = dynamic_cast<list_t*>(o); auto t = dynamic_cast<list*>(o);
for(uint32_t i=0 ; i<t->cls.size() ; i++) for(uint32_t i=0 ; i<t->cls.size() ; i++)
{ {
auto r=resolve_condlist(t->cls[i], *ct); auto r=resolve_condlist(t->cls[i], *ct);
@ -373,9 +373,9 @@ bool r_resolve(_obj* o, parse_context* ct)
} }
return false; return false;
} break; } break;
case _obj::arglist : case _obj::_arglist :
{ {
auto t = dynamic_cast<arglist_t*>(o); auto t = dynamic_cast<arglist*>(o);
for(uint32_t i=0 ; i<t->size() ; i++) for(uint32_t i=0 ; i<t->size() ; i++)
{ {
auto r=resolve_arg(t->args[i], *ct); auto r=resolve_arg(t->args[i], *ct);
@ -397,7 +397,7 @@ bool r_resolve(_obj* o, parse_context* ct)
} break; } break;
case _obj::block_cmd : case _obj::block_cmd :
{ {
auto t = dynamic_cast<cmd_t*>(o); auto t = dynamic_cast<cmd*>(o);
for(auto it: t->var_assigns) // var assigns for(auto it: t->var_assigns) // var assigns
{ {
resolve_arg(it.second, *ct, true); // force quoted resolve_arg(it.second, *ct, true); // force quoted
@ -415,7 +415,7 @@ bool r_resolve(_obj* o, parse_context* ct)
}; break; }; break;
case _obj::block_case : case _obj::block_case :
{ {
auto t = dynamic_cast<case_t*>(o); auto t = dynamic_cast<case_block*>(o);
for(auto sc: t->cases) for(auto sc: t->cases)
{ {
resolve_arg(t->carg, *ct, true); // force quoted resolve_arg(t->carg, *ct, true); // force quoted

View file

@ -7,7 +7,7 @@
const std::map<const std::string, const lxsh_fct> lxsh_extend_fcts = { const std::map<const std::string, const lxsh_fct> lxsh_extend_fcts = {
{ "_lxsh_random", { "[K]", "Generate a random number between 0 and 2^(K*8). Default 2", RANDOM_SH} }, { "_lxsh_random", { "[K]", "Generate a random number between 0 and 2^(K*8). Default 2", RANDOM_SH} },
{ "_lxsh_random_string", { "[N]", "Generate a random alphanumeric string of length N. Default 20", RANDOM_STRING_SH} }, { "_lxsh_random_string", { "[N]", "Generate a random alphanumeric string of length N. Default 20", RANDOM_STRING_SH} },
{ "_lxsh_random_tmpfile", { "[PREFIX] [N]", "Get a random TMP filepath, with N random chars. Default 20", RANDOM_TMPFILE_SH, {"_lxsh_random_string"} } { "_lxsh_random_tmpfile", { "[N]", "Get a random TMP filepath, with N random chars. Default 20", RANDOM_TMPFILE_SH, {"_lxsh_random_string"} }
} }
}; };

View file

@ -5,11 +5,13 @@
#include <unistd.h> #include <unistd.h>
const std::string cmd_t::empty_string=""; std::string g_origin="";
condlist_t::condlist_t(block_t* bl) const std::string cmd::empty_string="";
condlist::condlist(block* bl)
{ {
type=_obj::condlist; type=_obj::_condlist;
parallel=false; parallel=false;
this->add(new pipeline_t(bl)); this->add(new pipeline(bl));
} }

View file

@ -7,107 +7,107 @@
// makers // makers
arg_t* make_arg(std::string const& in) arg* make_arg(std::string const& in)
{ {
return parse_arg(make_context(in)).first; return parse_arg(make_context(in)).first;
} }
cmd_t* make_cmd(std::vector<const char*> const& args) cmd* make_cmd(std::vector<const char*> const& args)
{ {
cmd_t* ret = new cmd_t; cmd* ret = new cmd;
ret->args = new arglist_t; ret->args = new arglist;
for(auto it: args) for(auto it: args)
ret->args->add(new arg_t(it)); ret->args->add(new arg(it));
return ret; return ret;
} }
cmd_t* make_cmd(std::vector<std::string> const& args) cmd* make_cmd(std::vector<std::string> const& args)
{ {
cmd_t* ret = new cmd_t; cmd* ret = new cmd;
ret->args = new arglist_t; ret->args = new arglist;
for(auto it: args) for(auto it: args)
ret->args->add(new arg_t(it)); ret->args->add(new arg(it));
return ret; return ret;
} }
cmd_t* make_cmd(std::vector<arg_t*> const& args) cmd* make_cmd(std::vector<arg*> const& args)
{ {
cmd_t* ret = new cmd_t; cmd* ret = new cmd;
ret->args = new arglist_t; ret->args = new arglist;
for(auto it: args) for(auto it: args)
ret->args->add(it); ret->args->add(it);
return ret; return ret;
} }
cmd_t* make_cmd(std::string const& in) cmd* make_cmd(std::string const& in)
{ {
return parse_cmd(make_context(in)).first; return parse_cmd(make_context(in)).first;
} }
pipeline_t* make_pipeline(std::vector<block_t*> const& bls) pipeline* make_pipeline(std::vector<block*> const& bls)
{ {
pipeline_t* ret = new pipeline_t; pipeline* ret = new pipeline;
for(auto it: bls) for(auto it: bls)
ret->add(it); ret->add(it);
return ret; return ret;
} }
pipeline_t* make_pipeline(std::string const& in) pipeline* make_pipeline(std::string const& in)
{ {
return parse_pipeline(make_context(in)).first; return parse_pipeline(make_context(in)).first;
} }
condlist_t* make_condlist(std::string const& in) condlist* make_condlist(std::string const& in)
{ {
return parse_condlist(make_context(in)).first; return parse_condlist(make_context(in)).first;
} }
list_t* make_list(std::string const& in) list* make_list(std::string const& in)
{ {
auto t = parse_list_until(make_context(in)); auto t = parse_list_until(make_context(in));
return std::get<0>(t); return std::get<0>(t);
} }
block_t* make_block(std::string const& in) block* make_block(std::string const& in)
{ {
return parse_block(make_context(in)).first; return parse_block(make_context(in)).first;
} }
cmd_t* make_printf(arg_t* in) cmd* make_printf(arg* in)
{ {
cmd_t* prnt = make_cmd(std::vector<const char*>({"printf", "%s\\\\n"})); cmd* prnt = make_cmd(std::vector<const char*>({"printf", "%s\\\\n"}));
force_quotes(in); force_quotes(in);
prnt->add(in); prnt->add(in);
return prnt; return prnt;
} }
arithmetic_t* make_arithmetic(arg_t* a) arithmetic* make_arithmetic(arg* a)
{ {
if(a->sa.size() != 1) if(a->sa.size() != 1)
{ {
cmd_t* prnt = make_printf(a); cmd* prnt = make_printf(a);
return new arithmetic_subshell_t(new subshell_t(prnt)); return new subshell_arithmetic(new subshell(prnt));
} }
arithmetic_t* ret=nullptr; arithmetic* ret=nullptr;
switch(a->sa[0]->type) { switch(a->sa[0]->type) {
case _obj::subarg_string : { case _obj::subarg_string : {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(a->sa[0]); string_subarg* t = dynamic_cast<string_subarg*>(a->sa[0]);
ret = new arithmetic_number_t(t->val); ret = new number_arithmetic(t->val);
}; break; }; break;
case _obj::subarg_variable : { case _obj::subarg_variable : {
subarg_variable_t* t = dynamic_cast<subarg_variable_t*>(a->sa[0]); variable_subarg* t = dynamic_cast<variable_subarg*>(a->sa[0]);
ret = new arithmetic_variable_t(t->var); ret = new variable_arithmetic(t->var);
t->var = nullptr; t->var = nullptr;
}; break; }; break;
case _obj::subarg_subshell : { case _obj::subarg_subshell : {
subarg_subshell_t* t = dynamic_cast<subarg_subshell_t*>(a->sa[0]); subshell_subarg* t = dynamic_cast<subshell_subarg*>(a->sa[0]);
ret = new arithmetic_subshell_t(t->sbsh); ret = new subshell_arithmetic(t->sbsh);
t->sbsh = nullptr; t->sbsh = nullptr;
}; break; }; break;
case _obj::subarg_arithmetic : { case _obj::subarg_arithmetic : {
subarg_arithmetic_t* t = dynamic_cast<subarg_arithmetic_t*>(a->sa[0]); arithmetic_subarg* t = dynamic_cast<arithmetic_subarg*>(a->sa[0]);
ret = t->arith; ret = t->arith;
t->arith = nullptr; t->arith = nullptr;
}; break; }; break;
@ -117,22 +117,22 @@ arithmetic_t* make_arithmetic(arg_t* a)
return ret; return ret;
} }
arithmetic_t* make_arithmetic(arg_t* arg1, std::string op, arg_t* arg2) arithmetic* make_arithmetic(arg* arg1, std::string op, arg* arg2)
{ {
return new arithmetic_operation_t(op, make_arithmetic(arg1), make_arithmetic(arg2)); return new operation_arithmetic(op, make_arithmetic(arg1), make_arithmetic(arg2));
} }
// copy // copy
arg_t* copy(arg_t* in) { arg* copy(arg* in) {
std::string str = in->generate(0); std::string str = in->generate(0);
return parse_arg(make_context(str)).first; return parse_arg(make_context(str)).first;
} }
// modifiers // modifiers
void force_quotes(arg_t* in) void force_quotes(arg* in)
{ {
for(uint32_t i=0; i < in->sa.size() ; i++) for(uint32_t i=0; i < in->sa.size() ; i++)
{ {
@ -146,24 +146,24 @@ void force_quotes(arg_t* in)
} }
} }
void add_quotes(arg_t* in) void add_quotes(arg* in)
{ {
for(uint32_t i=0; i < in->sa.size() ; i++) for(uint32_t i=0; i < in->sa.size() ; i++)
in->sa[i]->quoted=true; in->sa[i]->quoted=true;
in->insert(0, new subarg_string_t("\"")); in->insert(0, new string_subarg("\""));
in->add("\""); in->add("\"");
} }
// ** TESTERS ** // // ** TESTERS ** //
bool arg_has_char(char c, arg_t* in) bool arg_has_char(char c, arg* in)
{ {
for(auto it: in->sa) for(auto it: in->sa)
{ {
if(it->type == _obj::subarg_string) if(it->type == _obj::subarg_string)
{ {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(it); string_subarg* t = dynamic_cast<string_subarg*>(it);
if(t->val.find(c) != std::string::npos) if(t->val.find(c) != std::string::npos)
return true; return true;
} }
@ -171,7 +171,7 @@ bool arg_has_char(char c, arg_t* in)
return false; return false;
} }
bool possibly_expands(arg_t* in) bool possibly_expands(arg* in)
{ {
for(auto it: in->sa) for(auto it: in->sa)
if( (it->type == _obj::subarg_subshell || it->type == _obj::subarg_variable ) && it->quoted == false) if( (it->type == _obj::subarg_subshell || it->type == _obj::subarg_variable ) && it->quoted == false)
@ -179,7 +179,7 @@ bool possibly_expands(arg_t* in)
return false; return false;
} }
bool possibly_expands(arglist_t* in) bool possibly_expands(arglist* in)
{ {
for(auto it: in->args) for(auto it: in->args)
if(possibly_expands(it)) if(possibly_expands(it))
@ -193,7 +193,7 @@ bool possibly_expands(arglist_t* in)
// property getters // property getters
bool cmd_t::has_var_assign() bool cmd::has_var_assign()
{ {
if(this->args == nullptr || this->args->size() == 0) if(this->args == nullptr || this->args->size() == 0)
{ {
@ -202,7 +202,7 @@ bool cmd_t::has_var_assign()
return this->is_argvar(); return this->is_argvar();
} }
size_t cmd_t::arglist_size() size_t cmd::arglist_size()
{ {
if(args==nullptr) if(args==nullptr)
return 0; return 0;
@ -212,33 +212,26 @@ size_t cmd_t::arglist_size()
// string getters // string getters
bool arg_t::is_string() bool arg::is_string()
{ {
return sa.size() == 1 && sa[0]->type == _obj::subarg_string; return sa.size() == 1 && sa[0]->type == _obj::subarg_string;
} }
std::string arg_t::string() std::string arg::string()
{ {
if(!this->is_string()) if(!this->is_string())
return ""; return "";
return dynamic_cast<subarg_string_t*>(sa[0])->val; return dynamic_cast<string_subarg*>(sa[0])->val;
} }
std::string arg_t::first_sa_string() std::string arg::first_sa_string()
{ {
if(sa.size() <=0 || sa[0]->type != _obj::subarg_string) if(sa.size() <=0 || sa[0]->type != _obj::subarg_string)
return ""; return "";
return dynamic_cast<subarg_string_t*>(sa[0])->val; return dynamic_cast<string_subarg*>(sa[0])->val;
} }
std::string arglist_t::first_arg_string() bool arg::can_expand()
{
if(args.size()<=0 || args[0] == nullptr)
return "";
return args[0]->string();
}
bool arg_t::can_expand()
{ {
for(auto it: sa) for(auto it: sa)
{ {
@ -248,7 +241,7 @@ bool arg_t::can_expand()
return false; return false;
} }
bool arglist_t::can_expand() bool arglist::can_expand()
{ {
bool arg_expands=false; bool arg_expands=false;
for(auto it: args) for(auto it: args)
@ -260,7 +253,7 @@ bool arglist_t::can_expand()
return false; return false;
} }
std::vector<std::string> arglist_t::strargs(uint32_t start) std::vector<std::string> arglist::strargs(uint32_t start)
{ {
std::vector<std::string> ret; std::vector<std::string> ret;
bool t=opt_minify; bool t=opt_minify;
@ -273,16 +266,16 @@ std::vector<std::string> arglist_t::strargs(uint32_t start)
return ret; return ret;
} }
std::string const& cmd_t::arg_string(uint32_t n) std::string const& cmd::arg_string(uint32_t n)
{ {
if(args!=nullptr && args->args.size()>n && args->args[n]->sa.size() == 1 && args->args[n]->sa[0]->type == _obj::subarg_string) if(args!=nullptr && args->args.size()>n && args->args[n]->sa.size() == 1 && args->args[n]->sa[0]->type == _obj::subarg_string)
return dynamic_cast<subarg_string_t*>(args->args[n]->sa[0])->val; return dynamic_cast<string_subarg*>(args->args[n]->sa[0])->val;
return cmd_t::empty_string; return cmd::empty_string;
} }
// subobject getters // subobject getters
block_t* condlist_t::first_block() block* condlist::first_block()
{ {
if(pls.size() > 0 && pls[0]->cmds.size() > 0) if(pls.size() > 0 && pls[0]->cmds.size() > 0)
return (pls[0]->cmds[0]); return (pls[0]->cmds[0]);
@ -290,40 +283,40 @@ block_t* condlist_t::first_block()
return nullptr; return nullptr;
} }
cmd_t* condlist_t::first_cmd() cmd* condlist::first_cmd()
{ {
if(pls.size() > 0 && pls[0]->cmds.size() > 0 && pls[0]->cmds[0]->type == _obj::block_cmd) if(pls.size() > 0 && pls[0]->cmds.size() > 0 && pls[0]->cmds[0]->type == _obj::block_cmd)
return dynamic_cast<cmd_t*>(pls[0]->cmds[0]); return dynamic_cast<cmd*>(pls[0]->cmds[0]);
else else
return nullptr; return nullptr;
} }
cmd_t* brace_t::single_cmd() cmd* brace::single_cmd()
{ {
if( lst->cls.size() == 1 && // only one condlist if( lst->cls.size() == 1 && // only one condlist
lst->cls[0]->pls.size() == 1 && // only one pipeline lst->cls[0]->pls.size() == 1 && // only one pipeline
lst->cls[0]->pls[0]->cmds.size() == 1 && // only one block lst->cls[0]->pls[0]->cmds.size() == 1 && // only one block
lst->cls[0]->pls[0]->cmds[0]->type == _obj::block_cmd) // block is a command lst->cls[0]->pls[0]->cmds[0]->type == _obj::block_cmd) // block is a command
return dynamic_cast<cmd_t*>(lst->cls[0]->pls[0]->cmds[0]); // return command return dynamic_cast<cmd*>(lst->cls[0]->pls[0]->cmds[0]); // return command
return nullptr; return nullptr;
} }
cmd_t* subshell_t::single_cmd() cmd* subshell::single_cmd()
{ {
if( lst->cls.size() == 1 && // only one condlist if( lst->cls.size() == 1 && // only one condlist
lst->cls[0]->pls.size() == 1 && // only one pipeline lst->cls[0]->pls.size() == 1 && // only one pipeline
lst->cls[0]->pls[0]->cmds.size() == 1 && // only one block lst->cls[0]->pls[0]->cmds.size() == 1 && // only one block
lst->cls[0]->pls[0]->cmds[0]->type == _obj::block_cmd) // block is a command lst->cls[0]->pls[0]->cmds[0]->type == _obj::block_cmd) // block is a command
return dynamic_cast<cmd_t*>(lst->cls[0]->pls[0]->cmds[0]); // return command return dynamic_cast<cmd*>(lst->cls[0]->pls[0]->cmds[0]); // return command
return nullptr; return nullptr;
} }
cmd_t* block_t::single_cmd() cmd* block::single_cmd()
{ {
if(this->type == _obj::block_subshell) if(this->type == _obj::block_subshell)
return dynamic_cast<subshell_t*>(this)->single_cmd(); return dynamic_cast<subshell*>(this)->single_cmd();
if(this->type == _obj::block_brace) if(this->type == _obj::block_brace)
return dynamic_cast<brace_t*>(this)->single_cmd(); return dynamic_cast<brace*>(this)->single_cmd();
return nullptr; return nullptr;
} }
@ -331,15 +324,15 @@ cmd_t* block_t::single_cmd()
// simple setters // simple setters
void arg_t::set(std::string const& str) void arg::set(std::string const& str)
{ {
for(auto it: sa) for(auto it: sa)
delete it; delete it;
sa.resize(0); sa.resize(0);
sa.push_back(new subarg_string_t(str)); sa.push_back(new string_subarg(str));
} }
void condlist_t::prune_first_cmd() void condlist::prune_first_cmd()
{ {
if(pls.size()>0 && pls[0]->cmds.size()>0) if(pls.size()>0 && pls[0]->cmds.size()>0)
{ {
@ -350,40 +343,40 @@ void condlist_t::prune_first_cmd()
// add/extend // add/extend
void arg_t::insert(uint32_t i, std::string const& in) void arg::insert(uint32_t i, std::string const& in)
{ {
if(i>0 && i<=sa.size() && sa[i-1]->type == _obj::subarg_string) if(i>0 && i<=sa.size() && sa[i-1]->type == _obj::subarg_string)
{ {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(sa[i-1]); string_subarg* t = dynamic_cast<string_subarg*>(sa[i-1]);
t->val += in; t->val += in;
} }
else if(i<sa.size() && sa[i]->type == _obj::subarg_string) else if(i<sa.size() && sa[i]->type == _obj::subarg_string)
{ {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(sa[i]); string_subarg* t = dynamic_cast<string_subarg*>(sa[i]);
t->val = in + t->val; t->val = in + t->val;
} }
else else
sa.insert(sa.begin()+i, new subarg_string_t(in)); sa.insert(sa.begin()+i, new string_subarg(in));
} }
void arg_t::add(std::string const& in) void arg::add(std::string const& in)
{ {
this->insert(this->size(), in); this->insert(this->size(), in);
} }
void arg_t::insert(uint32_t i, subarg_t* val) void arg::insert(uint32_t i, subarg* val)
{ {
if(val->type == _obj::subarg_string) if(val->type == _obj::subarg_string)
{ {
subarg_string_t* tval = dynamic_cast<subarg_string_t*>(val); string_subarg* tval = dynamic_cast<string_subarg*>(val);
if(i>0 && i<=sa.size() && sa[i-1]->type == _obj::subarg_string) if(i>0 && i<=sa.size() && sa[i-1]->type == _obj::subarg_string)
{ {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(sa[i-1]); string_subarg* t = dynamic_cast<string_subarg*>(sa[i-1]);
t->val += tval->val; t->val += tval->val;
delete val; delete val;
} }
else if(i<sa.size() && sa[i]->type == _obj::subarg_string) else if(i<sa.size() && sa[i]->type == _obj::subarg_string)
{ {
subarg_string_t* t = dynamic_cast<subarg_string_t*>(sa[i]); string_subarg* t = dynamic_cast<string_subarg*>(sa[i]);
t->val = tval->val + t->val; t->val = tval->val + t->val;
delete val; delete val;
} }
@ -393,43 +386,43 @@ void arg_t::insert(uint32_t i, subarg_t* val)
else else
sa.insert(sa.begin()+i, val); sa.insert(sa.begin()+i, val);
} }
void arg_t::insert(uint32_t i, arg_t const& a) void arg::insert(uint32_t i, arg const& a)
{ {
sa.insert(sa.begin()+i, a.sa.begin(), a.sa.end()); sa.insert(sa.begin()+i, a.sa.begin(), a.sa.end());
} }
void arglist_t::insert(uint32_t i, arg_t* val) void arglist::insert(uint32_t i, arg* val)
{ {
args.insert(args.begin()+i, val); args.insert(args.begin()+i, val);
} }
void arglist_t::insert(uint32_t i, arglist_t const& lst) void arglist::insert(uint32_t i, arglist const& lst)
{ {
args.insert(args.begin()+i, lst.args.begin(), lst.args.end()); args.insert(args.begin()+i, lst.args.begin(), lst.args.end());
} }
void cmd_t::add(arg_t* in) void cmd::add(arg* in)
{ {
if(args==nullptr) if(args==nullptr)
args = new arglist_t; args = new arglist;
args->add(in); args->add(in);
} }
void condlist_t::add(pipeline_t* pl, bool or_op) void condlist::add(pipeline* pl, bool or_op)
{ {
if(pls.size() > 0) if(pls.size() > 0)
or_ops.push_back(or_op); or_ops.push_back(or_op);
pls.push_back(pl); pls.push_back(pl);
} }
void list_t::insert(uint32_t i, condlist_t* val) void list::insert(uint32_t i, condlist* val)
{ {
if(i<0) if(i<0)
cls.insert(cls.end(), val); cls.insert(cls.end(), val);
else else
cls.insert(cls.begin()+i, val); cls.insert(cls.begin()+i, val);
} }
void list_t::insert(uint32_t i, list_t const& lst) void list::insert(uint32_t i, list const& lst)
{ {
if(i<0) if(i<0)
cls.insert(cls.end(), lst.cls.begin(), lst.cls.end()); cls.insert(cls.end(), lst.cls.begin(), lst.cls.end());
@ -447,7 +440,7 @@ void shmain::concat(shmain* in)
// special modifiers // special modifiers
void condlist_t::negate() void condlist::negate()
{ {
// invert commands // invert commands
for(uint32_t i=0; i<pls.size(); i++) for(uint32_t i=0; i<pls.size(); i++)

View file

@ -1,47 +0,0 @@
#!/usr/bin/env bash
diff <(echo a) <(echo b)
write_to_file() { echo "$2" > "$1"; }
write_to_file >(grep bar) bar
wait $!
echo a &> /tmp/foo
echo b >& /tmp/bar
echo c &>> /tmp/foo
cat /tmp/bar /tmp/foo
rm /tmp/bar /tmp/foo
TOTO="foo
bar"
grep ar <<< ar$TOTO
declare -a A
A=("fo o" bar)
echo ${A[1]}
declare -A B
B[foo]=ta
B[bar]=tu
echo ${B[foo]}
echo ${B[bar]}
echo ${B[*]}
C=([foo]=bar [bar]=foo)
echo ${C[foo]}
echo ${C[bar]}
echo ${C[*]}
BAR=FOO
echo ${!BAR}
[[ $DEBUG == true ]] && echo debug
a=a
[[ $a = a && foo = fo* && bar =~ b.r || 2 < 3 ]]
for I in A B C ; do
echo "$I"
done > >(cat)

View file

@ -1,4 +0,0 @@
#!/bin/sh
echo $(( (2+1)*3 ))
echo $(( $((2+1))*3 ))

View file

@ -1,38 +0,0 @@
#!/bin/bash
TOTO=(toto tata)
TOTO[0]=titi
TOTO[1]+=tu
echo ${TOTO[0]}
echo ${TOTO[1]}
echo ${TOTO[*]}
TOTO+=(2)
echo $((TOTO[2]+1))
echo $((${TOTO[2]}+2))
declare -a TUTU
TUTU=(titi "tu tu")
echo ${TUTU[0]}
echo ${TUTU[1]}
echo ${TUTU[*]}
echo "${TUTU[*]}"
declare -A A
A[to]=ta
A[ti]=tu
echo ${A[to]}
echo ${A[ti]}
echo ${A[*]}
declare -A B
B=([to]=ta [ti]=tu)
echo ${B[to]}
echo ${B[ti]}
echo ${B[*]}
echo "${B[*]}"
toto=tata
C=()
C+=($toto)
echo ${C[@]}

View file

@ -1,7 +0,0 @@
#!/bin/sh
echo $(echo toto)
echo $(printf %s\\n tata)
echo `echo titi`
echo `printf '%s\\n' tutu`

View file

@ -1,7 +0,0 @@
#!/bin/sh
{ echo tata ; echo a; } | sed 's|a|toto|g'
echo a | { grep a && echo b; }
{ { echo tata ; } }

View file

@ -1,8 +0,0 @@
#!/usr/bin/bash
echo tot{a,o,i}
echo {1..10}
echo {0..10..2}
echo {1..10..2}
echo tot{a,o,i}{1..3}tata
echo :{{a..z},{A..Z}}

View file

@ -1,17 +0,0 @@
echo "$*" | case $1 in
to*) echo toto ;;
tata) echo wew tata ;;
a | b)
echo titi
;;
*)
cat ;;
esac
case foo in bar)echo a;;foo)echo b;esac
case foo in bar)echo a;;foo)echo b
esac
case far in foo) echo a;;bar)
esac

View file

@ -1,5 +0,0 @@
#!/bin/sh
echo toto#
echo toto#tata
echo toto #tata

View file

@ -1,22 +0,0 @@
while [ -z "$I" ]
do
case $U in
*)echo toto;I=y
esac
done
echo "$I"
case toto in
tutu) ;;
toto)
cat << EOF
toto
EOF
;;
tata)
esac
echo to 2>&1
echo to2 >&1
echo to$(echo 2) >&1

View file

@ -1,50 +0,0 @@
#!/bin/bash
readonly tutu titi=tata
echo "$tutu $titi"
diff <(echo a) <(echo b)
write_to_file() { echo "$2" > "$1"; }
write_to_file >(grep tutu) tutu
wait $!
echo a &> /tmp/toto
echo b >& /tmp/tata
echo c &>> /tmp/toto
cat /tmp/tata /tmp/toto
rm /tmp/tata /tmp/toto
TOTO="ta
to"
grep ta <<< toto$TOTO
TATA=ti
TATA+=tu
echo $TATA
[[ $DEBUG == true ]] && echo debug
[ $((RANDOM+RANDOM)) -gt 0 ]
echo randomstat: $?
a=a
[[ $a = a && foo = fo* && bar =~ b.r || 2 < 3 ]]
echo $?
N=1
TOTO=tatitu
echo "${TOTO:2}"
echo "${TOTO:$N:2}"
echo ${TOTO:-tutu}
echo ${TITI:-bar}
TATA=TOTO
echo ${!TATA}
for I in A B C ; do
echo "$I"
done 2>&1 > >(grep A)

View file

@ -1,78 +0,0 @@
#!/bin/sh
toto=tutu
tata=titi
echo "toto tata titi"
echo "toto"
echo "tata"titi
echo "ta ta"
echo "$toto"tata
echo "$toto"
echo $toto"tata"
echo $"toto"
toto="$toto"
toto="$toto"tata
echo "$toto"
toto="tata"$tata
echo "$toto"
toto=$toto"tata"
echo "$toto"
toto="$toto".tata
echo "$toto"
tata="ta ta"
echo "$tata"
echo "$"
echo \$
toto=tutu
tata=titi
echo 'toto tata titi'
echo 'toto'
echo 'tata'titi
echo 'ta ta'
echo '$toto'tata
echo '$toto'
echo $toto'tata'
echo $'toto'
toto='$toto'
toto='$toto'tata
echo '$toto'
toto='tata'$tata
echo '$toto'
toto=$toto'tata'
echo '$toto'
toto='$toto'.tata
echo '$toto'
tata='ta ta'
echo '$tata'
echo '$'
cat << EOF
"toto"
EOF
printf "%s\n" "" ""'' "toto"

View file

@ -1,12 +0,0 @@
#!/bin/bash
echo -n titi:
echo -e 'tata\n'
echo -E 'tutu\n'
echo -n tata tutu tete
toto="to to"
echo $toto
echo to $toto

View file

@ -1 +0,0 @@
{ ; }

View file

@ -1,12 +0,0 @@
#!/bin/bash
var[a
read var+=a
export var+=a
export var=()
[[ a = b ]] toto
echo >() <()
function toto-titi{ true; }

View file

@ -1,66 +0,0 @@
#!/bin/sh
read var=a
var+=a
var=(foo)
$((var~2))
${!var}
${~}
${#var-a}
`echo \`echo\` `
$(( (var) )
>& /dev/null
echo &> /dev/null
cat 2< file
cat <<< var
echo >
echo &| cat
echo |& cat
[[ a = b ]] foo
()
fct() abc
{ ; }
fct() { }
typeset var
var=val read var
case foo ; esac
case foo in aiae ; esac
case foo in ) ; esac
case foo in a) ; b) esac
for 2 in a ; do true ; done
for foo do ; do true ; done
for foo & ; do true ; done
for I in ; true ; done
while
do true ; done
while true ; do
done
if true ;then
fi
if
then true ; fi
if true ; then true ; else
fi
fct-foo() { true; }
function foo { true; }
{ foo; } bar

View file

@ -1,11 +0,0 @@
#!/bin/sh
toto() {
echo toto
}
tata () {
echo tata
}
toto

View file

@ -1,18 +0,0 @@
#!/bin/sh
__for_fct() {
for I in ; do
echo $I
done
}
for N
do
echo $N
done
for I in $(seq 1 10); do
echo "toto $I"
done
__for_fct toto tata

View file

@ -1,48 +0,0 @@
#!/bin/sh
cat << EOF
toto
tata
EOF
toto=toto
cat << EOF | grep toto
$toto
tata
EOF
cat << EOF
'
EOF
cat << EOF |
azjeha
kijejaze
ljksdjk
EOF
cut -c1
grep -q toto << EOF &&
toto
EOF
echo found toto
{ cat << EOF | grep toto; }
toto
tata
EOF
( cat << EOF | grep toto )
toto
tata
EOF
{ cat << EOF | grep toto && echo true; echo eyy; }
toto
tata
EOF
( cat << EOF | grep toto && echo true ; echo eyy )
toto
tata
EOF

View file

@ -1,11 +0,0 @@
#!/bin/sh
if [ -n "$DEBUG" ]
then
echo "set"
elif [ -n "$TOTO" ]
then
echo "toto lol"
else
echo "not set"
fi

View file

@ -1,9 +0,0 @@
#!/bin/sh
RAW="$(%include -f pipe.sh brace.sh)"
echo "$RAW"
{ %include -f pipe.sh; } | grep -q arch && echo "btw i use arch"
%include *.sh

View file

@ -1,15 +0,0 @@
#!/bin/sh
var="marijuana"
echo ${#var}
echo ${var-foo}
echo ${var+foo}
echo ${foo-foo}
echo ${foo+foo}
echo ${var#*a}
echo ${var##*a}
echo ${var%a*}
echo ${var%%a*}

View file

@ -1,8 +0,0 @@
#!/bin/sh
grep "^ID=" /etc/os-release | cut -d '=' -f2-
echo toto | #
grep to
echo '#toto' | grep '#toto'

View file

@ -1,3 +0,0 @@
#!/bin/sh
read -r prompt || echo $?

View file

@ -1,5 +0,0 @@
{ echo toto >&2; } 2>&1
{ echo tata; }>/dev/null
grep abc < test/redir.sh

View file

@ -1,9 +0,0 @@
#!/bin/sh
echo "a$(%resolve echo tata titi)b"
echo $(%resolve cut -d ' ' -f1 /proc/uptime)s
%resolve echo "TIME=$(cut -d ' ' -f1 /proc/uptime)s;echo This was compiled at \${TIME}s uptime"
FOO=$(%resolve echo bar) echo foo

View file

@ -1,10 +0,0 @@
TOTO=toto
(TOTO=tata; echo $TOTO; echo a) | sed 's|a|titi|g'
echo $TOTO
echo a | ( grep a && echo b )
echo ab | ( grep a )
pwd
(cd /)
pwd

View file

@ -1,31 +0,0 @@
#!/bin/sh
foo()
{
echo $FOO
}
TOTO=tata
TATA=titi
echo $TOTO
echo "$TOTO $TATA$TITI"
echo "${AYE-aye}"
export TUTU=ta
foo
FOO=bar foo
BAR=foo foo
ABCD=$(FOO=true foo)
echo $ABCD
nul=/dev/null
echo toto > "$nul"
somevar=val
echo $somevar
unset somevar
echo $somevar
cat << EOF
$TOTO
EOF

View file

@ -1,23 +0,0 @@
#!/bin/sh
I=0
while [ $I -lt 10 ]
do
I=$((I+1))
echo "$I"
done
I=0
until [ $I -eq 10 ]
do
I=$((I+1))
echo "$I"
done
I=0
while
I=$((I+1))
echo "$I"
[ $I -lt 10 ]
do true
done