From ca41c2724639350b7449e20c4d68d73a4bc0efde Mon Sep 17 00:00:00 2001 From: zawz Date: Fri, 28 Aug 2020 10:57:28 +0200 Subject: [PATCH] Init sources --- .gitignore | 5 + Makefile | 62 ++++++ include/options.hpp | 36 ++++ include/parse.hpp | 17 ++ include/struc.hpp | 175 +++++++++++++++++ include/util.hpp | 32 ++++ lxsh | Bin 0 -> 166392 bytes src/generate.cpp | 332 ++++++++++++++++++++++++++++++++ src/main.cpp | 91 +++++++++ src/options.cpp | 76 ++++++++ src/parse.cpp | 458 ++++++++++++++++++++++++++++++++++++++++++++ src/struc.cpp | 54 ++++++ src/util.cpp | 54 ++++++ 13 files changed, 1392 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 include/options.hpp create mode 100644 include/parse.hpp create mode 100644 include/struc.hpp create mode 100644 include/util.hpp create mode 100755 lxsh create mode 100644 src/generate.cpp create mode 100644 src/main.cpp create mode 100644 src/options.cpp create mode 100644 src/parse.cpp create mode 100644 src/struc.cpp create mode 100644 src/util.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6e760d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/obj +/test +/run-tests.sh +/Zmakefile +/TODO diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3d50c54 --- /dev/null +++ b/Makefile @@ -0,0 +1,62 @@ +## CONFIG ## + +IDIR=include +SRCDIR=src +ODIR=obj +BINDIR=. + +# binary name, default name of dir +NAME = $(shell readlink -f . | xargs basename) + +# global links +LDFLAGS = -lpthread + +# compiler +CC=g++ +# compiler flags +CXXFLAGS= -I$(IDIR) -Wall -pedantic -std=c++17 +ifeq ($(DEBUG),true) + # debugging flags + CC=clang++ + CXXFLAGS += -g +else + # release flags + CXXFLAGS += -O2 +endif +ifeq ($(STATIC),true) + # static links + LDFLAGS += -l:libztd.a +else + # dynamic links + LDFLAGS += -lztd +endif + +## END CONFIG ## + + + +$(shell mkdir -p $(ODIR)) +$(shell mkdir -p $(BINDIR)) + +# automatically find .h and .hpp +DEPS = $(shell find $(IDIR) -type f -regex '.*\.hp?p?') +# automatically find .c and .cpp and make the corresponding .o rule +OBJ = $(shell find $(SRCDIR) -type f -regex '.*\.cp?p?' | sed 's|\.cpp|.o|g;s|\.c|.o|g;s|^$(SRCDIR)/|$(ODIR)/|g') + +$(ODIR)/%.o: $(SRCDIR)/%.c $(DEPS) + $(CC) $(CXXFLAGS) -c -o $@ $< + +$(ODIR)/%.o: $(SRCDIR)/%.cpp $(DEPS) + $(CC) $(CXXFLAGS) -c -o $@ $< + +$(BINDIR)/$(NAME): $(OBJ) + $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ + +test: $(BINDIR)/$(NAME) + $(BINDIR)/$(NAME) + +clean: + rm $(ODIR)/*.o + +clear: + rm $(BINDIR)/$(NAME) diff --git a/include/options.hpp b/include/options.hpp new file mode 100644 index 0000000..45f724d --- /dev/null +++ b/include/options.hpp @@ -0,0 +1,36 @@ +#ifndef OPTIONS_HPP +#define OPTIONS_HPP + +#include + +extern ztd::option_set options; + +extern bool opt_minimize; + +ztd::option_set gen_options(); +void print_help(const char* arg0); + +void print_include_help(); +void print_resolve_help(); + +/** +%include [options] +options: + -s single quote contents + -d double quote contents + -e escape chars. For double quotes + -r include raw text, don't parse. Don't count as included + -f include even if already included. Don't count as included +*/ +ztd::option_set create_include_opts(); + +/** +%resolve [options] +options: + -e escape chars. For double quotes + -p parse as shell code + -f ignore non zero return values +*/ +ztd::option_set create_resolve_opts(); + +#endif //OPTIONS_HPP diff --git a/include/parse.hpp b/include/parse.hpp new file mode 100644 index 0000000..2bd9b2f --- /dev/null +++ b/include/parse.hpp @@ -0,0 +1,17 @@ +#ifndef PARSE_HPP +#define PARSE_HPP + +#include "struc.hpp" + +#include + +#include + +extern std::string g_origin; + +std::string import_file(std::string const& path); + +block parse(const char* in, uint32_t size); +inline block parse(std::string const& in) { return parse(in.c_str(), in.size()); } + +#endif //PARSE_HPP diff --git a/include/struc.hpp b/include/struc.hpp new file mode 100644 index 0000000..f9bc0ef --- /dev/null +++ b/include/struc.hpp @@ -0,0 +1,175 @@ +#ifndef STRUC_HPP +#define STRUC_HPP + +#include +#include +#include + +#include +#include + +/* +structure: + +block: +- group + - brace: condlist[] + - subsh: condlist[] +- cmd: arglist[] +- if + - pair[] + +condlist: + pipeline[] + +pipeline: + block[] + +arglist: + arg[] + +arg: +- raw +- subarg[] + +subarg: +- raw +- variable +- block: subshell + + +*/ + +#define AND_OP false +#define OR_OP true + +class condlist; +class block; +class pipeline; +class arg; +class subarg; + +typedef std::vector list_t; + +block make_cmd(std::vector args); + +bool add_include(std::string const& file); + +class arg +{ +public: + arg() { ; } + arg(std::string const& str) {this->setstring(str);} + + void setstring(std::string const& str); + + std::string raw; + + std::vector sa; + + std::string string(); + std::string generate(int ind); +}; + +class arglist +{ +public: + inline void add(arg const& in) { args.push_back(in); } + inline void push_back(arg const& in) { args.push_back(in); } + + std::vector args; + + std::vector strargs(uint32_t start); + + inline uint64_t size() { return args.size(); } + inline arg& operator[](uint32_t i) { return args[i]; } + + std::string generate(int ind); +}; + +class redir +{ +public: + enum redirtype { none, write, append, read, raw } ; + redir(redirtype in=none) { type=in; } + redirtype type; + arg val; +}; + +class block +{ +public: + enum blocktype { none, subshell, brace, main, cmd, function, case_block, for_block, if_block, while_block}; + block() { type=none; } + block(blocktype in) { type=in; } + blocktype type; + // subshell/brace/main + list_t cls; + // cmd + arglist args; + + // case + arg carg; + std::vector< std::pair > cases; + + // main: shebang + // function: name + std::string shebang; + + // subshell: return the containing cmd, if it is a single command + block* single_cmd(); + + std::string generate(int ind=0, bool print_shebang=true); + +private: + std::string generate_cmd(int ind); + std::string generate_case(int ind); +}; + +class pipeline +{ +public: + pipeline() {;} + pipeline(block const& bl) { cmds.push_back(bl); } + inline void add(block bl) { this->cmds.push_back(bl); } + std::vector cmds; + + std::string generate(int ind); +}; + +class condlist +{ +public: + condlist() { parallel=false; } + condlist(block const& pl) { parallel=false; this->add(pl);} + condlist(pipeline const& pl) { parallel=false; this->add(pl);} + void add(pipeline const& pl, bool or_op=false); + + bool parallel; + // don't push_back here + std::vector or_ops; + std::vector pls; + + std::string generate(int ind); +}; + + +class subarg +{ +public: + enum argtype { string, subshell }; + subarg(argtype in) { this->type=in; } + subarg(std::string const& in="") { type=string; val=in; } + subarg(block const& in) { type=subshell; sbsh=in; } + + argtype type; + // raw string + std::string val; + // subshell + block sbsh; + + std::string generate(int ind); +}; + + +#endif //STRUC_HPP diff --git a/include/util.hpp b/include/util.hpp new file mode 100644 index 0000000..9c1ae99 --- /dev/null +++ b/include/util.hpp @@ -0,0 +1,32 @@ +#ifndef UTIL_HPP +#define UTIL_HPP + +#include +#include +#include +#include +#include + +#define INDENT indent(ind) + +extern std::string indenting_string; + +std::string indent(int n); + +std::vector split(std::string const& in, char c); + +std::string escape_str(std::string const& in); + +template +std::string strf( const std::string& format, Args ... args ) +{ + size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0' + if( size <= 0 ){ throw std::runtime_error( "Error during formatting." ); } + std::unique_ptr buf( new char[ size ] ); + snprintf( buf.get(), size, format.c_str(), args ... ); + return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside +} + +std::string delete_brackets(std::string const& in); + +#endif //UTIL_HPP diff --git a/lxsh b/lxsh new file mode 100755 index 0000000000000000000000000000000000000000..65272eec67c7a811537c40280f3fa7326219ac80 GIT binary patch literal 166392 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

hVNaPZnC@1`489lhB16R05 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 + +#include "util.hpp" +#include "options.hpp" +#include "parse.hpp" + +std::vector included; + +bool is_sub_special_cmd(std::string in) +{ + return in == "%include_sub" || in == "%resolve_sub"; +} + +std::string arg::generate(int ind) +{ + std::string ret; + for(auto it: sa) + { + ret += it.generate(ind); + } + return ret; +} + +std::string arglist::generate(int ind) +{ + std::string ret; + + for(auto it: args) + { + ret += it.generate(ind); + ret += ' '; + } + + ret.pop_back(); + + return ret; +} + +std::string pipeline::generate(int ind) +{ + std::string ret; + + ret += cmds[0].generate(ind); + for(uint32_t i=1 ; i args) +{ + std::string ret; + for(auto it: args) + ret += it + ' '; + ret.pop_back(); + return ret; +} + +std::string generate_resolve(std::vector args, int ind) +{ + auto opts=create_resolve_opts(); + auto rargs = opts.process(args, false, true, false); + + std::string cmd=concatargs(rargs); + auto p=ztd::shp("exec "+cmd); + + if(!opts['f'] && p.second!=0) + { + throw std::runtime_error( strf("command `%s` returned %u", cmd.c_str(), p.second) ); + } + while(p.first[p.first.size()-1] == '\n') + p.first.pop_back(); + + if(opts['p']) + { + block bl = parse(p.first); + std::string ret = bl.generate(ind, false); + std::string tmpind=INDENT; + ret = ret.substr(tmpind.size()); + ret.pop_back(); // remove \n + return ret; + } + else + { + return p.first; + } +} + +std::string generate_include(std::vector args, int ind) +{ + std::string ret; + + auto opts=create_include_opts(); + auto rargs = opts.process(args, false, true, false); + + std::string quote; + if(opts['s']) + quote = '\''; + else if(opts['d']) + quote = '"'; + + // do shell resolution + std::string command="for I in "; + for(auto it: rargs) + command += it + ' '; + command += "; do echo $I ; done"; + std::string inc=ztd::sh(command); + + auto v = split(inc, '\n'); + + std::string file; + block bl; + bool indent_remove=true; + + for(auto it : v) + { + if( opts['f'] || // force include + add_include(it) ) // not already included + { + file=import_file(it); + if(opts['r']) + ret += file; + else + { + try + { + bl = parse(quote + file + quote); + } + catch(ztd::format_error& e) + { + throw ztd::format_error(e.what(), it, e.data(), e.where()); + } + file = bl.generate(ind, false); + if(indent_remove) + { + indent_remove=false; + std::string tmpind=INDENT; + file = file.substr(tmpind.size()); + } + ret += file; + } + } + } + + if(!opts['r']) + ret.pop_back(); + + return ret; +} + +std::string block::generate_cmd(int ind) +{ + std::string ret; + if(args.size()<=0) + return ""; + std::string cmd=args[0].raw; + if(cmd == "%include" || cmd == "%include_s") + { + ret += generate_include(args.strargs(1), ind); + } + else if(cmd == "%resolve" || cmd == "%resolve_s") + { + ret += generate_resolve(args.strargs(1), ind); + } + else + ret = args.generate(ind); + return ret; +} + +std::string block::generate_case(int ind) +{ + std::string ret; + ret += "case " + carg.generate(ind) + " in\n"; + ind++; + for(auto cs: this->cases) + { + if(!opt_minimize) ret += INDENT; + ret += cs.first.generate(ind) + ')'; + if(!opt_minimize) ret += '\n'; + for(auto it: cs.second) + ret += it.generate(ind+1); + if(opt_minimize) + { + if(ret[ret.size()-1] == '\n') + ret.pop_back(); + } + else + { + ind++; + ret += INDENT; + ind--; + } + ret += ";;\n"; + } + ind--; + if(!opt_minimize) ret += INDENT; + ret += "esac"; + return ret; +} + +std::string block::generate(int ind, bool print_shebang) +{ + std::string ret; + + if(type==cmd) + { + ret += generate_cmd(ind); + } + else + { + if(type==function) + { + ret += shebang + "()"; + if(!opt_minimize) ret += '\n' + INDENT; + ret += "{\n"; + for(auto it: cls) + ret += it.generate(ind+1); + if(!opt_minimize) + ret += INDENT; + ret += '}'; + } + else if(type==subshell) + { + ret += '('; + if(!opt_minimize) ret += '\n'; + for(auto it: cls) + ret += it.generate(ind+1); + if(opt_minimize) + ret.pop_back(); + else + ret += INDENT; + ret += ')'; + } + else if(type==brace) + { + ret += "{\n" ; + for(auto it: cls) + ret += it.generate(ind+1); + if(!opt_minimize) + ret += INDENT; + ret += '}'; + } + else if(type==main) + { + if(print_shebang && shebang!="") + ret += shebang + '\n'; + for(auto it: cls) + ret += it.generate(ind); + } + else if(type==case_block) + { + ret += generate_case(ind); + } + + std::string t = generate_cmd(ind); // leftover redirections + if(t!="") + { + if(!opt_minimize) ret += ' '; + ret += t; + } + + } + + return ret; +} + +std::string subarg::generate(int ind) +{ + std::string ret; + if(type == subarg::string) + { + ret += val; + } + else if(type == subarg::subshell) + { + // includes and resolves inside command substitutions + // resolve here and not inside subshell + block* cmd = sbsh.single_cmd(); + if( cmd != nullptr && (cmd->args[0].raw == "%include" || cmd->args[0].raw == "%resolve") ) + { + ret += cmd->generate(ind); + } + // regular substitution + else + { + ret += '$'; + ret += sbsh.generate(ind); + } + } + return ret; +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..7d4deef --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,91 @@ +#include + +#include + +#include +#include + +#include + +#include "struc.hpp" +#include "parse.hpp" +#include "options.hpp" + +int main(int argc, char* argv[]) +{ + auto args=options.process(argc, argv); + + if(options['m']) + opt_minimize=true; + + bool piped=false; + + if(options['h']) + { + print_help(argv[0]); + return 1; + } + if(options["help-commands"]) + { + print_include_help(); + printf("\n\n"); + print_resolve_help(); + return 1; + } + + std::string file; + if(args.size() > 0) + { + if(args[0] == "-") + { + piped=true; + file = "/dev/stdin"; + } + else + file=args[0]; + } + else + { + if(isatty(fileno(stdin))) + { + print_help(argv[0]); + return 1; + } + else + { + piped=true; + file = "/dev/stdin"; + } + } + + if(!piped && !options['C']) + { + std::string dir=ztd::exec("dirname", file).first; + dir.pop_back(); + file=ztd::exec("basename", file).first; + file.pop_back(); + chdir(dir.c_str()); + } + + g_origin=file; + add_include(file); + + if(args.size()>0) + { + try + { + block sh(parse(import_file(file))); + std::cout << sh.generate(); + } + catch(ztd::format_error& e) + { + printFormatException(e); + } + catch(std::exception& e) + { + std::cerr << e.what() << std::endl; + } + } + + return 0; +} diff --git a/src/options.cpp b/src/options.cpp new file mode 100644 index 0000000..fa0c6e0 --- /dev/null +++ b/src/options.cpp @@ -0,0 +1,76 @@ +#include "options.hpp" + +ztd::option_set options = gen_options(); +bool opt_minimize; + +ztd::option_set gen_options() +{ + ztd::option_set ret; + ret.add(ztd::option('h', "help", false, "Display this help message")); + ret.add(ztd::option('m', "minimize", false, "Minimize code")); + ret.add(ztd::option('C', "no-cd", false, "Don't change directories")); + ret.add(ztd::option("help-commands", false, "Print help for linker commands")); + return ret; +} + +ztd::option_set create_include_opts() +{ + ztd::option_set opts; + opts.add( + ztd::option('s', false, "Single quote contents"), + ztd::option('d', false, "Double quote contents"), + // ztd::option('e', false, "Escape for double quotes"), + ztd::option('r', false, "Include raw contents, don't parse"), + 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 opts; + opts.add( + // ztd::option('e', false, "Escape for double quotes"), + ztd::option('p', false, "Parse contents as shell code"), + ztd::option('f', false, "Ignore non-zero return values") + ); + return opts; +} + +void print_help(const char* arg0) +{ + printf("%s [options] [file]\n", arg0); + printf("Link extended shell, allows file including and command resolving\n"); + printf("See --help-commands for help on linker commands\n"); + printf("\n"); + printf("Options:\n"); + options.print_help(3,20); +} + +void print_include_help() +{ + printf("%%include [options] \n"); + printf("Include the targeted files. Paths are relative to folder of current file\n"); + printf(" - Regular shell processing applies to the file arguments\n"); + printf(" - Only includes not already included files\n"); + printf(" - `%%include` in command substitutions replaces the substitution\n"); + printf(" =>`%%include_s` can be used inside a substitution to prevent this\n"); + printf("\n"); + + ztd::option_set opts=create_include_opts(); + printf("Options:\n"); + opts.print_help(3,7); +} +void print_resolve_help() +{ + printf("%%resolve [options] \n"); + printf("Execute shell command and substitute output. Paths is from folder of current file\n"); + printf(" - Fails if return value is not 0. Can be ignored with -f\n"); + printf(" - `%%resolve` in command substitutions replaces the substitution\n"); + printf(" =>`%%resolve_s` can be used inside a substitution to prevent this\n"); + printf("\n"); + + ztd::option_set opts=create_resolve_opts(); + printf("Options:\n"); + opts.print_help(3,7); +} diff --git a/src/parse.cpp b/src/parse.cpp new file mode 100644 index 0000000..39e4351 --- /dev/null +++ b/src/parse.cpp @@ -0,0 +1,458 @@ +#include "parse.hpp" + +#include +#include +#include + +#include "util.hpp" + +std::string g_origin; + +inline bool is_in(char c, const char* set) +{ + return index(set, c) != NULL; +} + +inline bool is_alphanum(char c) +{ + return (c >= 'a' && c<='z') || (c >= 'A' && c<='Z') || (c >= '0' && c<='9'); +} +inline bool is_alpha(char c) +{ + return (c >= 'a' && c<='z') || (c >= 'A' && c<='Z'); +} + +bool word_eq(const char* word, const char* in, uint32_t size, uint32_t start, const char* end_set=NULL) +{ + uint32_t wordsize=strlen(word); + if(wordsize > size-start) + return false; + if(strncmp(word, in+start, wordsize) == 0) + { + if(end_set==NULL) + return true; + // end set + if(wordsize < size-start) + return is_in(in[start+wordsize], end_set); + } + return false; +} + +uint32_t skip_chars(const char* in, uint32_t size, uint32_t start, const char* set) +{ + for(uint32_t i=start; i parse_subshell(const char* in, uint32_t size, uint32_t start); + +// parse one argument +// must start at a read char +// ends at either " \t|&;\n()" +std::pair parse_arg(const char* in, uint32_t size, uint32_t start) +{ + arg ret; + // j : start of subarg + uint32_t i=start,j=start; + while(i") && in[i+1]=='&') // special case for <& and >& + { + i+=2; + } + else if(in[i]=='\\') // backslash: don't check next char + { + i++; + if(i>=size) + break; + i++; + } + else if(in[i] == '"') // start double quote + { + i++; + while(i=size) + break; + i++; + } + else if( word_eq("$(", in, size, i) ) // substitution + { + // add string subarg + ret.sa.push_back(subarg(std::string(in+j, i-j))); + i+=2; + // add subshell subarg + auto r=parse_subshell(in, size, i); + ret.sa.push_back(subarg(r.first)); + j = i = r.second; + } + else + i++; + } + if(i>=size) + break; + i++; + } + else if(in[i] == '\'') // start single quote + { + i++; + while(i=size) + break; + i++; + } + else if( word_eq("$(", in, size, i) ) // substitution + { + ret.sa.push_back(subarg(std::string(in+j, i-j))); + i+=2; + auto r=parse_subshell(in, size, i); + ret.sa.push_back(subarg(r.first)); + j = i = r.second; + } + else + i++; + } + + // add string subarg + std::string val=std::string(in+j, i-j); + ret.sa.push_back(subarg(val)); + + // raw string for other uses + ret.raw = std::string(in+start, i-start); + + return std::make_pair(ret, i); +} + +// parse one list of arguments (a command for instance) +// must start at a read char +// first char has to be read +// ends at either &|;\n#() +std::pair parse_arglist(const char* in, uint32_t size, uint32_t start) +{ + uint32_t i=start; + arglist ret; + while(i=size || is_in(in[i], "&|;\n#()") ) + return std::make_pair(ret, i); + } + return std::make_pair(ret, i); +} + +std::pair parse_block(const char* in, uint32_t size, uint32_t start); + +// parse a pipeline +// must start at a read char +// separated by | +// ends at either &;\n#) +std::pair parse_pipeline(const char* in, uint32_t size, uint32_t start) +{ + uint32_t i = skip_unread(in, size, start); + pipeline ret; + while(i=size || is_in(in[i], "&;\n#)") ) || word_eq("||", in, size, i) ) + return std::make_pair(ret, i); + else if( in[i] != '|') + throw ztd::format_error( strf("Unexpected token: '%c'", in[i] ), g_origin, in, i); + i++; + } + return std::make_pair(ret, i); +} + +// parse condition lists +// must start at a read char +// separated by && or || +// ends at either ;\n)# +std::pair parse_condlist(const char* in, uint32_t size, uint32_t start) +{ + uint32_t i = skip_unread(in, size, start); + condlist ret; + bool optype=AND_OP; + while(i=size || is_in(in[i], ")#")) // end here exactly: used for control later + { + return std::make_pair(ret, i); + } + else if(is_in(in[i], ";\n")) // end one char after: skip them for next parse + { + i++; + return std::make_pair(ret, i); + } + else if( word_eq("&", in, size, i) && !word_eq("&&", in, size, i) ) // parallel: end one char after + { + ret.parallel=true; + i++; + return std::make_pair(ret, i); + } + else if( word_eq("&&", in, size, i) ) // and op + { + i += 2; + optype=AND_OP; + } + else if( word_eq("||", in, size, i) ) // or op + { + i += 2; + optype=OR_OP; + } + else if(i parse_subshell(const char* in, uint32_t size, uint32_t start) +{ + uint32_t i = skip_unread(in, size, start); + block ret(block::subshell); + while(i=size) + throw ztd::format_error("Expecting )", g_origin, in, start-1); + i++; + return std::make_pair(ret,i); +} + +// parse condlists until } +std::pair parse_brace(const char* in, uint32_t size, uint32_t start) +{ + uint32_t i = skip_unread(in, size, start); + block ret(block::brace); + while(i=size) + throw ztd::format_error("Expecting }", g_origin, in, start-1); + + i++; + + return std::make_pair(ret,i); +} + +std::pair parse_function(const char* in, uint32_t size, uint32_t start) +{ + block ret(block::function); + uint32_t i=start; + + i=skip_unread(in, size, i); + if(in[i] != '{') + throw ztd::format_error("Expecting { after ()", g_origin, in, i); + + i++; + auto pp = parse_brace(in, size, i); + ret.cls = pp.first.cls; + i=pp.second; + + return std::make_pair(ret, i); +} + +std::pair parse_cmd(const char* in, uint32_t size, uint32_t start) +{ + block ret(block::cmd); + uint32_t i=start; + + auto tp=parse_arg(in, size, i); + i=skip_unread(in, size, tp.second); + if(word_eq("()", in, size, i)) + { + i += 2; + auto pp = parse_function(in, size, i); + pp.first.shebang = tp.first.raw; + return pp; + } + else + { + auto pp=parse_arglist(in, size, start); + ret.args = pp.first; + i = pp.second; + } + + return std::make_pair(ret, i); +} + +std::pair parse_case(const char* in, uint32_t size, uint32_t start) +{ + block ret(block::case_block); + uint32_t i=start; + + auto pa = parse_arg(in, size, i); // case arg + ret.carg = pa.first; + i=skip_unread(in, size, pa.second); + + + if(!word_eq("in", in, size, i)) + { + auto pp=parse_arg(in, size, i); + throw ztd::format_error("Unexpected word: '"+pp.first.raw+"', expecting 'in' after case", g_origin, in, i); + } + + i=skip_unread(in, size, i+2); + + while(i cc; + pa = parse_arg(in, size, i); + cc.first = pa.first; + i=skip_unread(in, size, pa.second); + + if(in[i] != ')') + throw ztd::format_error( strf("Unexpected token '%c', expecting ')'", in[i]), g_origin, in, i ); + i++; + + while(true) // blocks + { + auto pc = parse_condlist(in, size, i); + cc.second.push_back(pc.first); + i=pc.second; + + if(i+1>=size) + throw ztd::format_error("Expecting ';;'", g_origin, in, i); + if(in[i] == ')') + throw ztd::format_error( strf("Unexpected token '%c', expecting ';;'", in[i]), g_origin, in, i ); + + if(in[i-1] == ';' && in[i] == ';') + { + i++; + break; + } + + i=skip_unread(in, size, i); + if(word_eq(";;", in, size, i)) + { + i+=2; + break; + } + if(word_eq("esac", in, size, i)) + break; + + } + i=skip_unread(in, size, i); + ret.cases.push_back(cc); + } + + if(i>=size) + throw ztd::format_error("Expecting 'esac'", g_origin, in, i); + i+=4; + + return std::make_pair(ret, i); +} + +// detect if brace, subshell, case or other +std::pair parse_block(const char* in, uint32_t size, uint32_t start) +{ + uint32_t i = skip_chars(in, size, start, " \n\t"); + std::pair ret; + if(in[i] == '{') // brace block + { + i++; + ret = parse_brace(in, size, i); + } + else if(in[i] == '(') //subshell + { + i++; + ret = parse_subshell(in, size, i); + } + else if(word_eq("case", in, size, i)) + { + i = skip_unread(in, size, i+4); + ret = parse_case(in, size, i); + } + else // command + { + ret = parse_cmd(in, size, i); + } + if(ret.first.args.args.size()<=0) + { + auto pp=parse_arglist(in, size, ret.second); // in case of redirects + ret.second=pp.second; + ret.first.args=pp.first; + } + return ret; +} + +// parse main +block parse(const char* in, uint32_t size) +{ + + block ret(block::main); + uint32_t i=0; + if(word_eq("#!", in, size, 0)) + { + i=skip_until(in, size, 0, "\n"); + ret.shebang=std::string(in, i); + } + i = skip_unread(in, size, i); + while(i args) +{ + block cmd(block::cmd); + for(auto it: args) + { + cmd.args.add(arg(it)); + } + return cmd; +} + +std::vector arglist::strargs(uint32_t start) +{ + std::vector ret; + for(uint32_t i=start; ipls.size() > 0) + this->or_ops.push_back(or_op); + this->pls.push_back(pl); +} + +block* block::single_cmd() +{ + if(this->type == block::subshell) + { + if( cls.size() == 1 && // only one condlist + cls[0].pls.size() == 1 && // only one pipeline + cls[0].pls[0].cmds.size() == 1 && // only one block + cls[0].pls[0].cmds[0].type == block::cmd) // block is a command + return &(cls[0].pls[0].cmds[0]); // return command + } + return nullptr; +} + +std::string arg::string() +{ + if(sa.size() > 1 || sa[0].type != subarg::string) + return ""; + return sa[0].val; +} diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..85e3cef --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,54 @@ +#include "util.hpp" + +std::string indenting_string="\t"; + +std::string indent(int n) +{ + std::string ret; + for(int i=0; i split(std::string const& in, char c) +{ + uint32_t i=0,j=0; + std::vector ret; + while(j