Extend options
+ Add global -E option + Add %include -e option ~ Move -C option to %include and %resolve + Improve comments and messages
This commit is contained in:
parent
ca41c27246
commit
af1de6d8fb
11 changed files with 218 additions and 62 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,3 +3,4 @@
|
|||
/run-tests.sh
|
||||
/Zmakefile
|
||||
/TODO
|
||||
/lxsh
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
extern ztd::option_set options;
|
||||
|
||||
extern bool opt_minimize;
|
||||
extern bool piped; // for cd in substitutions
|
||||
|
||||
|
||||
ztd::option_set gen_options();
|
||||
void print_help(const char* arg0);
|
||||
|
|
|
|||
|
|
@ -11,13 +11,16 @@
|
|||
/*
|
||||
structure:
|
||||
|
||||
list_t : condlist[]
|
||||
|
||||
block:
|
||||
- group
|
||||
- brace: condlist[]
|
||||
- subsh: condlist[]
|
||||
- brace: list_t
|
||||
- subsh: list_t
|
||||
- cmd: arglist[]
|
||||
- if
|
||||
- pair<condlist[]>[]
|
||||
- case
|
||||
- arg (input)
|
||||
- pair<arg,list_t>[] (cases)
|
||||
|
||||
condlist:
|
||||
pipeline[]
|
||||
|
|
@ -30,14 +33,11 @@ arglist:
|
|||
|
||||
arg:
|
||||
- raw
|
||||
- subarg[]
|
||||
- subarg[] split into subarguments in case of subshells
|
||||
|
||||
subarg:
|
||||
- raw
|
||||
- variable
|
||||
- block: subshell
|
||||
|
||||
|
||||
- block: subshell (substitution)
|
||||
*/
|
||||
|
||||
#define AND_OP false
|
||||
|
|
@ -49,6 +49,7 @@ class pipeline;
|
|||
class arg;
|
||||
class subarg;
|
||||
|
||||
// type pack of condlist
|
||||
typedef std::vector<condlist> list_t;
|
||||
|
||||
block make_cmd(std::vector<std::string> args);
|
||||
|
|
@ -63,11 +64,14 @@ public:
|
|||
|
||||
void setstring(std::string const& str);
|
||||
|
||||
// has to be set manually
|
||||
std::string raw;
|
||||
|
||||
std::vector<subarg> sa;
|
||||
|
||||
// return if is a string and only one subarg
|
||||
std::string string();
|
||||
|
||||
std::string generate(int ind);
|
||||
};
|
||||
|
||||
|
|
@ -99,12 +103,17 @@ public:
|
|||
class block
|
||||
{
|
||||
public:
|
||||
// type
|
||||
enum blocktype { none, subshell, brace, main, cmd, function, case_block, for_block, if_block, while_block};
|
||||
blocktype type;
|
||||
|
||||
// ctor
|
||||
block() { type=none; }
|
||||
block(blocktype in) { type=in; }
|
||||
blocktype type;
|
||||
|
||||
// subshell/brace/main
|
||||
list_t cls;
|
||||
|
||||
// cmd
|
||||
arglist args;
|
||||
|
||||
|
|
@ -143,12 +152,13 @@ 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<bool> or_ops;
|
||||
bool parallel; // & at the end
|
||||
|
||||
void add(pipeline const& pl, bool or_op=false);
|
||||
// don't push_back here, use add() instead
|
||||
std::vector<pipeline> pls;
|
||||
std::vector<bool> or_ops; // size of 1 less than pls, defines separator between pipelines
|
||||
|
||||
std::string generate(int ind);
|
||||
};
|
||||
|
|
@ -157,12 +167,15 @@ public:
|
|||
class subarg
|
||||
{
|
||||
public:
|
||||
// type
|
||||
enum argtype { string, subshell };
|
||||
argtype type;
|
||||
|
||||
// ctor
|
||||
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
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ template<typename ... Args>
|
|||
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." ); }
|
||||
if( size <= 0 )
|
||||
throw std::runtime_error( "Error during formatting." );
|
||||
std::unique_ptr<char[]> 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
|
||||
|
|
@ -29,4 +30,10 @@ std::string strf( const std::string& format, Args ... args )
|
|||
|
||||
std::string delete_brackets(std::string const& in);
|
||||
|
||||
std::string pwd();
|
||||
|
||||
void _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);
|
||||
|
||||
#endif //UTIL_HPP
|
||||
|
|
|
|||
BIN
lxsh
BIN
lxsh
Binary file not shown.
|
|
@ -6,6 +6,8 @@
|
|||
#include "options.hpp"
|
||||
#include "parse.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
std::vector<std::string> included;
|
||||
|
||||
bool is_sub_special_cmd(std::string in)
|
||||
|
|
@ -99,10 +101,24 @@ std::string concatargs(std::vector<std::string> args)
|
|||
|
||||
std::string generate_resolve(std::vector<std::string> args, int ind)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
auto opts=create_resolve_opts();
|
||||
auto rargs = opts.process(args, false, true, false);
|
||||
|
||||
std::string cmd=concatargs(rargs);
|
||||
std::string dir;
|
||||
|
||||
if(!opts['C'] && !piped)
|
||||
{
|
||||
dir=pwd();
|
||||
std::string cddir=ztd::exec("dirname", g_origin).first;
|
||||
cddir.pop_back();
|
||||
chdir(cddir.c_str());
|
||||
}
|
||||
|
||||
|
||||
// exec call
|
||||
auto p=ztd::shp("exec "+cmd);
|
||||
|
||||
if(!opts['f'] && p.second!=0)
|
||||
|
|
@ -114,17 +130,29 @@ std::string generate_resolve(std::vector<std::string> args, int ind)
|
|||
|
||||
if(opts['p'])
|
||||
{
|
||||
block bl = parse(p.first);
|
||||
std::string ret = bl.generate(ind, false);
|
||||
block bl;
|
||||
try
|
||||
{
|
||||
bl = parse(p.first);
|
||||
}
|
||||
catch(ztd::format_error& e)
|
||||
{
|
||||
throw ztd::format_error(e.what(), "command `"+cmd+'`', e.data(), e.where());
|
||||
}
|
||||
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;
|
||||
ret = p.first;
|
||||
}
|
||||
|
||||
if(!opts['C'] && !piped)
|
||||
chdir(dir.c_str());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string generate_include(std::vector<std::string> args, int ind)
|
||||
|
|
@ -140,6 +168,17 @@ std::string generate_include(std::vector<std::string> args, int ind)
|
|||
else if(opts['d'])
|
||||
quote = '"';
|
||||
|
||||
std::string curfile=g_origin;
|
||||
std::string dir;
|
||||
|
||||
if(!opts['C'] && !piped)
|
||||
{
|
||||
dir=pwd();
|
||||
std::string cddir=ztd::exec("dirname", curfile).first;
|
||||
cddir.pop_back();
|
||||
chdir(cddir.c_str());
|
||||
}
|
||||
|
||||
// do shell resolution
|
||||
std::string command="for I in ";
|
||||
for(auto it: rargs)
|
||||
|
|
@ -149,6 +188,7 @@ std::string generate_include(std::vector<std::string> args, int ind)
|
|||
|
||||
auto v = split(inc, '\n');
|
||||
|
||||
|
||||
std::string file;
|
||||
block bl;
|
||||
bool indent_remove=true;
|
||||
|
|
@ -159,10 +199,13 @@ std::string generate_include(std::vector<std::string> args, int ind)
|
|||
add_include(it) ) // not already included
|
||||
{
|
||||
file=import_file(it);
|
||||
if(opts['e'])
|
||||
file = stringReplace(file, "\"", "\\\"");
|
||||
if(opts['r'])
|
||||
ret += file;
|
||||
else
|
||||
{
|
||||
g_origin=it;
|
||||
try
|
||||
{
|
||||
bl = parse(quote + file + quote);
|
||||
|
|
@ -182,6 +225,9 @@ std::string generate_include(std::vector<std::string> args, int ind)
|
|||
}
|
||||
}
|
||||
}
|
||||
if(!opts['C'] && !piped)
|
||||
chdir(dir.c_str());
|
||||
g_origin=curfile;
|
||||
|
||||
if(!opts['r'])
|
||||
ret.pop_back();
|
||||
|
|
@ -215,13 +261,17 @@ std::string block::generate_case(int ind)
|
|||
ind++;
|
||||
for(auto cs: this->cases)
|
||||
{
|
||||
// case definition : foo)
|
||||
if(!opt_minimize) ret += INDENT;
|
||||
ret += cs.first.generate(ind) + ')';
|
||||
if(!opt_minimize) ret += '\n';
|
||||
// commands
|
||||
for(auto it: cs.second)
|
||||
ret += it.generate(ind+1);
|
||||
// end of case: ;;
|
||||
if(opt_minimize)
|
||||
{
|
||||
// ;; can be right after command
|
||||
if(ret[ret.size()-1] == '\n')
|
||||
ret.pop_back();
|
||||
}
|
||||
|
|
@ -233,6 +283,7 @@ std::string block::generate_case(int ind)
|
|||
}
|
||||
ret += ";;\n";
|
||||
}
|
||||
// close case
|
||||
ind--;
|
||||
if(!opt_minimize) ret += INDENT;
|
||||
ret += "esac";
|
||||
|
|
@ -251,25 +302,30 @@ std::string block::generate(int ind, bool print_shebang)
|
|||
{
|
||||
if(type==function)
|
||||
{
|
||||
// function definition
|
||||
ret += shebang + "()";
|
||||
if(!opt_minimize) ret += '\n' + INDENT;
|
||||
ret += "{\n";
|
||||
ret += "{\n";
|
||||
// commands
|
||||
for(auto it: cls)
|
||||
ret += it.generate(ind+1);
|
||||
if(!opt_minimize)
|
||||
ret += INDENT;
|
||||
if(!opt_minimize) ret += INDENT;
|
||||
// end function
|
||||
ret += '}';
|
||||
}
|
||||
else if(type==subshell)
|
||||
{
|
||||
// open subshell
|
||||
ret += '(';
|
||||
if(!opt_minimize) ret += '\n';
|
||||
// commands
|
||||
for(auto it: cls)
|
||||
ret += it.generate(ind+1);
|
||||
if(opt_minimize)
|
||||
ret.pop_back();
|
||||
ret.pop_back(); // ) can be right after command
|
||||
else
|
||||
ret += INDENT;
|
||||
// close subshell
|
||||
ret += ')';
|
||||
}
|
||||
else if(type==brace)
|
||||
|
|
|
|||
59
src/main.cpp
59
src/main.cpp
|
|
@ -7,18 +7,19 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "util.hpp"
|
||||
#include "struc.hpp"
|
||||
#include "parse.hpp"
|
||||
#include "options.hpp"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
auto args=options.process(argc, argv);
|
||||
auto args=options.process(argc, argv, false, true);
|
||||
|
||||
if(options['m'])
|
||||
opt_minimize=true;
|
||||
|
||||
bool piped=false;
|
||||
piped=false;
|
||||
|
||||
if(options['h'])
|
||||
{
|
||||
|
|
@ -58,34 +59,48 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
try
|
||||
block sh(parse(import_file(file)));
|
||||
if(options['E'])
|
||||
{
|
||||
std::string data=sh.generate();
|
||||
// generate path
|
||||
std::string tmpdir = (getenv("TMPDIR") != NULL) ? getenv("TMPDIR") : "/tmp" ;
|
||||
std::string filepath = tmpdir + "/lxsh_exec_" + ztd::sh("tr -dc '[:alnum:]' < /dev/urandom | head -c10");
|
||||
// create stream
|
||||
std::ofstream stream(filepath);
|
||||
if(!stream)
|
||||
throw std::runtime_error("Failed to write to file '"+filepath+'\'');
|
||||
|
||||
// output
|
||||
stream << data;
|
||||
stream.close();
|
||||
auto p = ztd::exec("chmod", "+x", filepath);
|
||||
if(p.second != 0)
|
||||
return p.second;
|
||||
|
||||
args.erase(args.begin());
|
||||
_exec(filepath, args);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
catch(ztd::format_error& e)
|
||||
{
|
||||
printFormatException(e);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
ztd::option_set options = gen_options();
|
||||
bool opt_minimize;
|
||||
bool piped=false;
|
||||
|
||||
|
||||
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('E', "exec", false, "Directly exec instead of outputting"));
|
||||
ret.add(ztd::option("help-commands", false, "Print help for linker commands"));
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -19,8 +21,9 @@ ztd::option_set create_include_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('e', false, "Escape double quotes"),
|
||||
ztd::option('r', false, "Include raw contents, don't parse"),
|
||||
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")
|
||||
);
|
||||
return opts;
|
||||
|
|
@ -30,8 +33,8 @@ 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('C', false, "Don't cd to folder this file is in"),
|
||||
ztd::option('f', false, "Ignore non-zero return values")
|
||||
);
|
||||
return opts;
|
||||
|
|
@ -39,7 +42,7 @@ ztd::option_set create_resolve_opts()
|
|||
|
||||
void print_help(const char* arg0)
|
||||
{
|
||||
printf("%s [options] [file]\n", arg0);
|
||||
printf("%s [options] <file> [arg...]\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");
|
||||
|
|
@ -50,7 +53,7 @@ void print_help(const char* arg0)
|
|||
void print_include_help()
|
||||
{
|
||||
printf("%%include [options] <file...>\n");
|
||||
printf("Include the targeted files. Paths are relative to folder of current file\n");
|
||||
printf("Include the targeted files, from 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");
|
||||
|
|
@ -64,7 +67,7 @@ void print_include_help()
|
|||
void print_resolve_help()
|
||||
{
|
||||
printf("%%resolve [options] <command...>\n");
|
||||
printf("Execute shell command and substitute output. Paths is from folder of current file\n");
|
||||
printf("Execute shell command and substitute output, 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");
|
||||
|
|
|
|||
|
|
@ -241,7 +241,9 @@ std::pair<condlist, uint32_t> parse_condlist(const char* in, uint32_t size, uint
|
|||
return std::make_pair(ret, i);
|
||||
}
|
||||
|
||||
// parse condlists until )
|
||||
// parse a subshell
|
||||
// must start right after the opening (
|
||||
// ends at ) and nothing else
|
||||
std::pair<block, uint32_t> parse_subshell(const char* in, uint32_t size, uint32_t start)
|
||||
{
|
||||
uint32_t i = skip_unread(in, size, start);
|
||||
|
|
@ -258,7 +260,9 @@ std::pair<block, uint32_t> parse_subshell(const char* in, uint32_t size, uint32_
|
|||
return std::make_pair(ret,i);
|
||||
}
|
||||
|
||||
// parse condlists until }
|
||||
// parse a brace block
|
||||
// must start right after the opening {
|
||||
// ends at } and nothing else
|
||||
std::pair<block, uint32_t> parse_brace(const char* in, uint32_t size, uint32_t start)
|
||||
{
|
||||
uint32_t i = skip_unread(in, size, start);
|
||||
|
|
@ -279,6 +283,9 @@ std::pair<block, uint32_t> parse_brace(const char* in, uint32_t size, uint32_t s
|
|||
return std::make_pair(ret,i);
|
||||
}
|
||||
|
||||
// parse a functions
|
||||
// must start right after the ()
|
||||
// then parses a brace block
|
||||
std::pair<block, uint32_t> parse_function(const char* in, uint32_t size, uint32_t start)
|
||||
{
|
||||
block ret(block::function);
|
||||
|
|
@ -301,16 +308,18 @@ std::pair<block, uint32_t> parse_cmd(const char* in, uint32_t size, uint32_t sta
|
|||
block ret(block::cmd);
|
||||
uint32_t i=start;
|
||||
|
||||
// parse first arg and keep it
|
||||
auto tp=parse_arg(in, size, i);
|
||||
i=skip_unread(in, size, tp.second);
|
||||
if(word_eq("()", in, size, i))
|
||||
if(word_eq("()", in, size, i)) // is a function
|
||||
{
|
||||
i += 2;
|
||||
auto pp = parse_function(in, size, i);
|
||||
// first arg is function name
|
||||
pp.first.shebang = tp.first.raw;
|
||||
return pp;
|
||||
}
|
||||
else
|
||||
else // is a command
|
||||
{
|
||||
auto pp=parse_arglist(in, size, start);
|
||||
ret.args = pp.first;
|
||||
|
|
@ -320,16 +329,20 @@ std::pair<block, uint32_t> parse_cmd(const char* in, uint32_t size, uint32_t sta
|
|||
return std::make_pair(ret, i);
|
||||
}
|
||||
|
||||
// parse a case block
|
||||
// must start right after the case
|
||||
// ends at } and nothing else
|
||||
std::pair<block, uint32_t> parse_case(const char* in, uint32_t size, uint32_t start)
|
||||
{
|
||||
block ret(block::case_block);
|
||||
uint32_t i=start;
|
||||
uint32_t i=skip_unread(in, size, start);;
|
||||
|
||||
auto pa = parse_arg(in, size, i); // case arg
|
||||
// get the treated argument
|
||||
auto pa = parse_arg(in, size, i);
|
||||
ret.carg = pa.first;
|
||||
i=skip_unread(in, size, pa.second);
|
||||
|
||||
|
||||
// must be an 'in'
|
||||
if(!word_eq("in", in, size, i))
|
||||
{
|
||||
auto pp=parse_arg(in, size, i);
|
||||
|
|
@ -338,6 +351,7 @@ std::pair<block, uint32_t> parse_case(const char* in, uint32_t size, uint32_t st
|
|||
|
||||
i=skip_unread(in, size, i+2);
|
||||
|
||||
// parse all cases
|
||||
while(i<size && !word_eq("esac", in, size, i, " \t\n;()&") )
|
||||
{
|
||||
// toto)
|
||||
|
|
@ -361,18 +375,21 @@ std::pair<block, uint32_t> parse_case(const char* in, uint32_t size, uint32_t st
|
|||
if(in[i] == ')')
|
||||
throw ztd::format_error( strf("Unexpected token '%c', expecting ';;'", in[i]), g_origin, in, i );
|
||||
|
||||
// end of case: on same line
|
||||
if(in[i-1] == ';' && in[i] == ';')
|
||||
{
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
|
||||
// end of case: on new line
|
||||
i=skip_unread(in, size, i);
|
||||
if(word_eq(";;", in, size, i))
|
||||
{
|
||||
i+=2;
|
||||
break;
|
||||
}
|
||||
// end of block: ignore missing ;;
|
||||
if(word_eq("esac", in, size, i))
|
||||
break;
|
||||
|
||||
|
|
@ -381,6 +398,7 @@ std::pair<block, uint32_t> parse_case(const char* in, uint32_t size, uint32_t st
|
|||
ret.cases.push_back(cc);
|
||||
}
|
||||
|
||||
// ended before finding esac
|
||||
if(i>=size)
|
||||
throw ztd::format_error("Expecting 'esac'", g_origin, in, i);
|
||||
i+=4;
|
||||
|
|
@ -405,8 +423,7 @@ std::pair<block, uint32_t> parse_block(const char* in, uint32_t size, uint32_t s
|
|||
}
|
||||
else if(word_eq("case", in, size, i))
|
||||
{
|
||||
i = skip_unread(in, size, i+4);
|
||||
ret = parse_case(in, size, i);
|
||||
ret = parse_case(in, size, i+4);
|
||||
}
|
||||
else // command
|
||||
{
|
||||
|
|
@ -424,15 +441,16 @@ std::pair<block, uint32_t> parse_block(const char* in, uint32_t size, uint32_t s
|
|||
// parse main
|
||||
block parse(const char* in, uint32_t size)
|
||||
{
|
||||
|
||||
block ret(block::main);
|
||||
uint32_t i=0;
|
||||
// get shebang
|
||||
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);
|
||||
// parse all commands
|
||||
while(i<size)
|
||||
{
|
||||
auto pp=parse_condlist(in, size, i);
|
||||
|
|
@ -442,6 +460,7 @@ block parse(const char* in, uint32_t size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// import a file's contents into a string
|
||||
std::string import_file(std::string const& path)
|
||||
{
|
||||
std::ifstream st(path);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "util.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
block make_cmd(std::vector<std::string> args)
|
||||
{
|
||||
block cmd(block::cmd);
|
||||
|
|
@ -24,6 +26,7 @@ void arg::setstring(std::string const& str)
|
|||
{
|
||||
sa.resize(0);
|
||||
sa.push_back(subarg(str));
|
||||
raw = str;
|
||||
}
|
||||
|
||||
void condlist::add(pipeline const& pl, bool or_op)
|
||||
|
|
|
|||
37
src/util.cpp
37
src/util.cpp
|
|
@ -1,5 +1,9 @@
|
|||
#include "util.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ztd/shell.hpp>
|
||||
|
||||
std::string indenting_string="\t";
|
||||
|
||||
std::string indent(int n)
|
||||
|
|
@ -52,3 +56,36 @@ std::string delete_brackets(std::string const& in)
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string pwd()
|
||||
{
|
||||
char buf[2048];
|
||||
if(getcwd(buf, 2048) != NULL)
|
||||
{
|
||||
std::string ret=ztd::exec("pwd").first; // getcwd failed: call pwd
|
||||
ret.pop_back();
|
||||
return ret;
|
||||
}
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
void _exec(std::string const& bin, std::vector<std::string> const& args)
|
||||
{
|
||||
std::vector<char*> rargs;
|
||||
rargs.push_back((char*) bin.c_str());
|
||||
for(auto it=args.begin(); it!=args.end(); it++)
|
||||
rargs.push_back((char*) it->c_str());
|
||||
rargs.push_back(NULL);
|
||||
execvp(bin.c_str(), rargs.data());
|
||||
}
|
||||
|
||||
std::string stringReplace(std::string subject, const std::string& search, const std::string& replace)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while ((pos = subject.find(search, pos)) != std::string::npos)
|
||||
{
|
||||
subject.replace(pos, search.length(), replace);
|
||||
pos += replace.length();
|
||||
}
|
||||
return subject;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue