def _EvalDoubleQuotedPart(self, part, part_vals): """DoubleQuotedPart -> part_value Args: part_vals: output param to append to. """ # Example of returning array: # $ a=(1 2); b=(3); $ c=(4 5) # $ argv "${a[@]}${b[@]}${c[@]}" # ['1', '234', '5'] # Example of multiple parts # $ argv "${a[@]}${undef[@]:-${c[@]}}" # ['1', '24', '5'] #log('DQ part %s', part) # Special case for "". The parser outputs (DoubleQuotedPart []), instead # of (DoubleQuotedPart [LiteralPart '']). This is better but it means we # have to check for it. if not part.parts: v = runtime.StringPartValue('', False) part_vals.append(v) return for p in part.parts: self._EvalWordPart(p, part_vals, quoted=True)
def _EvalWordToParts(self, word, quoted, part_vals): """Helper for EvalRhsWord, EvalWordSequence, etc. Returns: List of part_value. But note that this is a TREE. """ if word.tag == word_e.CompoundWord: for p in word.parts: self._EvalWordPart(p, part_vals, quoted=quoted) elif word.tag == word_e.EmptyWord: part_vals.append(runtime.StringPartValue('', False)) else: raise AssertionError(word.__class__.__name__)
def _ValueToPartValue(val, quoted): """Helper for VarSub evaluation. Called by _EvalBracedVarSub and __EvalWordPart for SimpleVarSub. """ assert isinstance(val, runtime.value), val if val.tag == value_e.Str: return runtime.StringPartValue(val.s, not quoted) elif val.tag == value_e.StrArray: return runtime.ArrayPartValue(val.strs) else: # Undef should be caught by _EmptyStrOrError(). raise AssertionError
def _EvalWordPart(self, part, part_vals, quoted=False): """Evaluate a word part. Args: part_vals: Output parameter. Returns: None """ if part.tag == word_part_e.ArrayLiteralPart: raise AssertionError( 'Array literal should have been handled at word level') elif part.tag == word_part_e.LiteralPart: v = runtime.StringPartValue(part.token.val, not quoted) part_vals.append(v) elif part.tag == word_part_e.EscapedLiteralPart: val = part.token.val assert len(val) == 2, val # e.g. \* assert val[0] == '\\' s = val[1] v = runtime.StringPartValue(s, False) part_vals.append(v) elif part.tag == word_part_e.SingleQuotedPart: if part.left.id == Id.Left_SingleQuote: s = ''.join(t.val for t in part.tokens) elif part.left.id == Id.Left_DollarSingleQuote: # NOTE: This could be done at compile time s = ''.join( word_compile.EvalCStringToken(t.id, t.val) for t in part.tokens) else: raise AssertionError(part.left.id) v = runtime.StringPartValue(s, False) part_vals.append(v) elif part.tag == word_part_e.DoubleQuotedPart: self._EvalDoubleQuotedPart(part, part_vals) elif part.tag == word_part_e.CommandSubPart: id_ = part.left_token.id if id_ in (Id.Left_CommandSub, Id.Left_Backtick): v = self._EvalCommandSub(part.command_list, quoted) elif id_ in (Id.Left_ProcSubIn, Id.Left_ProcSubOut): v = self._EvalProcessSub(part.command_list, id_) else: raise AssertionError(id_) part_vals.append(v) elif part.tag == word_part_e.SimpleVarSub: maybe_decay_array = False # 1. Evaluate from (var_name, var_num, token) -> defined, value if part.token.id == Id.VSub_Name: var_name = part.token.val[1:] val = self.mem.GetVar(var_name) elif part.token.id == Id.VSub_Number: var_num = int(part.token.val[1:]) val = self._EvalVarNum(var_num) else: val, maybe_decay_array = self._EvalSpecialVar( part.token.id, quoted) #log('SIMPLE %s', part) val = self._EmptyStrOrError(val, token=part.token) if maybe_decay_array and val.tag == value_e.StrArray: val = self._DecayArray(val) v = _ValueToPartValue(val, quoted) part_vals.append(v) elif part.tag == word_part_e.BracedVarSub: self._EvalBracedVarSub(part, part_vals, quoted) elif part.tag == word_part_e.TildeSubPart: # We never parse a quoted string into a TildeSubPart. assert not quoted s = self._EvalTildeSub(part.token) v = runtime.StringPartValue(s, False) part_vals.append(v) elif part.tag == word_part_e.ArithSubPart: num = self.arith_ev.Eval(part.anode) v = runtime.StringPartValue(str(num), False) part_vals.append(v) elif part.tag == word_part_e.ExtGlobPart: # do_split_glob should be renamed 'unquoted'? or inverted and renamed # 'quoted'? part_vals.append(runtime.StringPartValue(part.op.val, True)) for i, w in enumerate(part.arms): if i != 0: part_vals.append(runtime.StringPartValue( '|', True)) # separator # This flattens the tree! self._EvalWordToParts(w, False, part_vals) # eval like not quoted? part_vals.append(runtime.StringPartValue(')', True)) # closing ) else: raise AssertionError(part.__class__.__name__)
def _EvalProcessSub(self, node, id_): return runtime.StringPartValue('__PROCESS_SUB_NOT_EXECUTED__', False)
def _EvalCommandSub(self, node, quoted): return runtime.StringPartValue('__COMMAND_SUB_NOT_EXECUTED__', not quoted)
def _EvalProcessSub(self, node, id_): dev_path = self.ex.RunProcessSub(node, id_) return runtime.StringPartValue(dev_path, False) # no split or glob
def _EvalCommandSub(self, node, quoted): stdout = self.ex.RunCommandSub(node) return runtime.StringPartValue(stdout, not quoted)