def _InitVarsFromEnv(self, environ): # This is the way dash and bash work -- at startup, they turn everything in # 'environ' variable into shell variables. Bash has an export_env # variable. Dash has a loop through environ in init.c for n, v in environ.iteritems(): self.SetVar(lhs_expr.LhsName(n), value.Str(v), (var_flags_e.Exported, ), scope_e.GlobalOnly) # If it's not in the environment, initialize it. This makes it easier to # update later in ExecOpts. # TODO: IFS, etc. should follow this pattern. Maybe need a SysCall # interface? self.syscall.getcwd() etc. v = self.GetVar('SHELLOPTS') if v.tag == value_e.Undef: SetGlobalString(self, 'SHELLOPTS', '') # Now make it readonly self.SetVar(lhs_expr.LhsName('SHELLOPTS'), None, (var_flags_e.ReadOnly, ), scope_e.GlobalOnly) # Usually we inherit PWD from the parent shell. When it's not set, we may # compute it. v = self.GetVar('PWD') if v.tag == value_e.Undef: SetGlobalString(self, 'PWD', _GetWorkingDir()) # Now mark it exported, no matter what. This is one of few variables # EXPORTED. bash and dash both do it. (e.g. env -i -- dash -c env) self.SetVar(lhs_expr.LhsName('PWD'), None, (var_flags_e.Exported, ), scope_e.GlobalOnly)
def _InitVarsFromEnv(self, environ): # This is the way dash and bash work -- at startup, they turn everything in # 'environ' variable into shell variables. Bash has an export_env # variable. Dash has a loop through environ in init.c for n, v in environ.iteritems(): self.SetVar(lhs_expr.LhsName(n), value.Str(v), (var_flags_e.Exported,), scope_e.GlobalOnly) # If it's not in the environment, initialize it. This makes it easier to # update later in ExecOpts. # TODO: IFS, PWD, etc. should follow this pattern. Maybe need a SysCall # interface? self.syscall.getcwd() etc. v = self.GetVar('SHELLOPTS') if v.tag == value_e.Undef: SetGlobalString(self, 'SHELLOPTS', '') # Now make it readonly self.SetVar( lhs_expr.LhsName('SHELLOPTS'), None, (var_flags_e.ReadOnly,), scope_e.GlobalOnly) v = self.GetVar('HOME') if v.tag == value_e.Undef: # TODO: Should lack of a home dir be an error? What does bash do? home_dir = _GetHomeDir() or '~' SetGlobalString(self, 'HOME', home_dir)
def SetArrayDynamic(mem, name, a): """Set an array by looking up the stack. Used for _init_completion. """ assert isinstance(a, list) mem.SetVar(lhs_expr.LhsName(name), value.StrArray(a), (), scope_e.Dynamic)
def SetStringDynamic(mem, name, s): """Set a string by looking up the stack. Used for getopts. """ assert isinstance(s, str) mem.SetVar(lhs_expr.LhsName(name), value.Str(s), (), scope_e.Dynamic)
def SetLocalString(mem, name, s): """Set a local string. Used for: 1) for loop iteration variables 2) temporary environments like FOO=bar BAR=$FOO cmd, 3) read builtin """ assert isinstance(s, str) mem.SetVar(lhs_expr.LhsName(name), value.Str(s), (), scope_e.LocalOnly)
def ToLValue(node): # type: (arith_expr_t) -> lhs_expr_t """Determine if a node is a valid L-value by whitelisting tags. Args: node: ExprNode (could be VarExprNode or BinaryExprNode) """ # foo = bar, foo[1] = bar if isinstance(node, arith_expr__VarRef): # For consistency with osh/cmd_parse.py, append a span_id. # TODO: (( a[ x ] = 1 )) and a[x]=1 should use different LST nodes. n = lhs_expr.LhsName(node.token.val) n.spids.append(node.token.span_id) return n if isinstance(node, arith_expr__Binary): # For example, a[0][0] = 1 is NOT valid. if (node.op_id == Id.Arith_LBracket and isinstance(node.left, arith_expr__VarRef)): return lhs_expr.LhsIndexedName(node.left.token.val, node.right) return None
def ExportGlobalString(mem, name, s): """Helper for completion, $PWD, $OLDPWD, etc.""" assert isinstance(s, str) val = value.Str(s) mem.SetVar(lhs_expr.LhsName(name), val, (var_flags_e.Exported,), scope_e.GlobalOnly)
def SetGlobalArray(mem, name, a): """Helper for completion.""" assert isinstance(a, list) mem.SetVar(lhs_expr.LhsName(name), value.StrArray(a), (), scope_e.GlobalOnly)
def SetGlobalString(mem, name, s): """Helper for completion, etc.""" assert isinstance(s, str) val = value.Str(s) mem.SetVar(lhs_expr.LhsName(name), val, (), scope_e.GlobalOnly)
def SetGlobalFunc(mem, name, func): """Used by bin/oil.py to set split(), etc.""" assert callable(func), func mem.SetVar(lhs_expr.LhsName(name), value.Obj(func), (), scope_e.GlobalOnly)