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: public:
enum _objtype { enum _objtype {
subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_manipulation,
_arg, _arg,
_arglist, _arglist,
_pipeline, _pipeline,
@ -439,5 +439,18 @@ public:
std::string generate(int ind); 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 #endif //STRUC_HPP

View file

@ -330,10 +330,15 @@ std::string cmd::generate(int ind)
std::string subshell_subarg::generate(int ind) std::string subshell_subarg::generate(int ind)
{ {
std::string ret; return '$' + sbsh->generate(ind);
ret += '$'; }
ret += sbsh->generate(ind);
return ret; std::string manipulation_subarg::generate(int ind)
{
if(size)
return "${#" + varname + "}";
else
return "${" + varname + manip->generate(ind) + "}";
} }
// TEMPLATE // 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) if(!variable_map->insert( std::make_pair(t->varname, 1) ).second)
(*variable_map)[t->varname]++; (*variable_map)[t->varname]++;
}; break; }; 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: { case _obj::block_for: {
for_block* t = dynamic_cast<for_block*>(in); for_block* t = dynamic_cast<for_block*>(in);
if(!variable_map->insert( std::make_pair(t->varname, 1) ).second) 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()) if(el!=varmap->end())
t->varname = el->second; t->varname = el->second;
}; break; }; 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: { case _obj::block_for: {
for_block* t = dynamic_cast<for_block*>(in); for_block* t = dynamic_cast<for_block*>(in);
auto it=varmap->find(t->varname); 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("minimize-fct", false, "Minimize function names"),
ztd::option("exclude-var", true, "List of matching regex to ignore for variable processing", "list"), 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("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-var", false, "List all variables defined and invoked in the script"),
ztd::option("list-fct", false, "List all functions invoked in the script"), ztd::option("list-fct", false, "List all functions defined in the script"),
ztd::option("list-cmd", false, "List all functions invoked 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("unset-var", false, "Add 'unset' to vars"),
ztd::option("remove-unused", false, "Remove unused functions") 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); 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 // parse one argument
// must start at a read char // must start at a read char
// ends at either " \t|&;\n()" // 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; arg* ret = new arg;
// j : start of subarg , q = start of quote // 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 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); 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 >& if(i+1<size && is_in(in[i], "<>") && in[i+1]=='&') // special case for <& and >&
{ {
i+=2; i+=2;
} }
else if(in[i]=='\\') // backslash: don't check next char else if(doquote && in[i]=='\\') // backslash: don't check next char
{ {
i++; i++;
if(i>=size) if(i>=size)
break; break;
i++; i++;
} }
else if(in[i] == '"') // start double quote else if(doquote && in[i] == '"') // start double quote
{ {
q=i; q=i;
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 // add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j))); ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
i+=3;
// get arithmetic // get arithmetic
auto r=parse_arithmetic(in, size, i); auto r=parse_arithmetic(in, size, i+3);
ret->sa.push_back(r.first); ret->sa.push_back(r.first);
j = i = r.second; 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 // add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j))); ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
i+=2;
// get subshell // 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)); ret->sa.push_back(new subshell_subarg(r.first, true));
j = i = r.second; 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] == '$' ) else if( in[i] == '$' )
{ {
auto r=parse_varname(in, size, i+1); 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++; i++;
} }
else if(in[i] == '\'') // start single quote else if(doquote && in[i] == '\'') // start single quote
{ {
q=i; q=i;
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 // add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j))); ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
i+=3;
// get arithmetic // get arithmetic
auto r=parse_arithmetic(in, size, i); auto r=parse_arithmetic(in, size, i+3);
ret->sa.push_back(r.first); ret->sa.push_back(r.first);
j = i = r.second; 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 // add previous subarg
ret->sa.push_back(new string_subarg(std::string(in+j, i-j))); ret->sa.push_back(new string_subarg(std::string(in+j, i-j)));
i+=2;
// get subshell // 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)); ret->sa.push_back(new subshell_subarg(r.first, false));
j = i = r.second; 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] == '$' ) else if( in[i] == '$' )
{ {
auto r=parse_varname(in, size, i+1); auto r=parse_varname(in, size, i+1);