internal rework: implement parsing context
This commit is contained in:
parent
c0f5e4ba27
commit
7379eaf180
13 changed files with 1160 additions and 790 deletions
1
Makefile
1
Makefile
|
|
@ -17,7 +17,6 @@ CC=g++
|
|||
CXXFLAGS= -I$(IDIR) -Wall -pedantic -std=c++20
|
||||
ifeq ($(DEBUG),true)
|
||||
# debugging flags
|
||||
CC=clang++
|
||||
CXXFLAGS += -g -D NO_PARSE_CATCH
|
||||
else
|
||||
# release flags
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
#define EXEC_HPP
|
||||
|
||||
#include "options.hpp"
|
||||
#include "parse.hpp"
|
||||
|
||||
|
||||
void parse_exec(FILE* fd, const char* in, uint32_t size, std::string const& filename="");
|
||||
inline void parse_exec(FILE* fd, std::string const& in, std::string const& filename="") { parse_exec(fd, in.c_str(), in.size(), filename); }
|
||||
void parse_exec(FILE* fd, parse_context ct);
|
||||
|
||||
int exec_process(std::string const& runtime, std::vector<std::string> const& args, std::string const& filecontents, std::string const& file);
|
||||
int exec_process(std::string const& runtime, std::vector<std::string> const& args, parse_context ct);
|
||||
|
||||
#endif //EXEC_HPP
|
||||
|
|
|
|||
|
|
@ -25,59 +25,84 @@
|
|||
#define ARRAY_ARG_END " \t\n;#()&|<>]"
|
||||
|
||||
// macros
|
||||
#define PARSE_ERROR(str, i) format_error(str, "", in, i)
|
||||
// #define PARSE_ERROR_I(str, ctx, i) format_error(str, ctx.filename, ctx.data, i)
|
||||
// #define PARSE_ERROR(str, ctx) format_error(str, ctx.filename, ctx.data, ctx.i)
|
||||
// #define PARSE_ERROR_I(str, ctx, i) { printFormatError(format_error(str, ctx.filename, ctx.data, i)); ctx.has_errored=true; }
|
||||
// #define PARSE_ERROR(str, ctx) { printFormatError(format_error(str, ctx.filename, ctx.data, ctx.i)); ctx.has_errored=true; }
|
||||
|
||||
// structs
|
||||
|
||||
void parse_error(std::string const& message, parse_context& ctx);
|
||||
|
||||
void parse_error(std::string const& message, parse_context& ctx, uint64_t i);
|
||||
// globals
|
||||
|
||||
extern bool g_bash;
|
||||
|
||||
extern const std::vector<std::string> posix_cmdvar;
|
||||
extern const std::vector<std::string> bash_cmdvar;
|
||||
|
||||
std::string import_file(std::string const& path);
|
||||
|
||||
shmain* parse_text(const char* in, uint32_t size, std::string const& filename="");
|
||||
inline shmain* parse_text(std::string const& in, std::string const& filename="") { return parse_text(in.c_str(), in.size(), filename); }
|
||||
inline shmain* parse(std::string const& file) { return parse_text(import_file(file), file); }
|
||||
std::pair<shmain*, parse_context> parse_text(parse_context context);
|
||||
std::pair<shmain*, parse_context> parse_text(std::string const& in, std::string const& filename="");
|
||||
inline std::pair<shmain*, parse_context> parse(std::string const& file) { return parse_text(import_file(file), file); }
|
||||
|
||||
// tools
|
||||
parse_context make_context(std::string const& in, std::string const& filename="", bool bash=false);
|
||||
parse_context make_context(parse_context ctx, std::string const& in="", std::string const& filename="", bool bash=false);
|
||||
parse_context make_context(parse_context ctx, uint64_t i);
|
||||
parse_context operator+(parse_context ctx, int64_t a);
|
||||
parse_context operator-(parse_context ctx, int64_t a);
|
||||
|
||||
// ** unit parsers ** //
|
||||
|
||||
/* util parsers */
|
||||
bool word_eq(const char* word, const char* in, uint32_t size, uint32_t start, const char* end_set=NULL);
|
||||
std::pair<std::string,uint32_t> get_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=NULL);
|
||||
inline bool word_eq(const char* word, parse_context const& ct, const char* end_set=NULL) {
|
||||
return word_eq(word, ct.data, ct.size, ct.i, end_set);
|
||||
}
|
||||
std::pair<std::string,uint32_t> get_word(parse_context ct, const char* end_set);
|
||||
uint32_t skip_chars(const char* in, uint32_t size, uint32_t start, const char* set);
|
||||
inline uint32_t skip_chars(parse_context const& ct, const char* set) {
|
||||
return skip_chars(ct.data, ct.size, ct.i, set);
|
||||
}
|
||||
uint32_t skip_until(const char* in, uint32_t size, uint32_t start, const char* set);
|
||||
inline uint32_t skip_until(parse_context const& ct, const char* set) {
|
||||
return skip_until(ct.data, ct.size, ct.i, set);
|
||||
}
|
||||
uint32_t skip_unread(const char* in, uint32_t size, uint32_t start);
|
||||
inline uint32_t skip_unread(parse_context const& ct) {
|
||||
return skip_unread(ct.data, ct.size, ct.i);
|
||||
}
|
||||
|
||||
// list
|
||||
std::pair<list*, uint32_t> parse_list_until(const char* in, uint32_t size, uint32_t start, char end_c, const char* expecting=NULL);
|
||||
std::pair<list*, uint32_t> parse_list_until(const char* in, uint32_t size, uint32_t start, std::string const& end_word);
|
||||
std::tuple<list*, uint32_t, std::string> parse_list_until(const char* in, uint32_t size, uint32_t start, std::vector<std::string> const& end_words, const char* expecting=NULL);
|
||||
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);
|
||||
// name
|
||||
std::pair<variable*, uint32_t> parse_var(const char* in, uint32_t size, uint32_t start, bool specialvars=true, bool array=false);
|
||||
std::pair<variable*, parse_context> parse_var(parse_context ct, bool specialvars=true, bool array=false);
|
||||
|
||||
// subarg parsers
|
||||
std::pair<arithmetic*, uint32_t> parse_arithmetic(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<variable*, uint32_t> parse_manipulation(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<arithmetic*, parse_context> parse_arithmetic(parse_context ct);
|
||||
std::pair<variable*, parse_context> parse_manipulation(parse_context ct);
|
||||
// arg parser
|
||||
std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t start, const char* end=ARG_END, const char* unexpected=SPECIAL_TOKENS, bool doquote=true);
|
||||
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
|
||||
std::pair<redirect*, uint32_t> parse_redirect(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<redirect*, parse_context> parse_redirect(parse_context ct);
|
||||
// arglist parser
|
||||
std::pair<arglist*, uint32_t> parse_arglist(const char* in, uint32_t size, uint32_t start, bool hard_error=false, std::vector<redirect*>* redirs=nullptr);
|
||||
std::pair<arglist*, parse_context> parse_arglist(parse_context ct, bool hard_error=false, std::vector<redirect*>* redirs=nullptr);
|
||||
// block parsers
|
||||
std::pair<block*, uint32_t> parse_block(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<cmd*, uint32_t> parse_cmd(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<function*, uint32_t> parse_function(const char* in, uint32_t size, uint32_t start, const char* after="()");
|
||||
std::pair<subshell*, uint32_t> parse_subshell(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<brace*, uint32_t> parse_brace(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<case_block*, uint32_t> parse_case(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<if_block*, uint32_t> parse_if(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<for_block*, uint32_t> parse_for(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<while_block*, uint32_t> parse_while(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<block*, parse_context> parse_block(parse_context ct);
|
||||
std::pair<cmd*, parse_context> parse_cmd(parse_context ct);
|
||||
std::pair<function*, parse_context> parse_function(parse_context ct, const char* after="()");
|
||||
std::pair<subshell*, parse_context> parse_subshell(parse_context ct);
|
||||
std::pair<brace*, parse_context> parse_brace(parse_context ct);
|
||||
std::pair<case_block*, parse_context> parse_case(parse_context ct);
|
||||
std::pair<if_block*, parse_context> parse_if(parse_context ct);
|
||||
std::pair<for_block*, parse_context> parse_for(parse_context ct);
|
||||
std::pair<while_block*, parse_context> parse_while(parse_context ct);
|
||||
// pipeline parser
|
||||
std::pair<pipeline*, uint32_t> parse_pipeline(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<pipeline*, parse_context> parse_pipeline(parse_context ct);
|
||||
// condlist parser
|
||||
std::pair<condlist*, uint32_t> parse_condlist(const char* in, uint32_t size, uint32_t start);
|
||||
std::pair<condlist*, parse_context> parse_condlist(parse_context ct);
|
||||
|
||||
#endif //PARSE_HPP
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@
|
|||
#define RESOLVE_HPP
|
||||
|
||||
#include "struc.hpp"
|
||||
#include "parse.hpp"
|
||||
|
||||
extern std::vector<std::string> included;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> do_include_raw(condlist* cmd, std::string const& filename, std::string* ex_dir=nullptr);
|
||||
std::pair<std::string, std::string> do_resolve_raw(condlist* cmd, std::string const& filename, 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* cmd, parse_context ctx, std::string* ex_dir=nullptr);
|
||||
|
||||
bool add_include(std::string const& file);
|
||||
|
||||
void resolve(_obj* sh, std::string* filename);
|
||||
void resolve(shmain* sh);
|
||||
void resolve(_obj* sh, parse_context ctx);
|
||||
|
||||
std::string _pre_cd(std::string const& filename);
|
||||
void _cd(std::string const& dir);
|
||||
|
|
|
|||
|
|
@ -62,13 +62,26 @@ subarg: can be one of
|
|||
|
||||
*/
|
||||
|
||||
struct parse_context {
|
||||
const char* data=NULL;
|
||||
uint64_t size=0;
|
||||
uint64_t i=0;
|
||||
const char* filename="";
|
||||
bool bash=false;
|
||||
const char* expecting="";
|
||||
const char* here_delimiter="";
|
||||
const char* here_doc="";
|
||||
const char operator[](uint64_t a) { return data[a]; }
|
||||
bool has_errored=false;
|
||||
};
|
||||
|
||||
// exceptions
|
||||
class format_error : public std::exception
|
||||
{
|
||||
public:
|
||||
//! @brief Conctructor
|
||||
inline format_error(const std::string& what, const std::string& origin, const std::string& data, int where) { desc=what; index=where; filename=origin; sdat=data; }
|
||||
|
||||
inline format_error(const std::string& what, parse_context const& ctx) { desc=what; index=ctx.i; filename=ctx.filename; sdat=ctx.data; }
|
||||
//! @brief Error message
|
||||
inline const char * what () const throw () {return desc.c_str();}
|
||||
//! @brief Origin of the data, name of imported file, otherwise empty if generated
|
||||
|
|
@ -84,6 +97,7 @@ private:
|
|||
std::string sdat;
|
||||
};
|
||||
|
||||
|
||||
// objects
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -473,7 +473,7 @@ bool debashify_array_set(cmd* in, debashify_params* params)
|
|||
gen=gen.substr(2);
|
||||
gen.pop_back();
|
||||
// create cmd out of arguments
|
||||
arglist* args = parse_arglist( gen.c_str(), gen.size(), 0 ).first;
|
||||
arglist* args = parse_arglist( make_context(gen) ).first;
|
||||
cmd* c = new cmd(args);
|
||||
// cmd first argument is _lxsh_X_create
|
||||
if(params->arrays[varname])
|
||||
|
|
@ -569,7 +569,7 @@ bool debashify_array_set(cmd* in, debashify_params* params)
|
|||
gen=gen.substr(3);
|
||||
gen.pop_back();
|
||||
// create cmd out of arguments
|
||||
arglist* args = parse_arglist( gen.c_str(), gen.size(), 0 ).first;
|
||||
arglist* args = parse_arglist( make_context(gen) ).first;
|
||||
cmd* c = new cmd(args);
|
||||
// cmd first argument is _lxsh_array_create
|
||||
if(params->arrays[varname])
|
||||
|
|
|
|||
121
src/exec.cpp
121
src/exec.cpp
|
|
@ -18,16 +18,16 @@
|
|||
#define PIPE_READ 0
|
||||
#define PIPE_WRITE 1
|
||||
|
||||
std::vector<condlist*> do_include_exec(condlist* cmd, std::string const& filename, FILE* fd)
|
||||
std::vector<condlist*> do_include_exec(condlist* cmd, parse_context ctx, FILE* fd)
|
||||
{
|
||||
std::vector<condlist*> ret;
|
||||
|
||||
std::string dir;
|
||||
auto incs=do_include_raw(cmd, filename, &dir);
|
||||
auto incs=do_include_raw(cmd, ctx, &dir);
|
||||
|
||||
for(auto it: incs)
|
||||
{
|
||||
parse_exec(fd, it.second, it.first);
|
||||
parse_exec(fd, make_context(ctx, it.second, it.first));
|
||||
}
|
||||
// cd back
|
||||
_cd(dir);
|
||||
|
|
@ -36,7 +36,7 @@ std::vector<condlist*> do_include_exec(condlist* cmd, std::string const& filenam
|
|||
}
|
||||
|
||||
// if first is nullptr: is a string
|
||||
std::vector<condlist*> do_resolve_exec(condlist* cmd, std::string const& filename, FILE* fd)
|
||||
std::vector<condlist*> do_resolve_exec(condlist* cmd, parse_context ctx, FILE* fd)
|
||||
{
|
||||
std::vector<condlist*> ret;
|
||||
|
||||
|
|
@ -45,9 +45,9 @@ std::vector<condlist*> do_resolve_exec(condlist* cmd, std::string const& filenam
|
|||
{
|
||||
// get
|
||||
std::string dir;
|
||||
p=do_resolve_raw(cmd, filename, &dir);
|
||||
p=do_resolve_raw(cmd, ctx, &dir);
|
||||
// do parse
|
||||
parse_exec(fd, p.second, filename);
|
||||
parse_exec(fd, make_context(ctx, p.second, p.first));
|
||||
// cd back
|
||||
_cd(dir);
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ std::vector<condlist*> do_resolve_exec(condlist* cmd, std::string const& filenam
|
|||
|
||||
// -- OBJECT CALLS --
|
||||
|
||||
bool resolve_condlist_exec(condlist* in, std::string const& filename, FILE* fd)
|
||||
bool resolve_condlist_exec(condlist* in, parse_context ctx, FILE* fd)
|
||||
{
|
||||
cmd* tc = in->first_cmd();
|
||||
if(tc == nullptr)
|
||||
|
|
@ -71,23 +71,23 @@ bool resolve_condlist_exec(condlist* in, std::string const& filename, FILE* fd)
|
|||
|
||||
if(g_include && strcmd == "%include")
|
||||
{
|
||||
do_include_exec(in, filename, fd);
|
||||
do_include_exec(in, ctx, fd);
|
||||
return true;
|
||||
}
|
||||
else if(g_resolve && strcmd == "%resolve")
|
||||
{
|
||||
do_resolve_exec(in, filename, fd);
|
||||
do_resolve_exec(in, ctx, fd);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool resolve_exec(condlist* in, std::string const& filename, FILE* fd)
|
||||
bool resolve_exec(condlist* in, parse_context ctx, FILE* fd)
|
||||
{
|
||||
if(!resolve_condlist_exec(in, filename, fd))
|
||||
if(!resolve_condlist_exec(in, ctx, fd))
|
||||
{
|
||||
resolve(in, (std::string*) &filename);
|
||||
resolve(in, ctx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -138,60 +138,57 @@ std::string random_string()
|
|||
return ret;
|
||||
}
|
||||
|
||||
void parse_exec(FILE* fd, const char* in, uint32_t size, std::string const& filename)
|
||||
void parse_exec(FILE* fd, parse_context ctx)
|
||||
{
|
||||
uint32_t i=skip_unread(in, size, 0);
|
||||
#ifndef NO_PARSE_CATCH
|
||||
try
|
||||
ctx.i=skip_unread(ctx);
|
||||
|
||||
debashify_params debash_params;
|
||||
list* t_lst=new list;
|
||||
if(t_lst == nullptr)
|
||||
throw std::runtime_error("Alloc error");
|
||||
while(ctx.i<ctx.size)
|
||||
{
|
||||
#endif
|
||||
;
|
||||
debashify_params debash_params;
|
||||
list* t_lst=new list;
|
||||
if(t_lst == nullptr)
|
||||
throw std::runtime_error("Alloc error");
|
||||
while(i<size)
|
||||
auto pp=parse_condlist(ctx);
|
||||
ctx=pp.second;
|
||||
if(ctx.has_errored)
|
||||
{
|
||||
auto pp=parse_condlist(in, size, i);
|
||||
i=pp.second;
|
||||
t_lst->add(pp.first);
|
||||
if(g_resolve || g_include)
|
||||
parse_list_until(ctx, 0);
|
||||
throw std::runtime_error("Aborting due to previous errors");
|
||||
}
|
||||
t_lst->add(pp.first);
|
||||
if(g_resolve || g_include)
|
||||
{
|
||||
if(resolve_exec(t_lst->cls[0], ctx, fd))
|
||||
{
|
||||
if(resolve_exec(t_lst->cls[0], filename, fd))
|
||||
{
|
||||
t_lst->clear();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(options["debashify"])
|
||||
debashify(t_lst, &debash_params);
|
||||
|
||||
|
||||
std::string gen=t_lst->generate(0);
|
||||
t_lst->clear();
|
||||
|
||||
fprintf(fd, "%s", gen.c_str());
|
||||
|
||||
if(i < size)
|
||||
{
|
||||
if(in[i] == '#')
|
||||
; // skip here
|
||||
else if(is_in(in[i], COMMAND_SEPARATOR))
|
||||
i++; // skip on next char
|
||||
else if(is_in(in[i], CONTROL_END))
|
||||
throw PARSE_ERROR(strf("Unexpected token: '%c'", in[i]), i);
|
||||
|
||||
i = skip_unread(in, size, i);
|
||||
t_lst->clear();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
delete t_lst;
|
||||
#ifndef NO_PARSE_CATCH
|
||||
}
|
||||
catch(format_error& e)
|
||||
{
|
||||
throw format_error(e.what(), filename, in, e.where());
|
||||
if(options["debashify"])
|
||||
debashify(t_lst, &debash_params);
|
||||
|
||||
|
||||
std::string gen=t_lst->generate(0);
|
||||
t_lst->clear();
|
||||
|
||||
fprintf(fd, "%s", gen.c_str());
|
||||
|
||||
if(ctx.i < ctx.size)
|
||||
{
|
||||
if(ctx[ctx.i] == '#')
|
||||
; // skip here
|
||||
else if(is_in(ctx[ctx.i], COMMAND_SEPARATOR))
|
||||
ctx.i++; // skip on next char
|
||||
else if(is_in(ctx[ctx.i], CONTROL_END))
|
||||
{
|
||||
format_error(strf("Unexpected token: '%c'", ctx[ctx.i]), ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.i = skip_unread(ctx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
delete t_lst;
|
||||
}
|
||||
|
||||
pid_t forkexec(const char* bin, char *const args[])
|
||||
|
|
@ -230,7 +227,7 @@ int wait_pid(pid_t pid)
|
|||
return WEXITSTATUS(stat);
|
||||
}
|
||||
|
||||
int exec_process(std::string const& runtime, std::vector<std::string> const& args, std::string const& filecontents, std::string const& file)
|
||||
int exec_process(std::string const& runtime, std::vector<std::string> const& args, parse_context ctx)
|
||||
{
|
||||
std::vector<std::string> strargs = split(runtime, " \t");
|
||||
std::vector<char*> runargs;
|
||||
|
|
@ -250,8 +247,6 @@ int exec_process(std::string const& runtime, std::vector<std::string> const& arg
|
|||
runargs.push_back(NULL);
|
||||
|
||||
pid_t pid=0;
|
||||
// std::string test="echo Hello world\nexit 10\n";
|
||||
// fprintf(ffd, "%s\n",, test.c_str(), test.size());
|
||||
FILE* ffd=0;
|
||||
try
|
||||
{
|
||||
|
|
@ -264,7 +259,7 @@ int exec_process(std::string const& runtime, std::vector<std::string> const& arg
|
|||
}
|
||||
for(auto it: lxsh_extend_fcts)
|
||||
fprintf(ffd, "%s\n", it.second.code);
|
||||
parse_exec(ffd, filecontents, file);
|
||||
parse_exec(ffd, ctx);
|
||||
}
|
||||
catch(std::runtime_error& e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ std::string case_block::generate(int ind)
|
|||
// replace ;; from last case with ;
|
||||
if(this->cases.size()>0 && opt_minify)
|
||||
{
|
||||
ret.erase(ret.size()-1, 2);
|
||||
ret.pop_back();
|
||||
}
|
||||
|
||||
// close case
|
||||
|
|
|
|||
26
src/main.cpp
26
src/main.cpp
|
|
@ -79,6 +79,9 @@ int main(int argc, char* argv[])
|
|||
|
||||
// do parsing
|
||||
bool shebang_is_bin=false;
|
||||
bool parse_bash=false;
|
||||
parse_context ctx;
|
||||
std::string binshebang;
|
||||
for(uint32_t i=0 ; i<args.size() ; i++)
|
||||
{
|
||||
std::string file = args[i];
|
||||
|
|
@ -91,7 +94,9 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
first_run=false;
|
||||
// resolve shebang
|
||||
shebang_is_bin = ( basename(argv[0]) == basename(shebang) );
|
||||
binshebang = basename(shebang);
|
||||
shebang_is_bin = ( basename(argv[0]) == binshebang );
|
||||
parse_bash = (options["debashify"] || binshebang == "bash" || binshebang == "lxsh");
|
||||
|
||||
// detect if need execution
|
||||
if(options['e'])
|
||||
|
|
@ -108,7 +113,10 @@ int main(int argc, char* argv[])
|
|||
throw std::runtime_error("Option -e must be before file");
|
||||
|
||||
if(shebang_is_bin) // enable debashify option
|
||||
{
|
||||
shebang="#!/bin/sh";
|
||||
options["debashify"].activated=true;
|
||||
}
|
||||
|
||||
oneshot_opt_process(argv[0]);
|
||||
get_opts();
|
||||
|
|
@ -119,25 +127,27 @@ int main(int argc, char* argv[])
|
|||
if(!add_include(file))
|
||||
continue;
|
||||
|
||||
ctx.data=filecontents.data();
|
||||
|
||||
|
||||
ctx = make_context(filecontents, file, parse_bash);
|
||||
if(is_exec)
|
||||
{
|
||||
if(options["debashify"])
|
||||
shebang = "#!/bin/sh";
|
||||
if(options["debashify"] || basename(shebang) == "bash")
|
||||
g_bash = true;
|
||||
args.erase(args.begin());
|
||||
return exec_process(shebang.substr(2), args, filecontents, file);
|
||||
return exec_process(shebang.substr(2), args, ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
tsh = parse_text(filecontents, file);
|
||||
auto pp = parse_text(ctx);
|
||||
tsh = pp.first;
|
||||
ctx = pp.second;
|
||||
if(shebang_is_bin) // resolve lxsh shebang to sh
|
||||
tsh->shebang="#!/bin/sh";
|
||||
|
||||
/* mid processing */
|
||||
// resolve/include
|
||||
if(g_include || g_resolve)
|
||||
resolve(tsh);
|
||||
resolve(tsh, ctx);
|
||||
|
||||
// concatenate to main
|
||||
sh->concat(tsh);
|
||||
|
|
|
|||
1576
src/parse.cpp
1576
src/parse.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -431,7 +431,7 @@ std::set<std::string> get_processors(std::string const& in)
|
|||
if(ln.size()>1 && ln[0] == '#' && is_alphanum(ln[1]))
|
||||
{
|
||||
i+=ln.size();
|
||||
ret.insert(get_word(ln.c_str(), ln.size(), 1, SEPARATORS).first);
|
||||
ret.insert(get_word(make_context(ln.substr(1)), SEPARATORS).first);
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
|
@ -450,7 +450,8 @@ bool r_do_string_processor(_obj* in)
|
|||
{
|
||||
try
|
||||
{
|
||||
shmain* tsh = parse_text(t->val.substr(1, t->val.size()-2));
|
||||
std::string stringcode = t->val.substr(1, t->val.size()-2);
|
||||
shmain* tsh = parse_text( stringcode ).first;
|
||||
require_rescan_all();
|
||||
if(options["remove-unused"])
|
||||
delete_unused( tsh, re_var_exclude, re_fct_exclude );
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ void _cd(std::string const& dir)
|
|||
// -- COMMANDS --
|
||||
|
||||
// return <name, contents>[]
|
||||
std::vector<std::pair<std::string, std::string>> do_include_raw(condlist* cmd, std::string const& filename, 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;
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ std::vector<std::pair<std::string, std::string>> do_include_raw(condlist* cmd, s
|
|||
std::string dir;
|
||||
if(g_cd && !opts['C'])
|
||||
{
|
||||
dir=_pre_cd(filename);
|
||||
dir=_pre_cd(ctx.filename);
|
||||
if(ex_dir!=nullptr)
|
||||
*ex_dir=dir;
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ std::vector<std::pair<std::string, std::string>> do_include_raw(condlist* cmd, s
|
|||
}
|
||||
|
||||
//
|
||||
std::pair<std::string, std::string> do_resolve_raw(condlist* cmd, std::string const& filename, 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;
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ std::pair<std::string, std::string> do_resolve_raw(condlist* cmd, std::string co
|
|||
std::string dir;
|
||||
if(g_cd && !opts['C'])
|
||||
{
|
||||
dir=_pre_cd(filename);
|
||||
dir=_pre_cd(ctx.filename);
|
||||
if(ex_dir!=nullptr)
|
||||
*ex_dir=dir;
|
||||
}
|
||||
|
|
@ -152,23 +152,33 @@ std::pair<std::string, std::string> do_resolve_raw(condlist* cmd, std::string co
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::vector<condlist*> do_include_parse(condlist* cmd, std::string const& filename)
|
||||
std::vector<condlist*> do_include_parse(condlist* cmd, parse_context ctx)
|
||||
{
|
||||
std::vector<condlist*> ret;
|
||||
|
||||
std::string dir;
|
||||
auto incs=do_include_raw(cmd, filename, &dir);
|
||||
auto incs=do_include_raw(cmd, ctx, &dir);
|
||||
|
||||
for(auto it: incs)
|
||||
std::vector<shmain*> shs;
|
||||
shs.resize(incs.size());
|
||||
|
||||
for(uint32_t i=0; i<incs.size(); i++)
|
||||
{
|
||||
parse_context newctx = make_context(ctx, incs[i].second, incs[i].first);
|
||||
auto pp = parse_text(newctx);
|
||||
shmain* sh = pp.first;
|
||||
resolve(sh, pp.second);
|
||||
shs[i] = sh;
|
||||
}
|
||||
for(auto sh: shs)
|
||||
{
|
||||
shmain* sh=parse_text(it.second, it.first);
|
||||
resolve(sh);
|
||||
// get the cls
|
||||
ret.insert(ret.end(), sh->lst->cls.begin(), sh->lst->cls.end());
|
||||
// safety and cleanup
|
||||
sh->lst->cls.resize(0);
|
||||
delete sh;
|
||||
}
|
||||
shs.resize(0);
|
||||
// cd back
|
||||
_cd(dir);
|
||||
|
||||
|
|
@ -176,7 +186,7 @@ std::vector<condlist*> do_include_parse(condlist* cmd, std::string const& filena
|
|||
}
|
||||
|
||||
// if first is nullptr: is a string
|
||||
std::vector<condlist*> do_resolve_parse(condlist* cmd, std::string const& filename)
|
||||
std::vector<condlist*> do_resolve_parse(condlist* cmd, parse_context ctx)
|
||||
{
|
||||
std::vector<condlist*> ret;
|
||||
|
||||
|
|
@ -185,10 +195,13 @@ std::vector<condlist*> do_resolve_parse(condlist* cmd, std::string const& filena
|
|||
{
|
||||
// get
|
||||
std::string dir;
|
||||
p=do_resolve_raw(cmd, filename, &dir);
|
||||
p=do_resolve_raw(cmd, ctx, &dir);
|
||||
|
||||
// do parse
|
||||
shmain* sh = parse_text(p.second);
|
||||
resolve(sh);
|
||||
parse_context newctx = make_context(ctx, p.second, '`'+p.first+'`');
|
||||
auto pp = parse_text(newctx);
|
||||
shmain* sh = pp.first;
|
||||
resolve(sh, pp.second);
|
||||
// get the cls
|
||||
ret = sh->lst->cls;
|
||||
// safety and cleanup
|
||||
|
|
@ -207,7 +220,7 @@ std::vector<condlist*> do_resolve_parse(condlist* cmd, std::string const& filena
|
|||
|
||||
// -- OBJECT CALLS --
|
||||
|
||||
std::pair< std::vector<condlist*> , bool > resolve_condlist(condlist* in, std::string const& filename)
|
||||
std::pair< std::vector<condlist*> , bool > resolve_condlist(condlist* in, parse_context ctx)
|
||||
{
|
||||
cmd* tc = in->first_cmd();
|
||||
if(tc == nullptr)
|
||||
|
|
@ -216,14 +229,14 @@ std::pair< std::vector<condlist*> , bool > resolve_condlist(condlist* in, std::s
|
|||
std::string const& strcmd=tc->arg_string(0);
|
||||
|
||||
if(g_include && strcmd == "%include")
|
||||
return std::make_pair(do_include_parse(in, filename), true);
|
||||
return std::make_pair(do_include_parse(in, ctx), true);
|
||||
else if(g_resolve && strcmd == "%resolve")
|
||||
return std::make_pair(do_resolve_parse(in, filename), true);
|
||||
return std::make_pair(do_resolve_parse(in, ctx), true);
|
||||
else
|
||||
return std::make_pair(std::vector<condlist*>(), false);
|
||||
}
|
||||
|
||||
std::pair< std::vector<arg*> , bool > resolve_arg(arg* in, std::string const& filename, bool forcequote=false)
|
||||
std::pair< std::vector<arg*> , bool > resolve_arg(arg* in, parse_context ctx, bool forcequote=false)
|
||||
{
|
||||
std::vector<arg*> ret;
|
||||
if(in == nullptr)
|
||||
|
|
@ -249,12 +262,12 @@ std::pair< std::vector<arg*> , bool > resolve_arg(arg* in, std::string const& fi
|
|||
std::string fulltext;
|
||||
if(g_include && strcmd == "%include")
|
||||
{
|
||||
for(auto it: do_include_raw(tc, filename) )
|
||||
for(auto it: do_include_raw(tc, ctx) )
|
||||
fulltext += it.second;
|
||||
}
|
||||
else if(g_resolve && strcmd == "%resolve")
|
||||
{
|
||||
fulltext = do_resolve_raw(tc, filename).second;
|
||||
fulltext = do_resolve_raw(tc, ctx).second;
|
||||
}
|
||||
else // skip
|
||||
continue;
|
||||
|
|
@ -320,10 +333,10 @@ std::pair< std::vector<arg*> , bool > resolve_arg(arg* in, std::string const& fi
|
|||
return std::make_pair(ret, has_resolved);
|
||||
}
|
||||
|
||||
|
||||
void resolve(_obj* in, parse_context* ctx);
|
||||
// -- RECURSIVE CALL --
|
||||
|
||||
bool r_resolve(_obj* o, std::string* filename)
|
||||
bool r_resolve(_obj* o, parse_context* ct)
|
||||
{
|
||||
switch(o->type)
|
||||
{
|
||||
|
|
@ -336,7 +349,7 @@ bool r_resolve(_obj* o, std::string* filename)
|
|||
auto t = dynamic_cast<list*>(o);
|
||||
for(uint32_t i=0 ; i<t->cls.size() ; i++)
|
||||
{
|
||||
auto r=resolve_condlist(t->cls[i], *filename);
|
||||
auto r=resolve_condlist(t->cls[i], *ct);
|
||||
if(r.second)
|
||||
{
|
||||
// add new cls after current
|
||||
|
|
@ -349,7 +362,7 @@ bool r_resolve(_obj* o, std::string* filename)
|
|||
}
|
||||
else
|
||||
{
|
||||
resolve(t->cls[i], filename);
|
||||
resolve(t->cls[i], ct);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -359,7 +372,7 @@ bool r_resolve(_obj* o, std::string* filename)
|
|||
auto t = dynamic_cast<arglist*>(o);
|
||||
for(uint32_t i=0 ; i<t->size() ; i++)
|
||||
{
|
||||
auto r=resolve_arg(t->args[i], *filename);
|
||||
auto r=resolve_arg(t->args[i], *ct);
|
||||
if(r.first.size()>0)
|
||||
{
|
||||
// add new args
|
||||
|
|
@ -371,7 +384,7 @@ bool r_resolve(_obj* o, std::string* filename)
|
|||
}
|
||||
else
|
||||
{
|
||||
resolve(t->args[i], filename);
|
||||
resolve(t->args[i], ct);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -381,12 +394,12 @@ bool r_resolve(_obj* o, std::string* filename)
|
|||
auto t = dynamic_cast<cmd*>(o);
|
||||
for(auto it: t->var_assigns) // var assigns
|
||||
{
|
||||
resolve_arg(it.second, *filename, true); // force quoted
|
||||
resolve(it.second, filename);
|
||||
resolve_arg(it.second, *ct, true); // force quoted
|
||||
resolve(it.second, ct);
|
||||
}
|
||||
for(auto it: t->redirs)
|
||||
resolve(it, filename);
|
||||
resolve(t->args, filename);
|
||||
resolve(it, ct);
|
||||
resolve(t->args, ct);
|
||||
return false;
|
||||
}; break;
|
||||
case _obj::block_case :
|
||||
|
|
@ -394,15 +407,15 @@ bool r_resolve(_obj* o, std::string* filename)
|
|||
auto t = dynamic_cast<case_block*>(o);
|
||||
for(auto sc: t->cases)
|
||||
{
|
||||
resolve_arg(t->carg, *filename, true); // force quoted
|
||||
resolve(t->carg, filename);
|
||||
resolve_arg(t->carg, *ct, true); // force quoted
|
||||
resolve(t->carg, ct);
|
||||
|
||||
for(auto it: sc.first)
|
||||
{
|
||||
resolve_arg(it, *filename, true); // force quoted
|
||||
resolve(it, filename);
|
||||
resolve_arg(it, *ct, true); // force quoted
|
||||
resolve(it, ct);
|
||||
}
|
||||
resolve(sc.second, filename);
|
||||
resolve(sc.second, ct);
|
||||
}
|
||||
}; break;
|
||||
default: break;
|
||||
|
|
@ -411,12 +424,13 @@ bool r_resolve(_obj* o, std::string* filename)
|
|||
}
|
||||
|
||||
// recursive call of resolve
|
||||
void resolve(_obj* in, std::string* filename)
|
||||
void resolve(_obj* in, parse_context* ctx)
|
||||
{
|
||||
recurse(r_resolve, in, filename);
|
||||
recurse(r_resolve, in, ctx);
|
||||
}
|
||||
|
||||
void resolve(shmain* sh)
|
||||
// recursive call of resolve
|
||||
void resolve(_obj* in, parse_context ctx)
|
||||
{
|
||||
recurse(r_resolve, sh, &sh->filename);
|
||||
recurse(r_resolve, in, &ctx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
arg* make_arg(std::string const& in)
|
||||
{
|
||||
return parse_arg(in.c_str(), in.size(), 0).first;
|
||||
return parse_arg(make_context(in)).first;
|
||||
}
|
||||
|
||||
cmd* make_cmd(std::vector<std::string> const& args)
|
||||
|
|
@ -34,7 +34,7 @@ cmd* make_cmd(std::vector<arg*> const& args)
|
|||
|
||||
cmd* make_cmd(std::string const& in)
|
||||
{
|
||||
return parse_cmd(in.c_str(), in.size(), 0).first;
|
||||
return parse_cmd(make_context(in)).first;
|
||||
}
|
||||
|
||||
pipeline* make_pipeline(std::vector<block*> const& bls)
|
||||
|
|
@ -48,22 +48,22 @@ pipeline* make_pipeline(std::vector<block*> const& bls)
|
|||
|
||||
pipeline* make_pipeline(std::string const& in)
|
||||
{
|
||||
return parse_pipeline(in.c_str(), in.size(), 0).first;
|
||||
return parse_pipeline(make_context(in)).first;
|
||||
}
|
||||
|
||||
condlist* make_condlist(std::string const& in)
|
||||
{
|
||||
return parse_condlist(in.c_str(), in.size(), 0).first;
|
||||
return parse_condlist(make_context(in)).first;
|
||||
}
|
||||
|
||||
list* make_list(std::string const& in)
|
||||
{
|
||||
return parse_list_until(in.c_str(), in.size(), 0, 0).first;
|
||||
return parse_list_until(make_context(in), 0).first;
|
||||
}
|
||||
|
||||
block* make_block(std::string const& in)
|
||||
{
|
||||
return parse_block(in.c_str(), in.size(), 0).first;
|
||||
return parse_block(make_context(in)).first;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ block* make_block(std::string const& in)
|
|||
|
||||
arg* copy(arg* in) {
|
||||
std::string str = in->generate(0);
|
||||
return parse_arg(str.c_str(), str.size(), 0).first;
|
||||
return parse_arg(make_context(str)).first;
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
|
|
|||
Loading…
Reference in a new issue