diff --git a/src/options.cpp b/src/options.cpp index 078a6e7..59d3126 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -26,6 +26,7 @@ ztd::option_set gen_options() ztd::option('m', "minimize", false, "Minimize code without changing functionality"), ztd::option('I', "no-include", false, "Don't resolve %include commands"), ztd::option('R', "no-resolve", false, "Don't resolve %resolve commands"), + ztd::option("debashify", false, "Attempt to turn a bash-specific script into a POSIX shell script"), ztd::option("\r [var/fct processing]"), ztd::option("minimize-var", false, "Minimize variable names"), ztd::option("minimize-fct", false, "Minimize function names"), diff --git a/src/parse.cpp b/src/parse.cpp index 3d51b00..57152ae 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -7,9 +7,12 @@ #include #include "util.hpp" +#include "options.hpp" #define ORIGIN_NONE "" +bool g_bash=false; + // macro #define PARSE_ERROR(str, i) ztd::format_error(str, "", in, i) @@ -382,7 +385,7 @@ std::pair parse_redirect(const char* in, uint32_t size, uin bool needs_arg=false; bool has_num_prefix=false; - if(in[i] > '0' && in[i] < '9') + if(is_num(in[i])) { i++; has_num_prefix=true; @@ -392,30 +395,52 @@ std::pair parse_redirect(const char* in, uint32_t size, uin { i++; if(i>size) - PARSE_ERROR("Unexpected end of file", i); + throw PARSE_ERROR("Unexpected end of file", i); is_redirect = true; if(i+1& bash operator + { + if(!g_bash) + throw PARSE_ERROR("bash specific: '>&'. Use --debashify to remove bashisms", i); + i++; + needs_arg=true; + } else { if(in[i] == '>') i++; needs_arg=true; } - } else if( in[i] == '<' ) { if(has_num_prefix) - PARSE_ERROR("Invalid input redirection", i-1); + throw PARSE_ERROR("Invalid input redirection", i-1); i++; if(i>size) - PARSE_ERROR("Unexpected end of file", i); + throw PARSE_ERROR("Unexpected end of file", i); if(in[i] == '<') + { i++; + if(i", in, size, i) ) // &> bash operator + { + if(!g_bash) + throw PARSE_ERROR("bash specific: '&>'. Use --debashify to remove bashisms", i); + i+=2; is_redirect=true; needs_arg=true; } @@ -439,7 +464,7 @@ std::pair parse_redirect(const char* in, uint32_t size, uin pa.first = nullptr; if(delimitor == "") - PARSE_ERROR("Non-static or empty text input delimitor", i); + throw PARSE_ERROR("Non-static or empty text input delimitor", i); if(delimitor.find('"') != std::string::npos || delimitor.find('\'') != std::string::npos || delimitor.find('\\') != std::string::npos) { @@ -506,7 +531,7 @@ std::pair parse_arglist(const char* in, uint32_t size, uint3 try { - if(is_in(in[i], SPECIAL_TOKENS)) + if(is_in(in[i], SPECIAL_TOKENS) && !word_eq("&>", in, size, i)) { if(hard_error) throw PARSE_ERROR( strf("Unexpected token '%c'", in[i]) , i); @@ -536,6 +561,11 @@ argparse: i = pp.second; } i = skip_chars(in, size, i, SPACES); + if(word_eq("&>", in, size, i)) + // throw PARSE_ERROR("Unsupported &>", i); + continue; + if(word_eq("|&", in, size, i)) + throw PARSE_ERROR("Unsupported |&, use '2>&1 |' instead", i); if(i>=size) return std::make_pair(ret, i); if( is_in(in[i], SPECIAL_TOKENS) ) @@ -898,9 +928,19 @@ std::pair parse_cmd(const char* in, uint32_t size, uint32_t star if(wp.second parse_block(const char* in, uint32_t size, uint32_t if(ret->type != block::block_cmd) { - // while(true) - // { - // auto pr=parse_redirect(in, size, i); - // if(pr.first == nullptr) - // break; - // ret->redirs.push_back(pr.first); - // i = pr.second; - // } uint32_t j=skip_chars(in, size, i, SPACES); auto pp=parse_arglist(in, size, j, false, &ret->redirs); // in case of redirects if(pp.first != nullptr) @@ -1259,15 +1293,6 @@ std::pair parse_block(const char* in, uint32_t size, uint32_t throw PARSE_ERROR("Extra argument after block", i); } i=pp.second; - // if(pp.first->args.size()>0) - // { - // i = pp.second; - // ret->redirs=pp.first; - // } - // else - // { - // delete pp.first; - // } } } catch(ztd::format_error& e) @@ -1294,6 +1319,9 @@ shmain* parse_text(const char* in, uint32_t size, std::string const& filename) ret->shebang=std::string(in, i); } i = skip_unread(in, size, i); + // do bash reading + std::string binshebang = basename(ret->shebang); + g_bash = binshebang == "bash" || binshebang == "lxsh" || options["debashify"]; // parse all commands auto pp=parse_list_until(in, size, i, 0); ret->lst=pp.first;