add ${} parsing
This commit is contained in:
parent
99957ee3e5
commit
5a7c2e0bf0
5 changed files with 92 additions and 23 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue