forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenv.jl
137 lines (121 loc) · 3.74 KB
/
env.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
## core libc calls ##
@unix_only begin
_getenv(var::String) = ccall(:getenv, Ptr{Uint8}, (Ptr{Uint8},), var)
_hasenv(s::String) = _getenv(s) != C_NULL
end
@windows_only begin
_getenvlen(var::String) = ccall(:GetEnvironmentVariableA,stdcall,Uint32,(Ptr{Uint8},Ptr{Uint8},Uint32),var,C_NULL,0)
_hasenv(s::String) = _getenvlen(s)!=0
function _jl_win_getenv(s::String,len::Uint32)
val=zeros(Uint8,len-1)
ret=ccall(:GetEnvironmentVariableA,stdcall,Uint32,(Ptr{Uint8},Ptr{Uint8},Uint32),s,val,len)
if ret==0||ret!=len-1 #Trailing 0 is only included on first call to GetEnvA
error("getenv: unknown system error: ", s, len, ret)
end
val
end
end
macro accessEnv(var,errorcase)
@unix_only return quote
val=_getenv($var)
if val == C_NULL
$errorcase
end
bytestring(val)
end
@windows_only return quote
len=_getenvlen($var)
if len == 0
$errorcase
end
bytestring(_jl_win_getenv($var,len))
end
end
function _setenv(var::String, val::String, overwrite::Bool)
@unix_only begin
ret = ccall(:setenv, Int32, (Ptr{Uint8},Ptr{Uint8},Int32), var, val, overwrite)
systemerror(:setenv, ret != 0)
end
@windows_only begin
if overwrite||!_hasenv(var)
ret = ccall(:SetEnvironmentVariableA,stdcall,Int32,(Ptr{Uint8},Ptr{Uint8}),var,val)
systemerror(:setenv, ret == 0)
end
end
end
_setenv(var::String, val::String) = _setenv(var, val, true)
function _unsetenv(var::String)
@unix_only begin
ret = ccall(:unsetenv, Int32, (Ptr{Uint8},), var)
systemerror(:unsetenv, ret != 0)
end
@windows_only begin
ret = ccall(:SetEnvironmentVariableA,stdcall,Int32,(Ptr{Uint8},Ptr{Uint8}),var,C_NULL)
systemerror(:setenv, ret == 0)
end
end
## ENV: hash interface ##
@unix_only type EnvHash <: Associative{ByteString,ByteString}; end
@windows_only type EnvHash <: Associative{ByteString,ByteString}
block::Ptr{Uint8}
EnvHash() = new(C_NULL)
end
const ENV = EnvHash()
getindex(::EnvHash, k::String) = @accessEnv k throw(KeyError(k))
get(::EnvHash, k::String, def) = @accessEnv k (return def)
contains(::KeyIterator{EnvHash}, k::String) = _hasenv(k)
delete!(::EnvHash, k::String) = (v = ENV[k]; _unsetenv(k); v)
delete!(::EnvHash, k::String, def) = haskey(ENV,k) ? delete!(ENV,k) : def
setindex!(::EnvHash, v, k::String) = _setenv(k,string(v))
@unix_only begin
start(::EnvHash) = 0
done(::EnvHash, i) = (ccall(:jl_environ, Any, (Int32,), i) == nothing)
function next(::EnvHash, i)
env = ccall(:jl_environ, Any, (Int32,), i)
if env == nothing
error(BoundsError)
end
env::ByteString
m = match(r"^(.*?)=(.*)$"s, env)
if m == nothing
error("malformed environment entry: $env")
end
(m.captures, i+1)
end
end
@windows_only begin
start(hash::EnvHash) = (hash.block = ccall(:GetEnvironmentStringsA,stdcall,Ptr{Uint8},()))
function done(hash::EnvHash, pos::Ptr{Uint8})
if ccall(:jl_env_done,Any,(Ptr{Uint8},),pos)::Bool
ccall(:FreeEnvironmentStringsA,stdcall,Int32,(Ptr{Uint8},),hash.block)
hash.block=C_NULL
return true
end
false
end
function next(hash::EnvHash, pos::Ptr{Uint8})
len = ccall(:strlen, Uint, (Ptr{Uint8},), pos)
env=ccall(:jl_pchar_to_string, Any, (Ptr{Uint8},Int), pos, len)::ByteString
m = match(r"^(.*?)=(.*)$"s, env)
if m == nothing
error("malformed environment entry: $env")
end
(m.captures, pos+len+1)
end
end
#TODO: Make these more efficent
function length(::EnvHash)
i = 0
for (k,v) in ENV
i += 1
end
return i
end
function show(io::IO, ::EnvHash)
for (k,v) = ENV
println(io, "$k=$v")
end
end
## misc environment-related functionality ##
tty_cols() = parseint(Int32, get(ENV,"COLUMNS","80"), 10)
tty_rows() = parseint(Int32, get(ENV,"LINES","25"), 10)