Compare commits
No commits in common. "master" and "v1.2.0" have entirely different histories.
56 changed files with 1015 additions and 3213 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -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_*
|
||||||
|
|
|
||||||
7
Makefile
7
Makefile
|
|
@ -87,10 +87,3 @@ clean:
|
||||||
|
|
||||||
clear:
|
clear:
|
||||||
rm $(BINDIR)/$(NAME)
|
rm $(BINDIR)/$(NAME)
|
||||||
|
|
||||||
install:
|
|
||||||
cp lxsh /usr/local/bin
|
|
||||||
cp completion/lxsh.bash /etc/bash_completion.d
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm /usr/local/bin/lxsh /etc/bash_completion.d/lxsh.bash
|
|
||||||
|
|
|
||||||
35
README.md
35
README.md
|
|
@ -14,14 +14,14 @@ wget -qO- https://zpkg.zawz.net/install.sh | sh
|
||||||
zpkg install lxsh
|
zpkg install lxsh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Binary amd64
|
### Binary
|
||||||
|
|
||||||
Download the `lxsh-linux-amd64.tar.gz` archive, extract it,
|
Download the `lxsh.tar.gz` archive, extract it,
|
||||||
and move the `lxsh` binary in a PATH folder (`/usr/local/bin` is the recommended).
|
and move the `lxsh` binary in a PATH folder (`/usr/local/bin` is the recommended).
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
wget https://github.com/zawwz/lxsh/releases/download/v1.3.0/lxsh-linux-amd64.tar.gz
|
wget https://github.com/zawwz/lxsh/releases/download/v1.2.0/lxsh-linux-amd64.tar.gz
|
||||||
tar -xvf lxsh-linux-amd64.tar.gz
|
tar -xvf lxsh.tar.gz
|
||||||
sudo mv lxsh /usr/local/bin
|
sudo mv lxsh /usr/local/bin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -45,22 +45,6 @@ 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
|
|
||||||
|
|
||||||
#### Behaviors of the minify option
|
|
||||||
|
|
||||||
- removes any unnecessary separator character between arguments/commands
|
|
||||||
- removes `;;` from the last value in a case
|
|
||||||
- removes unnecessary quotes on arguments
|
|
||||||
- transforms unnecessary manipulations (e.g. `${VAR}`) into simple variable call
|
|
||||||
- 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
|
|
||||||
removal of an unnecessary manipulation will not be made if the following character
|
|
||||||
could expand the variable name
|
|
||||||
|
|
||||||
### Further minifying
|
### Further minifying
|
||||||
|
|
||||||
The script can be further minified by altering code elements.
|
The script can be further minified by altering code elements.
|
||||||
|
|
@ -72,6 +56,8 @@ use `--exclude-var` to exclude variables from being minified (for example enviro
|
||||||
Function names can be minified with `--minify-fct`,
|
Function names can be minified with `--minify-fct`,
|
||||||
use `--exclude-fct` to exclude functions from being minified.
|
use `--exclude-fct` to exclude functions from being minified.
|
||||||
|
|
||||||
|
Unnecessary quotes can be removed with `--minify-quotes`.
|
||||||
|
|
||||||
Unused functions and variables can be removed with `--remove-unused`.
|
Unused functions and variables can be removed with `--remove-unused`.
|
||||||
|
|
||||||
Use `-M` to enable all of these minifying features (you still have to specify `--exclude` options when needed)
|
Use `-M` to enable all of these minifying features (you still have to specify `--exclude` options when needed)
|
||||||
|
|
@ -87,9 +73,6 @@ The following bash features can be debashified:
|
||||||
- `[[ ]]` conditions
|
- `[[ ]]` conditions
|
||||||
- indexed arrays and associative arrays (+ their `declare` and `typeset` definitions)
|
- indexed arrays and associative arrays (+ their `declare` and `typeset` definitions)
|
||||||
- `$RANDOM`
|
- `$RANDOM`
|
||||||
- substring variable manipulation (`${VAR:N:M}`)
|
|
||||||
- variable substitution (`${!VAR}`)
|
|
||||||
- search replace manipulation (`${VAR/s/a/b}` )
|
|
||||||
|
|
||||||
### Advantages
|
### Advantages
|
||||||
|
|
||||||
|
|
@ -139,10 +122,6 @@ these features will continue working with undesired behavior.
|
||||||
|
|
||||||
Array argument with `[@]` does not expand into the desired multiple arguments.
|
Array argument with `[@]` does not expand into the desired multiple arguments.
|
||||||
|
|
||||||
#### Substring manipulation
|
|
||||||
|
|
||||||
Debashifying a substring manipulation on a variable containing a newline will not work correctly
|
|
||||||
|
|
||||||
## Extension commands
|
## Extension commands
|
||||||
|
|
||||||
If you use the `#!/usr/bin/lxsh` shebang, you can use special lxsh-defined commands.
|
If you use the `#!/usr/bin/lxsh` shebang, you can use special lxsh-defined commands.
|
||||||
|
|
@ -178,6 +157,8 @@ Directly execute an extended lxsh script with either
|
||||||
> Direct execution introduces direct dependency on lxsh and code parsing overhead,
|
> Direct execution introduces direct dependency on lxsh and code parsing overhead,
|
||||||
> therefore it should be avoided in production environments.
|
> therefore it should be avoided in production environments.
|
||||||
|
|
||||||
|
> stdin is known to not work properly on direct execution as of now
|
||||||
|
|
||||||
### Variable/Function/command listing
|
### Variable/Function/command listing
|
||||||
|
|
||||||
You can list all calls of variables, functions or commands with `--list-*` options
|
You can list all calls of variables, functions or commands with `--list-*` options
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
#/usr/bin/env bash
|
|
||||||
|
|
||||||
complete -F _longopt lxsh
|
|
||||||
|
|
@ -2,22 +2,17 @@
|
||||||
#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);
|
|
||||||
|
|
||||||
|
bool delete_unused_fct(_obj* in, std::regex const& exclude);
|
||||||
|
bool delete_unused_var(_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);
|
||||||
|
|
||||||
void minify_generic(_obj* in);
|
void minify_quotes(_obj* in);
|
||||||
|
|
||||||
#endif //MINIFY_HPP
|
#endif //MINIFY_HPP
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,11 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#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;#()&|=\"'\\{}"
|
||||||
|
|
@ -19,22 +18,19 @@
|
||||||
#define CONTROL_END "#)"
|
#define CONTROL_END "#)"
|
||||||
#define PIPELINE_END "\n;#()&"
|
#define PIPELINE_END "\n;#()&"
|
||||||
#define ARGLIST_END "\n;#()&|"
|
#define ARGLIST_END "\n;#()&|"
|
||||||
|
#define SPECIAL_TOKENS "\n;#()&|"
|
||||||
#define ALL_TOKENS "\n;#()&|{}"
|
#define ALL_TOKENS "\n;#()&|{}"
|
||||||
|
|
||||||
#define ARITHMETIC_OPERATOR_END " \t\n$)"
|
|
||||||
|
|
||||||
#define SPECIAL_VARS "!#*@$?"
|
#define SPECIAL_VARS "!#*@$?"
|
||||||
|
|
||||||
// bash specific
|
// bash specific
|
||||||
#define ARRAY_ARG_END " \t\n;#()&|<>]"
|
#define ARRAY_ARG_END " \t\n;#()&|<>]"
|
||||||
// optimizations
|
|
||||||
#define ARG_OPTIMIZE_NULL "$\\`"
|
// macros
|
||||||
#define ARG_OPTIMIZE_MANIP "$\\`}"
|
// #define PARSE_ERROR_I(str, ctx, i) format_error(str, ctx.filename, ctx.data, i)
|
||||||
#define ARG_OPTIMIZE_DEFARR "$\\`)"
|
// #define PARSE_ERROR(str, ctx) format_error(str, ctx.filename, ctx.data, ctx.i)
|
||||||
#define ARG_OPTIMIZE_BASHTEST "$\\`] \t\n"
|
// #define PARSE_ERROR_I(str, ctx, i) { printFormatError(format_error(str, ctx.filename, ctx.data, i)); ctx.has_errored=true; }
|
||||||
#define ARG_OPTIMIZE_ARG "$\\` \t\n;()&|<>\"'"
|
// #define PARSE_ERROR(str, ctx) { printFormatError(format_error(str, ctx.filename, ctx.data, ctx.i)); ctx.has_errored=true; }
|
||||||
#define ARG_OPTIMIZE_ARRAY "$\\`\t\n&|}[]\"'"
|
|
||||||
#define ARG_OPTIMIZE_ALL "$\\` \t\n;#()&|<>}]\"'"
|
|
||||||
|
|
||||||
// structs
|
// structs
|
||||||
|
|
||||||
|
|
@ -46,9 +42,9 @@ struct list_parse_options {
|
||||||
};
|
};
|
||||||
|
|
||||||
// globals
|
// globals
|
||||||
extern const std::set<std::string> all_reserved_words;
|
|
||||||
extern const std::set<std::string> posix_cmdvar;
|
extern const std::vector<std::string> posix_cmdvar;
|
||||||
extern const std::set<std::string> bash_cmdvar;
|
extern const std::vector<std::string> bash_cmdvar;
|
||||||
|
|
||||||
std::string import_file(std::string const& path);
|
std::string import_file(std::string const& path);
|
||||||
|
|
||||||
|
|
@ -88,41 +84,37 @@ uint32_t skip_unread(const char* in, uint32_t size, uint32_t start);
|
||||||
inline uint32_t skip_unread(parse_context const& ct) {
|
inline uint32_t skip_unread(parse_context const& ct) {
|
||||||
return skip_unread(ct.data, ct.size, ct.i);
|
return skip_unread(ct.data, ct.size, ct.i);
|
||||||
}
|
}
|
||||||
uint32_t skip_unread_noline(const char* in, uint32_t size, uint32_t start);
|
|
||||||
inline uint32_t skip_unread_noline(parse_context const& ct) {
|
|
||||||
return skip_unread_noline(ct.data, ct.size, ct.i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// heredocument
|
|
||||||
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=SPECIAL_TOKENS, bool doquote=true);
|
||||||
// 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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -29,12 +29,9 @@ extern set_t m_excluded_var, m_excluded_fct, m_excluded_cmd;
|
||||||
|
|
||||||
extern bool b_gotvar, b_gotfct, b_gotcmd;
|
extern bool b_gotvar, b_gotfct, b_gotcmd;
|
||||||
|
|
||||||
// tools
|
|
||||||
countmap_t combine_maps(countmap_t const& a, countmap_t const& b);
|
|
||||||
countmap_t combine_common(countmap_t const& a, countmap_t const& b);
|
|
||||||
|
|
||||||
/** map get functions (optimizations) **/
|
/** map get functions (optimizations) **/
|
||||||
|
|
||||||
|
|
||||||
// rescans
|
// rescans
|
||||||
void require_rescan_all();
|
void require_rescan_all();
|
||||||
void require_rescan_var();
|
void require_rescan_var();
|
||||||
|
|
@ -45,13 +42,9 @@ void require_rescan_cmd();
|
||||||
void varmap_get(_obj* in, std::regex const& exclude);
|
void varmap_get(_obj* in, std::regex const& exclude);
|
||||||
void fctmap_get(_obj* in, std::regex const& exclude);
|
void fctmap_get(_obj* in, std::regex const& exclude);
|
||||||
void cmdmap_get(_obj* in, std::regex const& exclude);
|
void cmdmap_get(_obj* in, std::regex const& exclude);
|
||||||
void fctcmdmap_get(_obj* in, std::regex const& exclude_fct, std::regex const& exclude_cmd);
|
|
||||||
void allmaps_get(_obj* in, std::regex const& exclude_var, std::regex const& exclude_fct, std::regex const& exclude_cmd);
|
|
||||||
|
|
||||||
/** util functions **/
|
/** util functions **/
|
||||||
#ifdef DEBUG_MODE
|
|
||||||
std::string gen_json_struc(_obj* in);
|
std::string gen_json_struc(_obj* in);
|
||||||
#endif
|
|
||||||
|
|
||||||
// gen regexes
|
// gen regexes
|
||||||
std::regex var_exclude_regex(std::string const& in, bool include_reserved);
|
std::regex var_exclude_regex(std::string const& in, bool include_reserved);
|
||||||
|
|
@ -60,7 +53,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);
|
||||||
|
|
@ -71,23 +64,17 @@ void list_fcts(_obj* in, std::regex const& exclude);
|
||||||
void list_cmds(_obj* in, std::regex const& exclude);
|
void list_cmds(_obj* in, std::regex const& exclude);
|
||||||
|
|
||||||
// recursives
|
// recursives
|
||||||
bool r_has_env_set(_obj* in, bool* result);
|
|
||||||
bool r_get_unsets(_obj* in, set_t* unsets);
|
bool r_get_unsets(_obj* in, set_t* unsets);
|
||||||
bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap);
|
bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap);
|
||||||
bool r_get_cmd(_obj* in, countmap_t* all_cmds);
|
bool r_get_cmd(_obj* in, countmap_t* all_cmds);
|
||||||
bool r_get_fct(_obj* in, countmap_t* fct_map);
|
bool r_get_fct(_obj* in, countmap_t* fct_map);
|
||||||
bool r_get_fctcmd(_obj* in, countmap_t* all_cmds, countmap_t* fct_map);
|
|
||||||
bool r_get_all(_obj* in, countmap_t* defmap, countmap_t* callmap, countmap_t* all_cmds, countmap_t* fct_map);
|
|
||||||
bool r_delete_fct(_obj* in, set_t* fcts);
|
bool r_delete_fct(_obj* in, set_t* fcts);
|
||||||
bool r_delete_var(_obj* in, set_t* vars);
|
bool r_delete_var(_obj* in, set_t* vars);
|
||||||
bool r_delete_varfct(_obj* in, set_t* vars, set_t* fcts);
|
|
||||||
bool r_do_string_processor(_obj* in);
|
|
||||||
|
|
||||||
/** Processing **/
|
/** Processing **/
|
||||||
|
|
||||||
std::set<std::string> find_lxsh_commands(shmain* sh);
|
std::set<std::string> find_lxsh_commands(shmain* sh);
|
||||||
void add_unset_variables(shmain* sh, std::regex const& exclude);
|
void add_unset_variables(shmain* sh, std::regex const& exclude);
|
||||||
bool has_env_set(_obj* in);
|
|
||||||
|
|
||||||
void string_processors(_obj* in);
|
void string_processors(_obj* in);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,58 +19,67 @@ 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...);
|
|
||||||
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 +89,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 +109,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,18 +119,13 @@ 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)
|
||||||
{
|
{
|
||||||
recurse(fct, it.first, args...);
|
recurse(fct, it.first, args...);
|
||||||
recurse(fct, it.second, args...);
|
recurse(fct, it.second, args...);
|
||||||
}
|
}
|
||||||
for(auto it: t->cmd_var_assigns)
|
|
||||||
{
|
|
||||||
recurse(fct, it.first, args...);
|
|
||||||
recurse(fct, it.second, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto it: t->redirs)
|
for(auto it: t->redirs)
|
||||||
recurse(fct, it, args...);
|
recurse(fct, it, args...);
|
||||||
|
|
@ -130,7 +134,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 +154,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 +173,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 +188,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 +201,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 +253,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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,22 +350,27 @@ 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;
|
||||||
delete it.second;
|
delete it.second;
|
||||||
}
|
}
|
||||||
for(auto it: cmd_var_assigns) {
|
|
||||||
delete it.first;
|
|
||||||
delete it.second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::string empty_string;
|
static const std::string empty_string;
|
||||||
|
|
@ -375,36 +379,31 @@ 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
|
|
||||||
std::vector<std::pair<variable_t*,arg_t*>> 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
|
arglist* args;
|
||||||
bool has_var_assign();
|
|
||||||
|
|
||||||
arglist_t* 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 +412,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 +481,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,48 +501,46 @@ 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) { type=_obj::block_for; var=in; iter=args; ops=lst; }
|
||||||
~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;
|
|
||||||
|
|
||||||
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 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 +548,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);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,43 +4,34 @@
|
||||||
#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<std::string> const& args);
|
||||||
cmd_t* make_cmd(std::vector<std::string> const& args);
|
cmd* make_cmd(std::vector<arg*> const& args);
|
||||||
cmd_t* make_cmd(std::vector<arg_t*> const& args);
|
cmd* make_cmd(std::string const& in);
|
||||||
cmd_t* 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);
|
|
||||||
inline cmd_t* make_printf_variable(std::string const& name) {
|
|
||||||
return make_printf(new arg_t(new subarg_variable_t(new variable_t(name))));
|
|
||||||
}
|
|
||||||
|
|
||||||
arithmetic_t* make_arithmetic(arg_t* a);
|
|
||||||
arithmetic_t* make_arithmetic(arg_t* arg1, std::string op, arg_t* 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
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ inline bool is_dev_file(std::string const& filename) { return filename.substr(0,
|
||||||
|
|
||||||
std::string indent(int n);
|
std::string indent(int n);
|
||||||
|
|
||||||
|
bool is_among(std::string const& in, std::vector<std::string> const& values);
|
||||||
|
|
||||||
std::vector<std::string> split(std::string const& in, const char* splitters);
|
std::vector<std::string> split(std::string const& in, const char* splitters);
|
||||||
std::vector<std::string> split(std::string const& in, char c);
|
std::vector<std::string> split(std::string const& in, char c);
|
||||||
|
|
||||||
|
|
@ -126,17 +128,6 @@ void concat_sets(std::set<T>& a, std::set<T> const& b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void exclude_sets(std::set<T>& a, std::set<T> const& b)
|
|
||||||
{
|
|
||||||
for(auto it: b)
|
|
||||||
{
|
|
||||||
auto t = a.find(it);
|
|
||||||
if(t != a.end())
|
|
||||||
a.erase(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
bool is_in_vector(T el, std::vector<T> vec)
|
bool is_in_vector(T el, std::vector<T> vec)
|
||||||
{
|
{
|
||||||
|
|
@ -146,12 +137,6 @@ bool is_in_vector(T el, std::vector<T> vec)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
bool is_in_set(T el, std::set<T> ss)
|
|
||||||
{
|
|
||||||
return ss.find(el) != ss.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<std::string> prune_matching(std::set<std::string>& in, std::regex re);
|
std::set<std::string> prune_matching(std::set<std::string>& in, std::regex re);
|
||||||
|
|
||||||
std::string delete_brackets(std::string const& in);
|
std::string delete_brackets(std::string const& in);
|
||||||
|
|
@ -161,7 +146,6 @@ std::string concatargs(std::vector<std::string> const& args);
|
||||||
int _exec(std::string const& bin, std::vector<std::string> const& args);
|
int _exec(std::string const& bin, std::vector<std::string> const& args);
|
||||||
|
|
||||||
std::string stringReplace(std::string subject, const std::string& search, const std::string& replace);
|
std::string stringReplace(std::string subject, const std::string& search, const std::string& replace);
|
||||||
std::string escape_chars(std::string subject, const char* chars);
|
|
||||||
|
|
||||||
void printFormatError(format_error const& e, bool print_line=true);
|
void printFormatError(format_error const& e, bool print_line=true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.2.0"
|
||||||
|
|
||||||
#endif //VERSION_H
|
#endif //VERSION_H
|
||||||
|
|
|
||||||
233
run-tests.sh
233
run-tests.sh
|
|
@ -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
|
|
||||||
|
|
@ -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
38
src/exec.cpp
38
src/exec.cpp
|
|
@ -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)
|
||||||
|
|
@ -194,12 +194,15 @@ void parse_exec(FILE* fd, parse_context ctx)
|
||||||
pid_t forkexec(const char* bin, char *const args[])
|
pid_t forkexec(const char* bin, char *const args[])
|
||||||
{
|
{
|
||||||
pid_t child_pid;
|
pid_t child_pid;
|
||||||
|
// int tfd = dup(STDIN_FILENO);
|
||||||
|
// std::cout << tfd << std::endl;
|
||||||
if((child_pid = vfork()) == -1)
|
if((child_pid = vfork()) == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("fork() failed");
|
throw std::runtime_error("fork() failed");
|
||||||
}
|
}
|
||||||
if (child_pid == 0) // child process
|
if (child_pid == 0) // child process
|
||||||
{
|
{
|
||||||
|
setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh
|
||||||
execv(bin, args);
|
execv(bin, args);
|
||||||
throw std::runtime_error("execv() failed");
|
throw std::runtime_error("execv() failed");
|
||||||
}
|
}
|
||||||
|
|
@ -236,18 +239,17 @@ 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);
|
||||||
|
|
||||||
|
for(uint32_t i=0; i<strargs.size(); i++)
|
||||||
|
runargs.push_back((char*) strargs[i].c_str());
|
||||||
|
runargs.push_back((char*) fifopath.c_str());
|
||||||
|
for(uint32_t i=0; i<args.size(); i++)
|
||||||
|
runargs.push_back((char*) args[i].c_str());
|
||||||
|
runargs.push_back(NULL);
|
||||||
|
|
||||||
pid_t pid=0;
|
pid_t pid=0;
|
||||||
FILE* ffd=0;
|
FILE* ffd=0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
for(uint32_t i=0; i<strargs.size(); i++)
|
|
||||||
runargs.push_back((char*) strargs[i].c_str());
|
|
||||||
runargs.push_back((char*) fifopath.c_str());
|
|
||||||
for(uint32_t i=0; i<args.size(); i++)
|
|
||||||
runargs.push_back((char*) args[i].c_str());
|
|
||||||
runargs.push_back(NULL);
|
|
||||||
|
|
||||||
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 +263,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
121
src/generate.cpp
121
src/generate.cpp
|
|
@ -6,9 +6,6 @@
|
||||||
#include "options.hpp"
|
#include "options.hpp"
|
||||||
#include "parse.hpp"
|
#include "parse.hpp"
|
||||||
|
|
||||||
// global
|
|
||||||
bool prev_is_heredoc=false;
|
|
||||||
|
|
||||||
bool is_sub_special_cmd(std::string in)
|
bool is_sub_special_cmd(std::string in)
|
||||||
{
|
{
|
||||||
return in == "%include_sub" || in == "%resolve_sub";
|
return in == "%include_sub" || in == "%resolve_sub";
|
||||||
|
|
@ -22,7 +19,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 +29,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 +44,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 +53,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 +63,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)
|
||||||
|
|
@ -85,7 +78,6 @@ std::string condlist_t::generate(int ind)
|
||||||
ret += opt_minify ? "&&" : " && ";
|
ret += opt_minify ? "&&" : " && ";
|
||||||
ret += pls[i+1]->generate(ind, &ctx);
|
ret += pls[i+1]->generate(ind, &ctx);
|
||||||
}
|
}
|
||||||
prev_is_heredoc=false;
|
|
||||||
if(ret=="")
|
if(ret=="")
|
||||||
return "";
|
return "";
|
||||||
if(ctx.here_document != nullptr)
|
if(ctx.here_document != nullptr)
|
||||||
|
|
@ -95,7 +87,6 @@ std::string condlist_t::generate(int ind)
|
||||||
ret += '\n';
|
ret += '\n';
|
||||||
ret += ctx.here_document->generate(0);
|
ret += ctx.here_document->generate(0);
|
||||||
ret += '\n';
|
ret += '\n';
|
||||||
prev_is_heredoc=true;
|
|
||||||
}
|
}
|
||||||
else if(parallel)
|
else if(parallel)
|
||||||
{
|
{
|
||||||
|
|
@ -106,47 +97,42 @@ 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)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
std::string next;
|
|
||||||
for(uint32_t i=0; i<cls.size(); i++)
|
for(uint32_t i=0; i<cls.size(); i++)
|
||||||
{
|
{
|
||||||
if(first_indent)
|
if(first_indent)
|
||||||
{
|
{
|
||||||
next = indented(cls[i]->generate(ind), ind);
|
ret += indented(cls[i]->generate(ind), ind);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
first_indent=true;
|
first_indent=true;
|
||||||
next = cls[i]->generate(ind);
|
ret += cls[i]->generate(ind);
|
||||||
}
|
}
|
||||||
if(ret[ret.size()-1] == '&' && next.size()>0 && is_in(next[0], "<>"))
|
|
||||||
ret += '\n';
|
|
||||||
ret += next;
|
|
||||||
}
|
}
|
||||||
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 +154,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,16 +188,13 @@ 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;
|
||||||
|
|
||||||
ret += "for "+var->generate(ind);
|
ret += "for "+var->generate(ind);
|
||||||
if(in_val) {
|
if(iter != nullptr)
|
||||||
ret += " in";
|
ret += " in " + iter->generate(ind);
|
||||||
if(iter != nullptr)
|
|
||||||
ret += " " + iter->generate(ind);
|
|
||||||
}
|
|
||||||
ret += '\n';
|
ret += '\n';
|
||||||
ret += indented("do\n", ind);
|
ret += indented("do\n", ind);
|
||||||
ret += ops->generate(ind+1);
|
ret += ops->generate(ind+1);
|
||||||
|
|
@ -223,7 +206,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 +226,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 +259,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 +271,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 +286,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";
|
||||||
|
|
@ -321,19 +304,17 @@ std::string case_t::generate(int ind, generate_context* ctx)
|
||||||
// commands
|
// commands
|
||||||
ret += cs.second->generate(ind+1);
|
ret += cs.second->generate(ind+1);
|
||||||
// end of case: ;;
|
// end of case: ;;
|
||||||
if(opt_minify && !prev_is_heredoc && ret[ret.size()-1] == '\n') // ;; can be right after command
|
if(opt_minify && ret[ret.size()-1] == '\n') // ;; can be right after command
|
||||||
ret.pop_back();
|
ret.pop_back();
|
||||||
ret += indented(";;", ind+1);
|
ret += indented(";;", ind+1);
|
||||||
if(!opt_minify)
|
if(!opt_minify)
|
||||||
ret+="\n";
|
ret+="\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace ;; from last case with \n
|
// replace ;; from last case with ;
|
||||||
if(this->cases.size()>0 && opt_minify)
|
if(this->cases.size()>0 && opt_minify)
|
||||||
{
|
{
|
||||||
ret.pop_back();
|
ret.pop_back();
|
||||||
ret.pop_back();
|
|
||||||
ret+='\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// close case
|
// close case
|
||||||
|
|
@ -344,28 +325,15 @@ 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;
|
||||||
|
|
||||||
bool has_args=false;
|
|
||||||
|
|
||||||
// pre-cmd var assigns
|
|
||||||
for(auto it: var_assigns)
|
|
||||||
{
|
|
||||||
has_args=true;
|
|
||||||
if(it.first != nullptr)
|
|
||||||
ret += it.first->generate(ind);
|
|
||||||
if(it.second != nullptr)
|
|
||||||
ret += it.second->generate(ind);
|
|
||||||
ret += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// is a varassign cmd
|
// is a varassign cmd
|
||||||
if(is_cmdvar)
|
if(is_cmdvar)
|
||||||
{
|
{
|
||||||
ret += args->generate(ind) + ' ';
|
ret += args->generate(ind) + ' ';
|
||||||
for(auto it: cmd_var_assigns)
|
for(auto it: var_assigns)
|
||||||
{
|
{
|
||||||
if(it.first != nullptr)
|
if(it.first != nullptr)
|
||||||
ret += it.first->generate(ind);
|
ret += it.first->generate(ind);
|
||||||
|
|
@ -377,10 +345,19 @@ std::string cmd_t::generate(int ind, generate_context* ctx)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pre-cmd var assigns
|
||||||
|
for(auto it: var_assigns)
|
||||||
|
{
|
||||||
|
if(it.first != nullptr)
|
||||||
|
ret += it.first->generate(ind);
|
||||||
|
if(it.second != nullptr)
|
||||||
|
ret += it.second->generate(ind);
|
||||||
|
ret += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
// cmd itself
|
// cmd itself
|
||||||
if(args!=nullptr && args->size()>0)
|
if(args!=nullptr && args->size()>0)
|
||||||
{
|
{
|
||||||
has_args=true;
|
|
||||||
// command
|
// command
|
||||||
ret += args->generate(ind);
|
ret += args->generate(ind);
|
||||||
// delete potential trailing space
|
// delete potential trailing space
|
||||||
|
|
@ -393,28 +370,18 @@ std::string cmd_t::generate(int ind, generate_context* ctx)
|
||||||
ret.pop_back();
|
ret.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string redirs = generate_redirs(ind, ret, ctx);
|
ret += generate_redirs(ind, ret, ctx);
|
||||||
if(!has_args)
|
|
||||||
redirs.erase(redirs.begin());
|
|
||||||
ret += redirs;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 +389,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 +402,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 +422,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 +433,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 +446,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)
|
||||||
|
|
|
||||||
75
src/main.cpp
75
src/main.cpp
|
|
@ -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,24 +94,9 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
first_run=false;
|
first_run=false;
|
||||||
// resolve shebang
|
// resolve shebang
|
||||||
if(options["lxsh"])
|
binshebang = basename(shebang);
|
||||||
{
|
shebang_is_bin = ( basename(argv[0]) == binshebang );
|
||||||
shebang_is_bin = true;
|
parse_bash = (options["debashify"] || binshebang == "bash" || binshebang == "lxsh");
|
||||||
parse_bash = true;
|
|
||||||
binshebang = basename(shebang);
|
|
||||||
shebang = "#!/usr/bin/env lxsh";
|
|
||||||
}
|
|
||||||
else if(options["bash"])
|
|
||||||
{
|
|
||||||
parse_bash=true;
|
|
||||||
shebang = "#!/usr/bin/env bash";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
binshebang = basename(shebang);
|
|
||||||
shebang_is_bin = ( basename(argv[0]) == binshebang );
|
|
||||||
parse_bash = (options["debashify"] || binshebang == "bash" || binshebang == "lxsh");
|
|
||||||
}
|
|
||||||
|
|
||||||
// detect if need execution
|
// detect if need execution
|
||||||
if(options['e'])
|
if(options['e'])
|
||||||
|
|
@ -138,16 +123,16 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
}
|
}
|
||||||
// parse
|
// parse
|
||||||
|
g_origin=file;
|
||||||
if(!add_include(file))
|
if(!add_include(file))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ctx.data=filecontents.data();
|
ctx.data=filecontents.data();
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
@ -155,8 +140,6 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
auto pp = parse_text(ctx);
|
auto pp = parse_text(ctx);
|
||||||
tsh = pp.first;
|
tsh = pp.first;
|
||||||
if(options["bash"])
|
|
||||||
tsh->shebang = "#!/usr/bin/env bash";
|
|
||||||
ctx = pp.second;
|
ctx = pp.second;
|
||||||
if(shebang_is_bin) // resolve lxsh shebang to sh
|
if(shebang_is_bin) // resolve lxsh shebang to sh
|
||||||
tsh->shebang="#!/bin/sh";
|
tsh->shebang="#!/bin/sh";
|
||||||
|
|
@ -188,6 +171,12 @@ int main(int argc, char* argv[])
|
||||||
list_fcts(sh, re_fct_exclude);
|
list_fcts(sh, re_fct_exclude);
|
||||||
else if(options["list-cmd"])
|
else if(options["list-cmd"])
|
||||||
list_cmds(sh, regex_null);
|
list_cmds(sh, regex_null);
|
||||||
|
#ifdef DEBUG_MODE
|
||||||
|
else if(options['J'])
|
||||||
|
{
|
||||||
|
std::cout << gen_json_struc(sh) << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// output
|
// output
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -203,46 +192,21 @@ 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);
|
string_processors(sh);
|
||||||
}
|
|
||||||
if(options['A']) {
|
|
||||||
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
|
|
||||||
allmaps_get(sh, re_var_exclude, re_fct_exclude, regex_null);
|
|
||||||
varmap = minify_var( sh, re_var_exclude );
|
|
||||||
fctmap = minify_fct( sh, re_fct_exclude );
|
|
||||||
}
|
|
||||||
else if(options["minify-var"]) {
|
|
||||||
varmap = minify_var( sh, re_var_exclude );
|
|
||||||
}
|
|
||||||
else if(options["minify-fct"]) {
|
|
||||||
fctmap = minify_fct( sh, re_fct_exclude );
|
|
||||||
}
|
}
|
||||||
|
if(options["minify-quotes"])
|
||||||
|
minify_quotes(sh);
|
||||||
|
if(options["minify-var"])
|
||||||
|
minify_var( sh, re_var_exclude );
|
||||||
|
if(options["minify-fct"])
|
||||||
|
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
|
|
||||||
if(options['J'])
|
|
||||||
{
|
|
||||||
std::cout << gen_json_struc(sh) << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(options['o']) // file output
|
if(options['o']) // file output
|
||||||
{
|
{
|
||||||
std::string destfile=options['o'];
|
std::string destfile=options['o'];
|
||||||
|
|
@ -283,6 +247,7 @@ int main(int argc, char* argv[])
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
return ERR_RUNTIME;
|
return ERR_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete sh;
|
delete sh;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
597
src/minify.cpp
597
src/minify.cpp
|
|
@ -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* escaped_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 = ∈
|
|
||||||
*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;
|
||||||
|
|
@ -91,7 +78,7 @@ uint32_t count_escape_chars(std::string const& in, bool doublequote)
|
||||||
{
|
{
|
||||||
if(doublequote && is_in(in[i], doublequote_escape_char))
|
if(doublequote && is_in(in[i], doublequote_escape_char))
|
||||||
r++;
|
r++;
|
||||||
else if(!doublequote && is_in(in[i], singlequote_escape_char))
|
else if(!doublequote && is_in(in[i], escaped_char))
|
||||||
r++;
|
r++;
|
||||||
else if(in[i] == '\n') // \n: can't remove quotes
|
else if(in[i] == '\n') // \n: can't remove quotes
|
||||||
return 2;
|
return 2;
|
||||||
|
|
@ -118,216 +105,117 @@ 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 == '_';
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_minify_quotes(arg_t* in)
|
|
||||||
{
|
|
||||||
auto t = in->sa.begin();
|
|
||||||
// global loop
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
uint32_t i=0;
|
|
||||||
// one iteration loop
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
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] == '"') )
|
|
||||||
{
|
|
||||||
if(val[i] == '\\')
|
|
||||||
i++;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
// if found: break and go to next step
|
|
||||||
if(i<val.size()) {
|
|
||||||
if(val[i] == '"')
|
|
||||||
doublequote=true;
|
|
||||||
strstart=&val;
|
|
||||||
quotestart=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)
|
|
||||||
{
|
|
||||||
while(i<val.size() && val[i] != '"')
|
|
||||||
{
|
|
||||||
if(val[i] == '\\') {
|
|
||||||
ce += count_escape_char(val, i++, doublequote, &escapestr, &escapepos);
|
|
||||||
}
|
|
||||||
ce += count_escape_char(val, i++, doublequote, &escapestr, &escapepos);
|
|
||||||
}
|
|
||||||
if(i>=val.size()) { // end before finding quote: continue looping
|
|
||||||
t++;
|
|
||||||
i=0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_minify_dollar(subarg_string_t* in)
|
|
||||||
{
|
{
|
||||||
std::string& val = in->val;
|
std::string& val = in->val;
|
||||||
for(uint32_t i=0; i<val.size(); i++) {
|
if(val.size() <= 1)
|
||||||
// skip singlequote strings
|
return;
|
||||||
if(val[i] == '\'') {
|
if(start_quoted) // don't handle start quoted for now
|
||||||
i++;
|
return;
|
||||||
while(val[i] != '\'')
|
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;
|
||||||
|
|
||||||
|
uint32_t i=0, j=0;
|
||||||
|
while( i < val.size() )
|
||||||
|
{
|
||||||
|
bool doublequote=false;
|
||||||
|
while(i<val.size() && !( val[i] == '\'' || val[i] == '"') )
|
||||||
|
{
|
||||||
|
if(val[i] == '\\')
|
||||||
i++;
|
i++;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
// has \$
|
if(i>=val.size()) // end before finding quote: exit
|
||||||
if(i+1<val.size() && val[i] == '\\' && val[i+1] == '$') {
|
return;
|
||||||
// char after $ is a varname
|
if(val[i] == '"')
|
||||||
if(i+2<val.size() && (is_varname(val[i+2]) || is_in(val[i+2], SPECIAL_VARS) || val[i+2] == '{') )
|
doublequote=true;
|
||||||
continue;
|
|
||||||
val.erase(i, 1);
|
j=i;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if(doublequote)
|
||||||
|
{
|
||||||
|
while(i<val.size() && val[i] != '"')
|
||||||
|
{
|
||||||
|
if(val[i] == '\\')
|
||||||
|
i++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if(i>=val.size()) // end before finding quote: exit
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while(i<val.size() && val[i] != '\'')
|
||||||
|
i++;
|
||||||
|
if(i>=val.size()) // end before finding quote: exit
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
uint32_t ce = count_escape_chars(val.substr(j+1, i-j-1), doublequote);
|
||||||
|
if(ce == 0)
|
||||||
|
{
|
||||||
|
val.erase(val.begin()+i);
|
||||||
|
val.erase(val.begin()+j);
|
||||||
|
}
|
||||||
|
else if(ce == 1) // only one char to escape: can save some space
|
||||||
|
{
|
||||||
|
val.erase(val.begin()+i);
|
||||||
|
val.erase(val.begin()+j);
|
||||||
|
uint32_t k;
|
||||||
|
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], escaped_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++)
|
||||||
}; break;
|
|
||||||
case _obj::subarg_string: {
|
|
||||||
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
|
|
||||||
redirect_t* t = dynamic_cast<redirect_t*>(in);
|
|
||||||
if(t->here_document != nullptr)
|
|
||||||
{
|
{
|
||||||
recurse(r_minify_useless_quotes, t->target);
|
if(t->sa[i]->type == _obj::subarg_string)
|
||||||
for(auto it: t->here_document->sa)
|
|
||||||
{
|
{
|
||||||
if(it->type!=_obj::subarg_string) {
|
string_subarg* ss = dynamic_cast<string_subarg*>(t->sa[i]);
|
||||||
recurse(r_minify_useless_quotes, it);
|
bool prev_is_var=false;
|
||||||
|
if(i>0 && t->sa[i-1]->type == _obj::subarg_variable)
|
||||||
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
// don't recurse on the rest
|
//if()
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
} break;
|
}; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -394,53 +282,47 @@ 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;
|
||||||
strmap_t varmap;
|
strmap_t varmap;
|
||||||
// get vars
|
// get vars
|
||||||
varmap_get(in, exclude);
|
varmap_get(in, exclude);
|
||||||
// concatenate excluded and reserved
|
|
||||||
concat_sets(excluded, m_excluded_var);
|
|
||||||
concat_sets(excluded, all_reserved_words);
|
|
||||||
// create mapping
|
// create mapping
|
||||||
varmap=gen_minimal_map(m_vars, excluded);
|
varmap=gen_minimal_map(m_vars, m_excluded_var);
|
||||||
// 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 allcmds, excluded, unsets;
|
||||||
strmap_t fctmap;
|
strmap_t fctmap;
|
||||||
// get fcts and cmds
|
// get fcts and cmds
|
||||||
fctcmdmap_get(in, exclude, regex_null);
|
fctmap_get(in, exclude);
|
||||||
|
cmdmap_get(in, regex_null);
|
||||||
recurse(r_get_unsets, in, &unsets);
|
recurse(r_get_unsets, in, &unsets);
|
||||||
// concatenate cmds, excluded and reserved
|
// concatenate cmds and excluded commands
|
||||||
excluded=map_to_set(m_cmds);
|
allcmds=map_to_set(m_cmds);
|
||||||
exclude_sets(excluded, map_to_set(m_fcts));
|
concat_sets(allcmds, m_excluded_fct);
|
||||||
concat_sets(excluded, m_excluded_fct);
|
concat_sets(allcmds, unsets);
|
||||||
concat_sets(excluded, unsets);
|
|
||||||
concat_sets(excluded, all_reserved_words);
|
|
||||||
// create mapping
|
// create mapping
|
||||||
m_fcts = combine_common(m_fcts, m_cmds);
|
fctmap=gen_minimal_map(m_fcts, allcmds);
|
||||||
fctmap=gen_minimal_map(m_fcts, excluded);
|
|
||||||
// perform replace
|
// perform replace
|
||||||
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)
|
||||||
{
|
{
|
||||||
set_t unused;
|
set_t unused;
|
||||||
// get fcts and cmds
|
// get fcts and cmds
|
||||||
fctcmdmap_get(in, exclude, regex_null);
|
fctmap_get(in, exclude);
|
||||||
|
cmdmap_get(in, regex_null);
|
||||||
// find unused fcts
|
// find unused fcts
|
||||||
for(auto it: m_fcts)
|
for(auto it: m_fcts)
|
||||||
{
|
{
|
||||||
|
|
@ -480,248 +362,13 @@ bool delete_unused_var(_obj* in, std::regex const& exclude)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool delete_unused_both(_obj* in, std::regex const& var_exclude, std::regex const& fct_exclude)
|
void minify_quotes(_obj* in)
|
||||||
{
|
{
|
||||||
set_t unused_var, unused_fct;
|
recurse(r_minify_useless_quotes, in);
|
||||||
// get all
|
|
||||||
allmaps_get(in, var_exclude, fct_exclude, regex_null);
|
|
||||||
// find unused
|
|
||||||
for(auto it: m_vardefs)
|
|
||||||
{
|
|
||||||
if(it.first!="" && m_varcalls.find(it.first) == m_varcalls.end())
|
|
||||||
unused_var.insert(it.first);
|
|
||||||
}
|
|
||||||
for(auto it: m_fcts)
|
|
||||||
{
|
|
||||||
if(m_cmds.find(it.first) == m_cmds.end())
|
|
||||||
unused_fct.insert(it.first);
|
|
||||||
}
|
|
||||||
if(unused_var.size()>0 || unused_fct.size()>0)
|
|
||||||
{
|
|
||||||
recurse(r_delete_varfct, in, &unused_var, &unused_fct);
|
|
||||||
require_rescan_all();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
while(delete_unused_both(in, var_exclude, fct_exclude));
|
while(delete_unused_fct(in, fct_exclude) || delete_unused_var(in, var_exclude));
|
||||||
// keep deleting until both no deletion
|
// keep deleting until both no function and no variables were deleted
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// minify ${var} to $var
|
|
||||||
bool r_minify_empty_manip(_obj* in)
|
|
||||||
{
|
|
||||||
switch(in->type)
|
|
||||||
{
|
|
||||||
case _obj::arg: {
|
|
||||||
arg_t* t = dynamic_cast<arg_t*>(in);
|
|
||||||
for(uint32_t i=0; i<t->sa.size(); i++)
|
|
||||||
{
|
|
||||||
if(t->sa[i]->type == _obj::subarg_variable)
|
|
||||||
{
|
|
||||||
// has to be a variable
|
|
||||||
subarg_variable_t* ss = dynamic_cast<subarg_variable_t*>(t->sa[i]);
|
|
||||||
if(ss->var->is_manip)
|
|
||||||
{
|
|
||||||
// if is a manip: possibility to skip it
|
|
||||||
if(ss->var->index != nullptr) // is a var bash array: skip
|
|
||||||
return true;
|
|
||||||
if(i+1<t->sa.size() && t->sa[i+1]->type == _obj::subarg_string)
|
|
||||||
{
|
|
||||||
// if next subarg is a string: check its first char
|
|
||||||
subarg_string_t* ss = dynamic_cast<subarg_string_t*>(t->sa[i+1]);
|
|
||||||
char c = ss->val[0];
|
|
||||||
// if its first would extend the var name: skip
|
|
||||||
if(is_alphanum(c) || c == '_')
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// if has no actual manipulation operation: set it to not manip
|
|
||||||
if(ss->var->manip == nullptr || ss->var->manip->sa.size() == 0)
|
|
||||||
ss->var->is_manip = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pipeline_t* do_one_minify_single_block(block_t* in)
|
|
||||||
{
|
|
||||||
pipeline_t* ret=nullptr;
|
|
||||||
list_t* l=nullptr;
|
|
||||||
if(in->type == _obj::block_brace)
|
|
||||||
l = dynamic_cast<brace_t*>(in)->lst;
|
|
||||||
else if(in->type == _obj::block_subshell)
|
|
||||||
l = dynamic_cast<subshell_t*>(in)->lst;
|
|
||||||
|
|
||||||
if(l == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// not a single pipeline: not applicable
|
|
||||||
if(l->cls.size() != 1 || l->cls[0]->pls.size() != 1)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
ret = l->cls[0]->pls[0];
|
|
||||||
|
|
||||||
// if is a subshell and has some env set: don't remove it
|
|
||||||
if(in->type == _obj::block_subshell && has_env_set(ret))
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool r_minify_single_block(_obj* in)
|
|
||||||
{
|
|
||||||
switch(in->type)
|
|
||||||
{
|
|
||||||
case _obj::pipeline: {
|
|
||||||
bool has_operated=false;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// loop operating on current
|
|
||||||
// (if has operated, current object has changed)
|
|
||||||
has_operated=false;
|
|
||||||
pipeline_t* t = dynamic_cast<pipeline_t*>(in);
|
|
||||||
for(uint32_t i=0; i<t->cmds.size(); i++)
|
|
||||||
{
|
|
||||||
pipeline_t* ret = do_one_minify_single_block(t->cmds[i]);
|
|
||||||
if(ret != nullptr) {
|
|
||||||
// concatenate redirects
|
|
||||||
block_t* firstb = ret->cmds[0];
|
|
||||||
block_t* lastb = ret->cmds[ret->cmds.size()-1];
|
|
||||||
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
|
|
||||||
t->cmds[i]->redirs.resize(0);
|
|
||||||
if(t->cmds[i]->type == _obj::block_brace)
|
|
||||||
dynamic_cast<brace_t*>(t->cmds[i])->lst->cls[0]->pls[0] = nullptr;
|
|
||||||
else if(t->cmds[i]->type == _obj::block_subshell)
|
|
||||||
dynamic_cast<subshell_t*>(t->cmds[i])->lst->cls[0]->pls[0] = nullptr;
|
|
||||||
|
|
||||||
// replace value
|
|
||||||
delete t->cmds[i];
|
|
||||||
t->cmds.erase(t->cmds.begin()+i);
|
|
||||||
for(auto it: ret->cmds) {
|
|
||||||
t->cmds.insert(t->cmds.begin()+i, it);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
has_operated=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(has_operated);
|
|
||||||
}; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
r_minify_empty_manip(in);
|
|
||||||
r_minify_single_block(in);
|
|
||||||
r_do_string_processor(in);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void minify_generic(_obj* 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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,26 +20,23 @@ 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"),
|
||||||
#endif
|
#endif
|
||||||
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-quotes --minify-var --minify-fct --remove-unused"),
|
||||||
ztd::option('A', "apply-map", true , "Apply var/fct minify map from given file", "file"),
|
ztd::option("minify-quotes", false, "Remove unnecessary quotes"),
|
||||||
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("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"),
|
||||||
ztd::option("\r [Variable processing]"),
|
ztd::option("\r [Variable processing]"),
|
||||||
ztd::option("exclude-var", true, "List of matching regex to ignore for variable processing, separated by spaces", "list"),
|
ztd::option("exclude-var", true, "List of matching regex to ignore for variable processing", "list"),
|
||||||
ztd::option("no-exclude-reserved",false, "Don't exclude reserved variables"),
|
ztd::option("no-exclude-reserved",false, "Don't exclude reserved variables"),
|
||||||
ztd::option("minify-var", false, "Minify variable names"),
|
ztd::option("minify-var", false, "Minify variable names"),
|
||||||
ztd::option("list-var", false, "List all variables set and invoked in the script"),
|
ztd::option("list-var", false, "List all variables set and invoked in the script"),
|
||||||
|
|
@ -47,7 +44,7 @@ ztd::option_set options( {
|
||||||
ztd::option("list-var-call", false, "List all variables invoked in the script"),
|
ztd::option("list-var-call", false, "List all variables invoked in the script"),
|
||||||
ztd::option("unset-var", false, "Add 'unset' to all variables at the start of the script to avoid environment interference"),
|
ztd::option("unset-var", false, "Add 'unset' to all variables at the start of the script to avoid environment interference"),
|
||||||
ztd::option("\r [Function processing]"),
|
ztd::option("\r [Function processing]"),
|
||||||
ztd::option("exclude-fct", true, "List of matching regex to ignore for function processing, separated by spaces", "list"),
|
ztd::option("exclude-fct", true, "List of matching regex to ignore for function processing", "list"),
|
||||||
ztd::option("minify-fct", false, "Minify function names"),
|
ztd::option("minify-fct", false, "Minify function names"),
|
||||||
ztd::option("list-fct", false, "List all functions defined in the script")
|
ztd::option("list-fct", false, "List all functions defined in the script")
|
||||||
} );
|
} );
|
||||||
|
|
@ -74,36 +71,30 @@ void get_opts()
|
||||||
options['m'].activated=true;
|
options['m'].activated=true;
|
||||||
options["minify-var"].activated=true;
|
options["minify-var"].activated=true;
|
||||||
options["minify-fct"].activated=true;
|
options["minify-fct"].activated=true;
|
||||||
|
options["minify-quotes"].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('e', false, "Escape double quotes"),
|
||||||
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 +127,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();
|
||||||
|
|
|
||||||
425
src/parse.cpp
425
src/parse.cpp
|
|
@ -14,14 +14,14 @@
|
||||||
// macro
|
// macro
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
const std::set<std::string> posix_cmdvar = { "export", "unset", "local", "read", "getopts" };
|
const std::vector<std::string> posix_cmdvar = { "export", "unset", "local", "read", "getopts" };
|
||||||
const std::set<std::string> bash_cmdvar = { "readonly", "declare", "typeset" };
|
const std::vector<std::string> bash_cmdvar = { "readonly", "declare", "typeset" };
|
||||||
|
|
||||||
const std::set<std::string> arithmetic_precedence_operators = { "!", "~", "+", "-" };
|
const std::vector<std::string> arithmetic_precedence_operators = { "!", "~", "+", "-" };
|
||||||
const std::set<std::string> arithmetic_operators = { "+", "-", "*", "/", "%", "+=", "-=", "*=", "/=", "=", "==", "!=", "&", "|", "^", "<<", ">>", "&&", "||" };
|
const std::vector<std::string> arithmetic_operators = { "+", "-", "*", "/", "+=", "-=", "*=", "/=", "=", "==", "!=", "&", "|", "^", "<<", ">>", "&&", "||" };
|
||||||
|
|
||||||
const std::set<std::string> all_reserved_words = { "if", "then", "else", "fi", "case", "esac", "for", "while", "do", "done", "{", "}" };
|
const std::vector<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::vector<std::string> out_reserved_words = { "then", "else", "fi", "esac", "do", "done", "}" };
|
||||||
|
|
||||||
// stuff
|
// stuff
|
||||||
|
|
||||||
|
|
@ -103,9 +103,11 @@ 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)
|
||||||
{
|
{
|
||||||
ctx.data = in.c_str();
|
if(in != "")
|
||||||
ctx.size = in.size();
|
{
|
||||||
|
ctx.data = in.c_str();
|
||||||
|
ctx.size = in.size();
|
||||||
|
}
|
||||||
if(filename != "")
|
if(filename != "")
|
||||||
ctx.filename = filename.c_str();
|
ctx.filename = filename.c_str();
|
||||||
if(bash)
|
if(bash)
|
||||||
|
|
@ -165,18 +167,6 @@ uint32_t skip_unread(const char* in, uint32_t size, uint32_t start)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t skip_unread_noline(const char* in, uint32_t size, uint32_t start)
|
|
||||||
{
|
|
||||||
uint32_t i=start;
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
i = skip_chars(in, size, i, SPACES);
|
|
||||||
if(in[i] != '#') // not a comment
|
|
||||||
return i;
|
|
||||||
i = skip_until(in, size, i, "\n"); //skip to endline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t word_eq(const char* word, const char* in, uint32_t size, uint32_t start, const char* end_set)
|
uint32_t word_eq(const char* word, const char* in, uint32_t size, uint32_t start, const char* end_set)
|
||||||
{
|
{
|
||||||
uint32_t i=start;
|
uint32_t i=start;
|
||||||
|
|
@ -205,9 +195,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,11 +215,11 @@ 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++;
|
||||||
auto pp=parse_arg(ctx, ARRAY_ARG_END, ARGLIST_END, true, ARG_OPTIMIZE_ARRAY);
|
auto pp=parse_arg(ctx, ARRAY_ARG_END);
|
||||||
ret->index=pp.first;
|
ret->index=pp.first;
|
||||||
ctx = pp.second;
|
ctx = pp.second;
|
||||||
if(ctx[ctx.i] != ']')
|
if(ctx[ctx.i] != ']')
|
||||||
|
|
@ -249,7 +239,7 @@ std::pair<std::string, uint32_t> get_operator(parse_context ctx)
|
||||||
std::string ret;
|
std::string ret;
|
||||||
uint32_t start=ctx.i;
|
uint32_t start=ctx.i;
|
||||||
|
|
||||||
while(!is_alphanum(ctx[ctx.i]) && !is_in(ctx[ctx.i], ARITHMETIC_OPERATOR_END))
|
while(!is_alphanum(ctx[ctx.i]) && !is_in(ctx[ctx.i], SEPARATORS) && ctx[ctx.i]!=')' )
|
||||||
ctx.i++;
|
ctx.i++;
|
||||||
|
|
||||||
ret = std::string(ctx.data+start, ctx.i-start);
|
ret = std::string(ctx.data+start, ctx.i-start);
|
||||||
|
|
@ -262,9 +252,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] == ')')
|
||||||
|
|
@ -274,16 +264,16 @@ std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto po = get_operator(ctx);
|
auto po = get_operator(ctx);
|
||||||
if(is_in_set(po.first, arithmetic_precedence_operators))
|
if(is_among(po.first, arithmetic_precedence_operators))
|
||||||
{
|
{
|
||||||
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 +281,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 +314,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;
|
||||||
}
|
}
|
||||||
|
|
@ -346,16 +323,16 @@ std::pair<arithmetic_t*, parse_context> parse_arithmetic(parse_context ctx)
|
||||||
auto po = get_operator(ctx);
|
auto po = get_operator(ctx);
|
||||||
if(po.first != "")
|
if(po.first != "")
|
||||||
{
|
{
|
||||||
if(!is_in_set(po.first, arithmetic_operators))
|
if(!is_among(po.first, arithmetic_operators))
|
||||||
{
|
{
|
||||||
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 +354,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 +370,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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -420,7 +397,7 @@ std::pair<variable_t*, parse_context> parse_manipulation(parse_context ctx)
|
||||||
}
|
}
|
||||||
else if(ctx[ctx.i] != '}')
|
else if(ctx[ctx.i] != '}')
|
||||||
{
|
{
|
||||||
auto pa = parse_arg(ctx, "}", NULL, false, ARG_OPTIMIZE_MANIP);
|
auto pa = parse_arg(ctx, "}", NULL, false);
|
||||||
ret->manip=pa.first;
|
ret->manip=pa.first;
|
||||||
ctx = pa.second;
|
ctx = pa.second;
|
||||||
}
|
}
|
||||||
|
|
@ -429,15 +406,14 @@ 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)
|
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
|
||||||
if(ctx.i-j>0)
|
std::string tmpstr=std::string(ctx.data+j, ctx.i-j);
|
||||||
ret->add(std::string(ctx.data+j, ctx.i-j));
|
if(tmpstr!="")
|
||||||
|
ret->add(tmpstr);
|
||||||
|
|
||||||
ctx.i++;
|
ctx.i++;
|
||||||
uint32_t k=skip_until(ctx, "`");
|
uint32_t k=skip_until(ctx, "`");
|
||||||
|
|
@ -453,24 +429,23 @@ 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;
|
||||||
}
|
}
|
||||||
else if( word_eq("$((", ctx) ) // arithmetic operation
|
else if( word_eq("$((", ctx) ) // arithmetic operation
|
||||||
{
|
{
|
||||||
// add previous subarg
|
// add previous subarg
|
||||||
if(ctx.i-j>0)
|
std::string tmpstr=std::string(ctx.data+j, ctx.i-j);
|
||||||
ret->add(std::string(ctx.data+j, ctx.i-j));
|
if(tmpstr!="")
|
||||||
|
ret->add(tmpstr);
|
||||||
// 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;
|
||||||
|
|
@ -487,24 +462,26 @@ inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t&
|
||||||
else if( word_eq("$(", ctx) ) // substitution
|
else if( word_eq("$(", ctx) ) // substitution
|
||||||
{
|
{
|
||||||
// add previous subarg
|
// add previous subarg
|
||||||
if(ctx.i-j>0)
|
std::string tmpstr=std::string(ctx.data+j, ctx.i-j);
|
||||||
ret->add(std::string(ctx.data+j, ctx.i-j));
|
if(tmpstr!="")
|
||||||
|
ret->add(tmpstr);
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
else if( word_eq("${", ctx) ) // variable manipulation
|
else if( word_eq("${", ctx) ) // variable manipulation
|
||||||
{
|
{
|
||||||
// add previous subarg
|
// add previous subarg
|
||||||
if(ctx.i-j>0)
|
std::string tmpstr=std::string(ctx.data+j, ctx.i-j);
|
||||||
ret->add(std::string(ctx.data+j, ctx.i-j));
|
if(tmpstr!="")
|
||||||
|
ret->add(tmpstr);
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
@ -516,10 +493,11 @@ inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t&
|
||||||
if(r.first !=nullptr)
|
if(r.first !=nullptr)
|
||||||
{
|
{
|
||||||
// add previous subarg
|
// add previous subarg
|
||||||
if(ctx.i-j>0)
|
std::string tmpstr=std::string(ctx.data+j, ctx.i-j);
|
||||||
ret->add(std::string(ctx.data+j, ctx.i-j));
|
if(tmpstr!="")
|
||||||
|
ret->add(tmpstr);
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
@ -531,55 +509,36 @@ inline parse_context do_one_subarg_step(arg_t* ret, parse_context ctx, uint32_t&
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t find_any(parse_context const& ctx, const char* chars, uint32_t nchar) {
|
|
||||||
uint64_t lowest=ctx.size;
|
|
||||||
uint64_t trank=0;
|
|
||||||
for(uint32_t i=0; i<nchar; i++) {
|
|
||||||
const char* tc = strchr(ctx.data+ctx.i, chars[i]);
|
|
||||||
if(tc != NULL) {
|
|
||||||
trank = tc-ctx.data;
|
|
||||||
if(trank < lowest)
|
|
||||||
lowest = trank;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lowest;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _optimize_skip_arg(parse_context& ctx, const char* str) {
|
|
||||||
while(ctx.i<ctx.size && !is_in(ctx[ctx.i], str))
|
|
||||||
ctx.i++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
if(unexpected != NULL && is_in(ctx[ctx.i], unexpected))
|
if(unexpected != NULL && is_in(ctx[ctx.i], unexpected))
|
||||||
{
|
{
|
||||||
parse_error( unexpected_token(ctx[ctx.i]), ctx);
|
parse_error( unexpected_token(ctx[ctx.i]) , ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(ctx.i<ctx.size && _optimize_skip_arg(ctx, optimize) && !(end != NULL && is_in(ctx[ctx.i], end)) )
|
while(ctx.i<ctx.size && !(end != NULL && is_in(ctx[ctx.i], end)) )
|
||||||
{
|
{
|
||||||
if(ctx.i+1<ctx.size && ctx[ctx.i+1]=='&' && (ctx[ctx.i] == '<' || ctx[ctx.i] == '>')) // special case for <& and >&
|
if(ctx.i+1<ctx.size && is_in(ctx[ctx.i], "<>") && ctx[ctx.i+1]=='&') // special case for <& and >&
|
||||||
{
|
{
|
||||||
ctx.i += 2;
|
ctx.i += 2;
|
||||||
}
|
}
|
||||||
else if(ctx[ctx.i]=='\\') // backslash: don't check next char
|
else if(doquote && ctx[ctx.i]=='\\') // backslash: don't check next char
|
||||||
{
|
{
|
||||||
ctx.i++;
|
ctx.i++;
|
||||||
if(ctx.i>=ctx.size)
|
if(ctx.i>=ctx.size)
|
||||||
break;
|
break;
|
||||||
if(ctx[ctx.i] == '\n') // \ on \n : skip this char
|
if(ctx[ctx.i] == '\n') // \ on \n : skip this char
|
||||||
{
|
{
|
||||||
if(ctx.i-1-j>0)
|
std::string tmpstr=std::string(ctx.data+j, ctx.i-1-j);
|
||||||
ret->add(std::string(ctx.data+j, ctx.i-1-j));
|
if(tmpstr!="")
|
||||||
|
ret->add(tmpstr);
|
||||||
ctx.i++;
|
ctx.i++;
|
||||||
j=ctx.i;
|
j=ctx.i;
|
||||||
}
|
}
|
||||||
|
|
@ -649,11 +608,8 @@ parse_context parse_heredocument(parse_context ctx)
|
||||||
{
|
{
|
||||||
ctx.i = ctx.size;
|
ctx.i = ctx.size;
|
||||||
}
|
}
|
||||||
parse_context newctx = make_context(ctx, j);
|
// std::string tmpparse=std::string(ctx.data+j, ctx.i-j);
|
||||||
newctx.size = ctx.i;
|
auto pval = parse_arg({ .data=ctx.data, .size=ctx.i, .i=j, .bash=ctx.bash} , NULL);
|
||||||
auto pval = parse_arg(newctx , NULL, NULL, false, ARG_OPTIMIZE_NULL);
|
|
||||||
ctx.i = pval.second.i;
|
|
||||||
ctx.has_errored = pval.second.has_errored;
|
|
||||||
ctx.here_document->here_document = pval.first;
|
ctx.here_document->here_document = pval.first;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -664,19 +620,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 +707,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,12 +745,8 @@ 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 <()
|
ret->target = pa.first;
|
||||||
pa = parse_bash_procsub(ctx);
|
|
||||||
else
|
|
||||||
pa = parse_arg(ctx);
|
|
||||||
ret->target=pa.first;
|
|
||||||
ctx=pa.second;
|
ctx=pa.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -823,9 +763,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 +776,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);
|
||||||
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) )
|
||||||
|
|
@ -860,7 +800,7 @@ std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(is_in(ctx[ctx.i], ARGLIST_END) && !word_eq("&>", ctx))
|
else if(is_in(ctx[ctx.i], SPECIAL_TOKENS) && !word_eq("&>", ctx))
|
||||||
{
|
{
|
||||||
if(hard_error)
|
if(hard_error)
|
||||||
{
|
{
|
||||||
|
|
@ -876,11 +816,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 +841,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;
|
||||||
}
|
}
|
||||||
|
|
@ -914,7 +858,7 @@ std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_
|
||||||
}
|
}
|
||||||
if(ctx.i>=ctx.size)
|
if(ctx.i>=ctx.size)
|
||||||
return std::make_pair(ret, ctx);
|
return std::make_pair(ret, ctx);
|
||||||
if( is_in(ctx[ctx.i], ARGLIST_END) )
|
if( is_in(ctx[ctx.i], SPECIAL_TOKENS) )
|
||||||
return std::make_pair(ret, ctx);
|
return std::make_pair(ret, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -927,33 +871,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) {
|
if(ctx[ctx.i] == '!' && ctx.i+1<ctx.size && is_in(ctx[ctx.i+1], SPACES))
|
||||||
auto wp = get_word(ctx, ARG_END);
|
{
|
||||||
if(ctx[ctx.i] == '!' && ctx.i+1<ctx.size && is_in(ctx[ctx.i+1], SPACES))
|
ret->negated = true;
|
||||||
{
|
ctx.i++;
|
||||||
ret->negated = ret->negated ? false : true;
|
ctx.i=skip_chars(ctx, SPACES);
|
||||||
ctx.i++;
|
|
||||||
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] != '|' )
|
||||||
{
|
{
|
||||||
|
|
@ -961,14 +895,6 @@ std::pair<pipeline_t*, parse_context> parse_pipeline(parse_context ctx)
|
||||||
return std::make_pair(ret, ctx);
|
return std::make_pair(ret, ctx);
|
||||||
}
|
}
|
||||||
ctx.i++;
|
ctx.i++;
|
||||||
if(ctx.here_document != nullptr)
|
|
||||||
{
|
|
||||||
ctx.i = skip_unread_noline(ctx);
|
|
||||||
if(ctx[ctx.i] == '\n')
|
|
||||||
ctx = parse_heredocument(ctx+1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ctx.i = skip_unread(ctx);
|
|
||||||
}
|
}
|
||||||
return std::make_pair(ret, ctx);
|
return std::make_pair(ret, ctx);
|
||||||
}
|
}
|
||||||
|
|
@ -977,9 +903,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 +914,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);
|
||||||
}
|
}
|
||||||
|
|
@ -1013,14 +939,7 @@ std::pair<condlist_t*, parse_context> parse_condlist(parse_context ctx)
|
||||||
parse_error( unexpected_token(ctx[ctx.i]), ctx);
|
parse_error( unexpected_token(ctx[ctx.i]), ctx);
|
||||||
return std::make_pair(ret, ctx);
|
return std::make_pair(ret, ctx);
|
||||||
}
|
}
|
||||||
if(ctx.here_document != nullptr)
|
ctx.i = skip_unread(ctx);
|
||||||
{
|
|
||||||
ctx.i = skip_unread_noline(ctx);
|
|
||||||
if(ctx[ctx.i] == '\n')
|
|
||||||
ctx = parse_heredocument(ctx+1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ctx.i = skip_unread(ctx);
|
|
||||||
if(ctx.i>=ctx.size)
|
if(ctx.i>=ctx.size)
|
||||||
{
|
{
|
||||||
parse_error( "Unexpected end of file", ctx );
|
parse_error( "Unexpected end of file", ctx );
|
||||||
|
|
@ -1030,9 +949,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 +1024,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
|
|
||||||
t_ctx = parse_heredocument(t_ctx+1);
|
|
||||||
has_parsed=true;
|
|
||||||
}
|
|
||||||
else if(t_ctx[t_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 = parse_heredocument(ctx+1);
|
||||||
has_parsed=true;
|
break;
|
||||||
}
|
}
|
||||||
else if(t_ctx[t_ctx.i] == '#')
|
else if(ctx[ctx.i] == '#')
|
||||||
{
|
{
|
||||||
t_ctx.i = skip_until(t_ctx, "\n"); //skip to endline
|
ctx.i = skip_until(ctx, "\n"); //skip to endline
|
||||||
t_ctx = parse_heredocument(t_ctx+1);
|
ctx = parse_heredocument(ctx+1);
|
||||||
has_parsed=true;
|
break;
|
||||||
}
|
}
|
||||||
|
skip_chars(ctx, SPACES);
|
||||||
|
do_twice--;
|
||||||
}
|
}
|
||||||
if(has_parsed)
|
// case of : cat << EOF ; ;
|
||||||
ctx = t_ctx;
|
if(do_twice==0 && is_in(ctx[ctx.i], COMMAND_SEPARATOR))
|
||||||
|
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 +1071,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 +1093,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 +1115,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 +1143,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* ret, 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,10 +1152,6 @@ 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;
|
|
||||||
if(cmdassign)
|
|
||||||
ret=&in->cmd_var_assigns;
|
|
||||||
|
|
||||||
while(ctx.i<ctx.size && !is_in(ctx[ctx.i], ARGLIST_END))
|
while(ctx.i<ctx.size && !is_in(ctx[ctx.i], ARGLIST_END))
|
||||||
{
|
{
|
||||||
auto vp=parse_var(ctx, false, true);
|
auto vp=parse_var(ctx, false, true);
|
||||||
|
|
@ -1277,7 +1184,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 +1196,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, ")");
|
||||||
ta=pp.first;
|
ta=pp.first;
|
||||||
ta->insert(0,"(");
|
ta->insert(0,"(");
|
||||||
ta->add(")");
|
ta->add(")");
|
||||||
|
|
@ -1298,7 +1205,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,8 +1214,7 @@ 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->var_assigns.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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1317,14 +1223,14 @@ parse_context parse_cmd_varassigns(cmd_t* in, parse_context ctx, bool cmdassign=
|
||||||
{
|
{
|
||||||
if(vp.first != nullptr && is_in(newct[newct.i], ARG_END) )
|
if(vp.first != nullptr && is_in(newct[newct.i], ARG_END) )
|
||||||
{
|
{
|
||||||
ret->push_back(std::make_pair(vp.first, nullptr));
|
ret->var_assigns.push_back(std::make_pair(vp.first, nullptr));
|
||||||
ctx=newct;
|
ctx=newct;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete vp.first;
|
delete vp.first;
|
||||||
auto pp=parse_arg(ctx);
|
auto pp=parse_arg(ctx);
|
||||||
ret->push_back(std::make_pair(nullptr, pp.first));
|
ret->var_assigns.push_back(std::make_pair(nullptr, pp.first));
|
||||||
ctx=pp.second;
|
ctx=pp.second;
|
||||||
}
|
}
|
||||||
ctx.i=skip_chars(ctx, SPACES);
|
ctx.i=skip_chars(ctx, SPACES);
|
||||||
|
|
@ -1341,36 +1247,41 @@ 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;
|
||||||
|
uint32_t start=ctx.i;
|
||||||
|
|
||||||
ctx = parse_cmd_varassigns(ret, ctx);
|
ctx = parse_cmd_varassigns(ret, ctx);
|
||||||
|
|
||||||
auto wp=get_word(ctx, ARG_END);
|
auto wp=get_word(ctx, ARG_END);
|
||||||
bool is_bash_cmdvar=false;
|
if(is_in_vector(wp.first, posix_cmdvar) || is_in_vector(wp.first, bash_cmdvar))
|
||||||
if(is_in_set(wp.first, posix_cmdvar) || (is_bash_cmdvar=is_in_set(wp.first, bash_cmdvar)) )
|
|
||||||
{
|
{
|
||||||
if(!ctx.bash && (is_bash_cmdvar || is_in_set(wp.first, bash_cmdvar)))
|
if(!ctx.bash && is_in_vector(wp.first, bash_cmdvar))
|
||||||
{
|
{
|
||||||
parse_error("bash specific: "+wp.first, ctx);
|
parse_error("bash specific: "+wp.first, ctx);
|
||||||
}
|
}
|
||||||
|
if(ret->var_assigns.size()>0)
|
||||||
|
{
|
||||||
|
parse_error("Unallowed preceding variables on "+wp.first, ctx, start);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
ctx = parse_cmd_varassigns(ret, ctx, true, wp.first);
|
ctx = parse_cmd_varassigns(ret, ctx, true, wp.first);
|
||||||
}
|
}
|
||||||
else if(!is_in(ctx[ctx.i], ARGLIST_END))
|
|
||||||
|
if(!is_in(ctx[ctx.i], SPECIAL_TOKENS))
|
||||||
{
|
{
|
||||||
auto pp=parse_arglist(ctx, true, &ret->redirs);
|
auto pp=parse_arglist(ctx, true, &ret->redirs);
|
||||||
ret->args = pp.first;
|
ret->args = pp.first;
|
||||||
ctx = pp.second;
|
ctx = pp.second;
|
||||||
}
|
}
|
||||||
else if( ret->var_assigns.size() <= 0 )
|
else if(ret->var_assigns.size() <= 0)
|
||||||
{
|
{
|
||||||
parse_error( unexpected_token(ctx[ctx.i]), ctx );
|
parse_error( unexpected_token(ctx[ctx.i]), ctx );
|
||||||
ctx.i++;
|
ctx.i++;
|
||||||
|
|
@ -1382,9 +1293,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 +1317,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;
|
||||||
|
|
||||||
|
|
@ -1428,7 +1339,7 @@ std::pair<case_t*, parse_context> parse_case(parse_context ctx)
|
||||||
}
|
}
|
||||||
if(ctx[ctx.i] == ')')
|
if(ctx[ctx.i] == ')')
|
||||||
break;
|
break;
|
||||||
if(is_in(ctx[ctx.i], PIPELINE_END))
|
if(ctx[ctx.i] != '|' && is_in(ctx[ctx.i], SPECIAL_TOKENS))
|
||||||
{
|
{
|
||||||
parse_error( unexpected_token(ctx[ctx.i])+", expecting ')'", ctx );
|
parse_error( unexpected_token(ctx[ctx.i])+", expecting ')'", ctx );
|
||||||
}
|
}
|
||||||
|
|
@ -1472,9 +1383,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)
|
||||||
{
|
{
|
||||||
|
|
@ -1503,10 +1414,6 @@ std::pair<if_t*, parse_context> parse_if(parse_context ctx)
|
||||||
newctx.has_errored=true;
|
newctx.has_errored=true;
|
||||||
}
|
}
|
||||||
ctx = newctx;
|
ctx = newctx;
|
||||||
if(ctx.i >= ctx.size)
|
|
||||||
{
|
|
||||||
return std::make_pair(ret, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(word == "fi")
|
if(word == "fi")
|
||||||
break;
|
break;
|
||||||
|
|
@ -1531,9 +1438,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 +1449,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);
|
||||||
|
|
||||||
|
|
@ -1555,7 +1462,6 @@ std::pair<for_t*, parse_context> parse_for(parse_context ctx)
|
||||||
auto pp = parse_arglist(ctx, false);
|
auto pp = parse_arglist(ctx, false);
|
||||||
ret->iter = pp.first;
|
ret->iter = pp.first;
|
||||||
ctx = pp.second;
|
ctx = pp.second;
|
||||||
ret->in_val=true;
|
|
||||||
}
|
}
|
||||||
else if(wp.first != "")
|
else if(wp.first != "")
|
||||||
{
|
{
|
||||||
|
|
@ -1595,9 +1501,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 +1533,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)
|
||||||
{
|
{
|
||||||
|
|
@ -1688,10 +1594,9 @@ std::pair<block_t*, parse_context> parse_block(parse_context ctx)
|
||||||
ret = pp.first;
|
ret = pp.first;
|
||||||
ctx = pp.second;
|
ctx = pp.second;
|
||||||
}
|
}
|
||||||
else if(is_in_set(word, out_reserved_words)) // is a reserved word
|
else if(is_in_vector(word, out_reserved_words)) // is a reserved word
|
||||||
{
|
{
|
||||||
parse_error( strf("Unexpected '%s'", word.c_str())+expecting(ctx.expecting) , ctx);
|
parse_error( strf("Unexpected '%s'", word.c_str())+expecting(ctx.expecting) , ctx);
|
||||||
ctx.i+=word.size();
|
|
||||||
}
|
}
|
||||||
// end reserved words
|
// end reserved words
|
||||||
else if( word == "function" ) // bash style function
|
else if( word == "function" ) // bash style function
|
||||||
|
|
@ -1746,11 +1651,11 @@ std::pair<block_t*, parse_context> parse_block(parse_context ctx)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ret!=nullptr && ret->type != block_t::block_cmd)
|
if(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;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ set_t m_excluded_var, m_excluded_fct, m_excluded_cmd;
|
||||||
|
|
||||||
bool b_gotvar=false, b_gotfct=false, b_gotcmd=false;
|
bool b_gotvar=false, b_gotfct=false, b_gotcmd=false;
|
||||||
|
|
||||||
|
|
||||||
// requires
|
// requires
|
||||||
|
|
||||||
void require_rescan_var()
|
void require_rescan_var()
|
||||||
|
|
@ -62,24 +63,16 @@ void require_rescan_all()
|
||||||
// type tools
|
// type tools
|
||||||
countmap_t combine_maps(countmap_t const& a, countmap_t const& b)
|
countmap_t combine_maps(countmap_t const& a, countmap_t const& b)
|
||||||
{
|
{
|
||||||
countmap_t ret = a;
|
countmap_t ret;
|
||||||
for(auto it: b)
|
for(auto it: a)
|
||||||
{
|
{
|
||||||
if(!ret.insert( it ).second)
|
if(!ret.insert( it ).second)
|
||||||
ret[it.first] += it.second;
|
ret[it.first] += it.second;
|
||||||
}
|
}
|
||||||
return ret;
|
for(auto it: b)
|
||||||
}
|
|
||||||
|
|
||||||
// add the values of b to a only if they are already present in a
|
|
||||||
countmap_t combine_common(countmap_t const& a, countmap_t const& b)
|
|
||||||
{
|
|
||||||
countmap_t ret = a;
|
|
||||||
for(auto it: a)
|
|
||||||
{
|
{
|
||||||
auto t=b.find(it.first);
|
if(!ret.insert( it ).second)
|
||||||
if(t!=b.end())
|
ret[it.first] += it.second;
|
||||||
ret[it.first] += t->second;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +148,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 "";
|
||||||
|
|
@ -167,15 +160,15 @@ std::string get_varname(arg_t* in)
|
||||||
|
|
||||||
bool cmd_is_argvar(std::string const& in)
|
bool cmd_is_argvar(std::string const& in)
|
||||||
{
|
{
|
||||||
return is_in_set(in, posix_cmdvar) || is_in_set(in, bash_cmdvar);
|
return is_in_vector(in, posix_cmdvar) || is_in_vector(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);
|
||||||
}
|
}
|
||||||
|
|
@ -213,39 +206,6 @@ void cmdmap_get(_obj* in, std::regex const& exclude)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fctcmdmap_get(_obj* in, std::regex const& exclude_fct, std::regex const& exclude_cmd)
|
|
||||||
{
|
|
||||||
if(!b_gotcmd && !b_gotfct) {
|
|
||||||
b_gotcmd = b_gotfct = true;
|
|
||||||
recurse(r_get_fctcmd, in, &m_cmds, &m_fcts);
|
|
||||||
m_excluded_fct = prune_matching(m_cmds, exclude_cmd);
|
|
||||||
concat_sets(m_excluded_fct, prune_matching(m_fcts, exclude_fct));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cmdmap_get(in, exclude_fct);
|
|
||||||
fctmap_get(in, exclude_cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void allmaps_get(_obj* in, std::regex const& exclude_var, std::regex const& exclude_fct, std::regex const& exclude_cmd)
|
|
||||||
{
|
|
||||||
if(!b_gotvar && !b_gotcmd && !b_gotfct)
|
|
||||||
{
|
|
||||||
b_gotvar = b_gotcmd = b_gotfct = true;
|
|
||||||
recurse(r_get_all, in, &m_vardefs, &m_varcalls, &m_cmds, &m_fcts);
|
|
||||||
m_excluded_fct = prune_matching(m_cmds, exclude_cmd);
|
|
||||||
concat_sets(m_excluded_fct, prune_matching(m_fcts, exclude_fct));
|
|
||||||
m_vars = combine_maps(m_vardefs, m_varcalls);
|
|
||||||
m_excluded_var = prune_matching(m_vars, exclude_var);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
varmap_get(in, exclude_var);
|
|
||||||
cmdmap_get(in, exclude_fct);
|
|
||||||
fctmap_get(in, exclude_fct);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** OUTPUT **/
|
/** OUTPUT **/
|
||||||
|
|
||||||
void list_vars(_obj* in, std::regex const& exclude)
|
void list_vars(_obj* in, std::regex const& exclude)
|
||||||
|
|
@ -285,53 +245,28 @@ 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->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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_env_set(_obj* in) {
|
|
||||||
bool r=false;
|
|
||||||
recurse(r_has_env_set, in, &r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** RECURSIVES **/
|
/** RECURSIVES **/
|
||||||
|
|
||||||
// CHECK //
|
|
||||||
|
|
||||||
bool r_has_env_set(_obj* in, bool* result)
|
|
||||||
{
|
|
||||||
switch(in->type)
|
|
||||||
{
|
|
||||||
case _obj::block_subshell: {
|
|
||||||
return false;
|
|
||||||
}; break;
|
|
||||||
case _obj::block_cmd: {
|
|
||||||
cmd_t* t = dynamic_cast<cmd_t*>(in);
|
|
||||||
if(t->has_var_assign() || t->arg_string(0) == "cd")
|
|
||||||
*result = true;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET //
|
// GET //
|
||||||
|
|
||||||
bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap)
|
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,10 +288,10 @@ 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->var_assigns)
|
||||||
{
|
{
|
||||||
if(it.first != nullptr)
|
if(it.first != nullptr)
|
||||||
unsets->insert(it.first->varname);
|
unsets->insert(it.first->varname);
|
||||||
|
|
@ -373,7 +308,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 +323,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;
|
||||||
|
|
@ -397,35 +332,20 @@ bool r_get_fct(_obj* in, countmap_t* fct_map)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool r_get_fctcmd(_obj* in, countmap_t* all_cmds, countmap_t* fct_map)
|
|
||||||
{
|
|
||||||
r_get_cmd(in, all_cmds);
|
|
||||||
r_get_fct(in, fct_map);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool r_get_all(_obj* in, countmap_t* defmap, countmap_t* callmap, countmap_t* all_cmds, countmap_t* fct_map)
|
|
||||||
{
|
|
||||||
r_get_var(in, defmap, callmap);
|
|
||||||
r_get_cmd(in, all_cmds);
|
|
||||||
r_get_fct(in, fct_map);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DELETE //
|
// DELETE //
|
||||||
|
|
||||||
bool r_delete_fct(_obj* in, set_t* fcts)
|
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 +364,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++)
|
||||||
{
|
{
|
||||||
|
|
@ -471,22 +391,6 @@ bool r_delete_var(_obj* in, set_t* vars)
|
||||||
if(has_deleted && c->var_assigns.size()<=0 && (c->arglist_size()<=0 || c->is_cmdvar) )
|
if(has_deleted && c->var_assigns.size()<=0 && (c->arglist_size()<=0 || c->is_cmdvar) )
|
||||||
to_delete=true;
|
to_delete=true;
|
||||||
|
|
||||||
for(uint32_t j=0; j<c->cmd_var_assigns.size(); j++)
|
|
||||||
{
|
|
||||||
if( c->cmd_var_assigns[j].first != nullptr && vars->find(c->cmd_var_assigns[j].first->varname) != vars->end() )
|
|
||||||
{
|
|
||||||
if(c->cmd_var_assigns[j].first != nullptr)
|
|
||||||
delete c->cmd_var_assigns[j].first;
|
|
||||||
if(c->cmd_var_assigns[j].second != nullptr)
|
|
||||||
delete c->cmd_var_assigns[j].second;
|
|
||||||
c->cmd_var_assigns.erase(c->cmd_var_assigns.begin()+j);
|
|
||||||
has_deleted=true;
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(has_deleted && c->cmd_var_assigns.size()<=0 && (c->arglist_size()<=0 || c->is_cmdvar) )
|
|
||||||
to_delete=true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if(to_delete)
|
if(to_delete)
|
||||||
{
|
{
|
||||||
|
|
@ -494,8 +398,6 @@ bool r_delete_var(_obj* in, set_t* vars)
|
||||||
t->cls.erase(t->cls.begin()+i);
|
t->cls.erase(t->cls.begin()+i);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
if(t->cls.size()<=0)
|
|
||||||
t->add(make_condlist("true"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
|
|
@ -503,13 +405,6 @@ bool r_delete_var(_obj* in, set_t* vars)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool r_delete_varfct(_obj* in, set_t* vars, set_t* fcts)
|
|
||||||
{
|
|
||||||
r_delete_var(in, vars);
|
|
||||||
r_delete_fct(in, fcts);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<std::string> find_lxsh_commands(shmain* sh)
|
std::set<std::string> find_lxsh_commands(shmain* sh)
|
||||||
{
|
{
|
||||||
std::set<std::string> ret;
|
std::set<std::string> ret;
|
||||||
|
|
@ -549,7 +444,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())
|
||||||
{
|
{
|
||||||
|
|
@ -560,8 +455,8 @@ bool r_do_string_processor(_obj* in)
|
||||||
require_rescan_all();
|
require_rescan_all();
|
||||||
if(options["remove-unused"])
|
if(options["remove-unused"])
|
||||||
delete_unused( tsh, re_var_exclude, re_fct_exclude );
|
delete_unused( tsh, re_var_exclude, re_fct_exclude );
|
||||||
if(options["minify"])
|
if(options["minify-quotes"])
|
||||||
minify_generic(tsh);
|
minify_quotes(tsh);
|
||||||
if(options["minify-var"])
|
if(options["minify-var"])
|
||||||
minify_var( tsh, re_var_exclude );
|
minify_var( tsh, re_var_exclude );
|
||||||
if(options["minify-fct"])
|
if(options["minify-fct"])
|
||||||
|
|
@ -582,17 +477,14 @@ bool r_do_string_processor(_obj* in)
|
||||||
|
|
||||||
void string_processors(_obj* in)
|
void string_processors(_obj* in)
|
||||||
{
|
{
|
||||||
// recurse(r_do_string_processor, in);
|
recurse(r_do_string_processor, in);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** JSON **/
|
/** JSON **/
|
||||||
|
|
||||||
#ifdef DEBUG_MODE
|
|
||||||
|
|
||||||
std::string quote_string(std::string const& in)
|
std::string quote_string(std::string const& in)
|
||||||
{
|
{
|
||||||
return '"' + stringReplace(stringReplace(stringReplace(in, "\\", "\\\\"), "\"", "\\\""), "\n", "\\n") + '"';
|
return '"' + stringReplace(in, "\"", "\\\"") + '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string gen_json(std::vector<std::pair<std::string,std::string>> const& vec)
|
std::string gen_json(std::vector<std::pair<std::string,std::string>> const& vec)
|
||||||
|
|
@ -627,6 +519,7 @@ std::string boolstring(bool in)
|
||||||
return "false";
|
return "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_MODE
|
||||||
std::string gen_json_struc(_obj* o)
|
std::string gen_json_struc(_obj* o)
|
||||||
{
|
{
|
||||||
if(o==nullptr)
|
if(o==nullptr)
|
||||||
|
|
@ -634,9 +527,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 +539,27 @@ 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)));
|
|
||||||
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 +567,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 +578,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 +596,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 +608,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 +622,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 +651,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 +666,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)));
|
||||||
|
|
@ -790,15 +681,6 @@ std::string gen_json_struc(_obj* o)
|
||||||
aa.push_back(gen_json(ttvec));
|
aa.push_back(gen_json(ttvec));
|
||||||
}
|
}
|
||||||
vec.push_back(std::make_pair( quote_string("var_assigns"), gen_json(aa)));
|
vec.push_back(std::make_pair( quote_string("var_assigns"), gen_json(aa)));
|
||||||
std::vector<std::string> bb;
|
|
||||||
for(auto it: t->cmd_var_assigns)
|
|
||||||
{
|
|
||||||
std::vector<std::pair<std::string,std::string>> ttvec;
|
|
||||||
ttvec.push_back( std::make_pair(quote_string("var"), gen_json_struc(it.first)) );
|
|
||||||
ttvec.push_back( std::make_pair(quote_string("value"), gen_json_struc(it.second)) );
|
|
||||||
bb.push_back(gen_json(ttvec));
|
|
||||||
}
|
|
||||||
vec.push_back(std::make_pair( quote_string("cmd_var_assigns"), gen_json(bb)));
|
|
||||||
|
|
||||||
std::vector<std::string> tvec;
|
std::vector<std::string> tvec;
|
||||||
for(auto it: t->redirs)
|
for(auto it: t->redirs)
|
||||||
|
|
@ -809,7 +691,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 +720,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 +745,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 +760,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 +774,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 +796,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 +832,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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -277,24 +277,18 @@ std::pair< std::vector<arg_t*> , bool > resolve_arg(arg_t* in, parse_context ctx
|
||||||
|
|
||||||
if(tsh->quoted || forcequote)
|
if(tsh->quoted || forcequote)
|
||||||
{
|
{
|
||||||
fulltext = stringReplace(fulltext, "\\\"", "\\\\\"");
|
stringReplace(fulltext, "\"", "\\\"");
|
||||||
fulltext = escape_chars(fulltext, "\"`$");
|
stringReplace(fulltext, "!", "\\!");
|
||||||
fulltext = stringReplace(fulltext, "!", "\"\\!\"");
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
fulltext = escape_chars(fulltext, "\\\"!$`#&|()';<>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!tsh->quoted && forcequote)
|
if(!tsh->quoted && forcequote)
|
||||||
fulltext = '"' + fulltext + '"';
|
fulltext = '"' + fulltext + '"';
|
||||||
|
|
||||||
|
|
||||||
if(tsh->quoted || forcequote)
|
if(tsh->quoted || forcequote)
|
||||||
{
|
{
|
||||||
// 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 +299,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 +344,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 +367,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,17 +391,12 @@ 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
|
||||||
resolve(it.second, ct);
|
resolve(it.second, ct);
|
||||||
}
|
}
|
||||||
for(auto it: t->cmd_var_assigns) // var assigns
|
|
||||||
{
|
|
||||||
resolve_arg(it.second, *ct, true); // force quoted
|
|
||||||
resolve(it.second, ct);
|
|
||||||
}
|
|
||||||
for(auto it: t->redirs)
|
for(auto it: t->redirs)
|
||||||
resolve(it, ct);
|
resolve(it, ct);
|
||||||
resolve(t->args, ct);
|
resolve(t->args, ct);
|
||||||
|
|
@ -415,7 +404,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
|
||||||
|
|
|
||||||
|
|
@ -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"} }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,163 +7,108 @@
|
||||||
|
|
||||||
// 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<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<std::string> 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)
|
|
||||||
ret->args->add(new arg_t(it));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_t* make_cmd(std::vector<arg_t*> const& args)
|
|
||||||
{
|
|
||||||
cmd_t* ret = new cmd_t;
|
|
||||||
ret->args = new arglist_t;
|
|
||||||
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_t* prnt = make_cmd(std::vector<const char*>({"printf", "%s\\\\n"}));
|
|
||||||
force_quotes(in);
|
|
||||||
prnt->add(in);
|
|
||||||
return prnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
arithmetic_t* make_arithmetic(arg_t* a)
|
|
||||||
{
|
|
||||||
if(a->sa.size() != 1)
|
|
||||||
{
|
|
||||||
cmd_t* prnt = make_printf(a);
|
|
||||||
return new arithmetic_subshell_t(new subshell_t(prnt));
|
|
||||||
}
|
|
||||||
arithmetic_t* ret=nullptr;
|
|
||||||
switch(a->sa[0]->type) {
|
|
||||||
case _obj::subarg_string : {
|
|
||||||
subarg_string_t* t = dynamic_cast<subarg_string_t*>(a->sa[0]);
|
|
||||||
ret = new arithmetic_number_t(t->val);
|
|
||||||
}; break;
|
|
||||||
case _obj::subarg_variable : {
|
|
||||||
subarg_variable_t* t = dynamic_cast<subarg_variable_t*>(a->sa[0]);
|
|
||||||
ret = new arithmetic_variable_t(t->var);
|
|
||||||
t->var = nullptr;
|
|
||||||
}; break;
|
|
||||||
case _obj::subarg_subshell : {
|
|
||||||
subarg_subshell_t* t = dynamic_cast<subarg_subshell_t*>(a->sa[0]);
|
|
||||||
ret = new arithmetic_subshell_t(t->sbsh);
|
|
||||||
t->sbsh = nullptr;
|
|
||||||
}; break;
|
|
||||||
case _obj::subarg_arithmetic : {
|
|
||||||
subarg_arithmetic_t* t = dynamic_cast<subarg_arithmetic_t*>(a->sa[0]);
|
|
||||||
ret = t->arith;
|
|
||||||
t->arith = nullptr;
|
|
||||||
}; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
delete a;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
arithmetic_t* make_arithmetic(arg_t* arg1, std::string op, arg_t* arg2)
|
|
||||||
{
|
|
||||||
return new arithmetic_operation_t(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++)
|
||||||
{
|
{
|
||||||
if(!in->sa[i]->quoted && (in->sa[i]->type == _obj::subarg_variable || in->sa[i]->type == _obj::subarg_subshell) )
|
if(!in->sa[i]->quoted && (in->sa[i]->type == _obj::subarg_variable || in->sa[i]->type == _obj::subarg_subshell) )
|
||||||
{
|
{
|
||||||
in->sa[i]->quoted=true;
|
in->sa[i]->quoted=true;
|
||||||
in->insert(i+1, "\"");
|
in->insert(i+1, new string_subarg("\""));
|
||||||
in->insert(i, "\"");
|
in->insert(i, new string_subarg("\""));
|
||||||
i+=2;
|
i+=2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(new string_subarg("\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ** 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 +116,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 +124,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,16 +138,7 @@ bool possibly_expands(arglist_t* in)
|
||||||
|
|
||||||
// property getters
|
// property getters
|
||||||
|
|
||||||
bool cmd_t::has_var_assign()
|
size_t cmd::arglist_size()
|
||||||
{
|
|
||||||
if(this->args == nullptr || this->args->size() == 0)
|
|
||||||
{
|
|
||||||
return this->var_assigns.size()>0;
|
|
||||||
}
|
|
||||||
return this->is_argvar();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cmd_t::arglist_size()
|
|
||||||
{
|
{
|
||||||
if(args==nullptr)
|
if(args==nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -212,33 +148,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 +177,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 +189,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 +202,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 +219,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 +260,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,42 +279,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 && 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 && 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;
|
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sa.insert(sa.begin()+i, val);
|
sa.insert(sa.begin()+i, val);
|
||||||
|
|
@ -393,43 +320,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 +374,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++)
|
||||||
|
|
|
||||||
21
src/util.cpp
21
src/util.cpp
|
|
@ -45,6 +45,14 @@ std::string dirname(std::string const& in)
|
||||||
return ".";
|
return ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_among(std::string const& in, std::vector<std::string> const& values)
|
||||||
|
{
|
||||||
|
for(auto it: values)
|
||||||
|
if(in == it)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> split(std::string const& in, const char* splitters)
|
std::vector<std::string> split(std::string const& in, const char* splitters)
|
||||||
{
|
{
|
||||||
uint32_t i=0,j=0;
|
uint32_t i=0,j=0;
|
||||||
|
|
@ -196,19 +204,6 @@ std::string stringReplace(std::string subject, const std::string& search, const
|
||||||
return subject;
|
return subject;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string escape_chars(std::string subject, const char* chars)
|
|
||||||
{
|
|
||||||
for(size_t i=0; i<subject.size(); i++)
|
|
||||||
{
|
|
||||||
if(is_in(subject[i], chars))
|
|
||||||
{
|
|
||||||
subject.insert(subject.begin()+i, '\\');
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return subject;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string repeatString(std::string const& str, uint32_t n)
|
std::string repeatString(std::string const& str, uint32_t n)
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
|
||||||
47
test/a.bash
47
test/a.bash
|
|
@ -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)
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
echo $(( (2+1)*3 ))
|
|
||||||
echo $(( $((2+1))*3 ))
|
|
||||||
|
|
@ -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[@]}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
echo $(echo toto)
|
|
||||||
echo $(printf %s\\n tata)
|
|
||||||
echo `echo titi`
|
|
||||||
echo `printf '%s\\n' tutu`
|
|
||||||
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
{ echo tata ; echo a; } | sed 's|a|toto|g'
|
|
||||||
|
|
||||||
echo a | { grep a && echo b; }
|
|
||||||
|
|
||||||
{ { echo tata ; } }
|
|
||||||
|
|
@ -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}}
|
|
||||||
17
test/case.sh
17
test/case.sh
|
|
@ -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
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
echo toto#
|
|
||||||
echo toto#tata
|
|
||||||
echo toto #tata
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
{ ; }
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
var[a
|
|
||||||
read var+=a
|
|
||||||
export var+=a
|
|
||||||
export var=()
|
|
||||||
|
|
||||||
[[ a = b ]] toto
|
|
||||||
|
|
||||||
echo >() <()
|
|
||||||
|
|
||||||
function toto-titi{ true; }
|
|
||||||
|
|
@ -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
|
|
||||||
11
test/fct.sh
11
test/fct.sh
|
|
@ -1,11 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
toto() {
|
|
||||||
echo toto
|
|
||||||
}
|
|
||||||
|
|
||||||
tata () {
|
|
||||||
echo tata
|
|
||||||
}
|
|
||||||
|
|
||||||
toto
|
|
||||||
18
test/for.sh
18
test/for.sh
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
11
test/if.sh
11
test/if.sh
|
|
@ -1,11 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -n "$DEBUG" ]
|
|
||||||
then
|
|
||||||
echo "set"
|
|
||||||
elif [ -n "$TOTO" ]
|
|
||||||
then
|
|
||||||
echo "toto lol"
|
|
||||||
else
|
|
||||||
echo "not set"
|
|
||||||
fi
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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*}
|
|
||||||
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
grep "^ID=" /etc/os-release | cut -d '=' -f2-
|
|
||||||
|
|
||||||
echo toto | #
|
|
||||||
grep to
|
|
||||||
|
|
||||||
echo '#toto' | grep '#toto'
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
read -r prompt || echo $?
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{ echo toto >&2; } 2>&1
|
|
||||||
|
|
||||||
{ echo tata; }>/dev/null
|
|
||||||
|
|
||||||
grep abc < test/redir.sh
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
31
test/var.sh
31
test/var.sh
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
Loading…
Reference in a new issue