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:
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue