add ${} parsing

This commit is contained in:
zawz 2020-11-10 18:01:51 +01:00
parent 99957ee3e5
commit 5a7c2e0bf0
5 changed files with 92 additions and 23 deletions

View file

@ -82,7 +82,7 @@ class _obj
{
public:
enum _objtype {
subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic,
subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_manipulation,
_arg,
_arglist,
_pipeline,
@ -439,5 +439,18 @@ public:
std::string generate(int ind);
};
class manipulation_subarg : public subarg
{
public:
manipulation_subarg(arg* in=nullptr) { type=_obj::subarg_manipulation; size=false; manip=in; }
~manipulation_subarg() { if(manip!=nullptr) delete manip; }
bool size;
std::string varname;
arg* manip;
std::string generate(int ind);
};
#endif //STRUC_HPP

View file

@ -330,10 +330,15 @@ std::string cmd::generate(int ind)
std::string subshell_subarg::generate(int ind)
{
std::string ret;
ret += '$';
ret += sbsh->generate(ind);
return ret;
return '$' + sbsh->generate(ind);
}
std::string manipulation_subarg::generate(int ind)
{
if(size)
return "${#" + varname + "}";
else
return "${" + varname + manip->generate(ind) + "}";
}
// TEMPLATE

View file

@ -98,6 +98,11 @@ void get_map_varname(_obj* in, std::map<std::string,uint32_t>* variable_map)
if(!variable_map->insert( std::make_pair(t->varname, 1) ).second)
(*variable_map)[t->varname]++;
}; break;
case _obj::subarg_manipulation: {
manipulation_subarg* t = dynamic_cast<manipulation_subarg*>(in);
if(!variable_map->insert( std::make_pair(t->varname, 1) ).second)
(*variable_map)[t->varname]++;
}; break;
case _obj::block_for: {
for_block* t = dynamic_cast<for_block*>(in);
if(!variable_map->insert( std::make_pair(t->varname, 1) ).second)
@ -129,6 +134,12 @@ void replace_varname(_obj* in, std::map<std::string,std::string>* varmap)
if(el!=varmap->end())
t->varname = el->second;
}; break;
case _obj::subarg_manipulation: {
manipulation_subarg* t = dynamic_cast<manipulation_subarg*>(in);
auto el=varmap->find(t->varname);
if(el!=varmap->end())
t->varname = el->second;
}; break;
case _obj::block_for: {
for_block* t = dynamic_cast<for_block*>(in);
auto it=varmap->find(t->varname);

View file

@ -30,9 +30,9 @@ ztd::option_set gen_options()
ztd::option("minimize-fct", false, "Minimize function names"),
ztd::option("exclude-var", true, "List of matching regex to ignore for variable processing", "list"),
ztd::option("exclude-fct", true, "List of matching regex to ignore for function processing", "list"),
ztd::option("list-var", false, "List all variables invoked in the script"),
ztd::option("list-fct", false, "List all functions invoked in the script"),
ztd::option("list-cmd", false, "List all functions invoked in the script"),
ztd::option("list-var", false, "List all variables defined and invoked in the script"),
ztd::option("list-fct", false, "List all functions defined in the script"),
ztd::option("list-cmd", false, "List all commands invoked in the script"),
// ztd::option("unset-var", false, "Add 'unset' to vars"),
ztd::option("remove-unused", false, "Remove unused functions")
);

View file

@ -176,10 +176,36 @@ std::pair<arithmetic_subarg*, uint32_t> parse_arithmetic(const char* in, uint32_
return std::make_pair(ret, i);
}
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<manipulation_subarg*, uint32_t> parse_manipulation(const char* in, uint32_t size, uint32_t start)
{
manipulation_subarg* ret = new manipulation_subarg;
uint32_t i=start;
if(in[i] == '#')
{
ret->size=true;
i++;
}
auto p=parse_varname(in, size, i);
if(p.second == i)
throw PARSE_ERROR( "Bad variable name", i );
ret->varname=p.first;
i = p.second;
auto pa = parse_arg(in, size, i, "}", NULL, false);
ret->manip=pa.first;
i = pa.second+1;
return std::make_pair(ret, i);
}
// parse one argument
// must start at a read char
// ends at either " \t|&;\n()"
std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t start)
std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t start, const char* end, const char* unexpected, bool doquote)
{
arg* ret = new arg;
// j : start of subarg , q = start of quote
@ -188,23 +214,23 @@ std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t star
try
{
if(is_in(in[i], SPECIAL_TOKENS))
if(unexpected != NULL && is_in(in[i], unexpected))
throw PARSE_ERROR( strf("Unexpected token '%c'", in[i]) , i);
while(i<size && !is_in(in[i], ARG_END))
while(i<size && !is_in(in[i], end))
{
if(i+1<size && is_in(in[i], "<>") && in[i+1]=='&') // special case for <& and >&
{
i+=2;
}
else if(in[i]=='\\') // backslash: don't check next char
else if(doquote && in[i]=='\\') // backslash: don't check next char
{
i++;
if(i>=size)
break;
break;
i++;
}
else if(in[i] == '"') // start double quote
else if(doquote && in[i] == '"') // start double quote
{
q=i;
i++;
@ -218,9 +244,8 @@ std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t star
{
// add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
i+=3;
// get arithmetic
auto r=parse_arithmetic(in, size, i);
auto r=parse_arithmetic(in, size, i+3);
ret->sa.push_back(r.first);
j = i = r.second;
}
@ -228,12 +253,20 @@ std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t star
{
// add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
i+=2;
// get subshell
auto r=parse_subshell(in, size, i);
auto r=parse_subshell(in, size, i+2);
ret->sa.push_back(new subshell_subarg(r.first, true));
j = i = r.second;
}
else if( word_eq("${", in, size, i) ) // variable manipulation
{
// add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
// get manipulation
auto r=parse_manipulation(in, size, i+2);
ret->sa.push_back(r.first);
j = i = r.second;
}
else if( in[i] == '$' )
{
auto r=parse_varname(in, size, i+1);
@ -256,7 +289,7 @@ std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t star
}
i++;
}
else if(in[i] == '\'') // start single quote
else if(doquote && in[i] == '\'') // start single quote
{
q=i;
i++;
@ -270,9 +303,8 @@ std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t star
{
// add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
i+=3;
// get arithmetic
auto r=parse_arithmetic(in, size, i);
auto r=parse_arithmetic(in, size, i+3);
ret->sa.push_back(r.first);
j = i = r.second;
}
@ -280,12 +312,20 @@ std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t star
{
// add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
i+=2;
// get subshell
auto r=parse_subshell(in, size, i);
auto r=parse_subshell(in, size, i+2);
ret->sa.push_back(new subshell_subarg(r.first, false));
j = i = r.second;
}
else if( word_eq("${", in, size, i) ) // variable manipulation
{
// add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
// get manipulation
auto r=parse_manipulation(in, size, i+2);
ret->sa.push_back(r.first);
j = i = r.second;
}
else if( in[i] == '$' )
{
auto r=parse_varname(in, size, i+1);