1if not modules then modules = { } end modules ['trac-pro'] = {
2 version = 1.001,
3 comment = "companion to luat-lib.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local getmetatable, setmetatable, rawset, type, next = getmetatable, setmetatable, rawset, type, next
10
11
12
13
14
15
16
17
18local trace_namespaces = false trackers.register("system.namespaces", function(v) trace_namespaces = v end)
19
20local report_system = logs.reporter("system","protection")
21
22namespaces = namespaces or { }
23local namespaces = namespaces
24
25local registered = { }
26
27local function report_index(k,name)
28 if trace_namespaces then
29 report_system("reference to %a in protected namespace %a: %s",k,name)
30 debugger.showtraceback(report_system)
31 else
32 report_system("reference to %a in protected namespace %a",k,name)
33 end
34end
35
36local function report_newindex(k,name)
37 if trace_namespaces then
38 report_system("assignment to %a in protected namespace %a: %s",k,name)
39 debugger.showtraceback(report_system)
40 else
41 report_system("assignment to %a in protected namespace %a",k,name)
42 end
43end
44
45local function register(name)
46 local data = name == "global" and _G or _G[name]
47 if not data then
48 return
49 end
50 registered[name] = data
51 local m = getmetatable(data)
52 if not m then
53 m = { }
54 setmetatable(data,m)
55 end
56 local index, newindex = { }, { }
57 m.__saved__index = m.__index
58 m.__no__index = function(t,k)
59 if not index[k] then
60 index[k] = true
61 report_index(k,name)
62 end
63 return nil
64 end
65 m.__saved__newindex = m.__newindex
66 m.__no__newindex = function(t,k,v)
67 if not newindex[k] then
68 newindex[k] = true
69 report_newindex(k,name)
70 end
71 rawset(t,k,v)
72 end
73 m.__protection__depth = 0
74end
75
76local function private(name)
77 local data = registered[name]
78 if not data then
79 data = _G[name]
80 if not data then
81 data = { }
82 _G[name] = data
83 end
84 register(name)
85 end
86 return data
87end
88
89local function protect(name)
90 local data = registered[name]
91 if not data then
92 return
93 end
94 local m = getmetatable(data)
95 local pd = m.__protection__depth
96 if pd > 0 then
97 m.__protection__depth = pd + 1
98 else
99 m.__save_d_index, m.__saved__newindex = m.__index, m.__newindex
100 m.__index, m.__newindex = m.__no__index, m.__no__newindex
101 m.__protection__depth = 1
102 end
103end
104
105local function unprotect(name)
106 local data = registered[name]
107 if not data then
108 return
109 end
110 local m = getmetatable(data)
111 local pd = m.__protection__depth
112 if pd > 1 then
113 m.__protection__depth = pd - 1
114 else
115 m.__index, m.__newindex = m.__saved__index, m.__saved__newindex
116 m.__protection__depth = 0
117 end
118end
119
120local function protectall()
121 for name, _ in next, registered do
122 if name ~= "global" then
123 protect(name)
124 end
125 end
126end
127
128local function unprotectall()
129 for name, _ in next, registered do
130 if name ~= "global" then
131 unprotect(name)
132 end
133 end
134end
135
136namespaces.register = register
137namespaces.private = private
138namespaces.protect = protect
139namespaces.unprotect = unprotect
140namespaces.protectall = protectall
141namespaces.unprotectall = unprotectall
142
143namespaces.private("namespaces") registered = { } register("global")
144
145directives.register("system.protect", function(v)
146 if v then
147 protectall()
148 else
149 unprotectall()
150 end
151end)
152
153directives.register("system.checkglobals", function(v)
154 if v then
155 report_system("enabling global namespace guard")
156 protect("global")
157 else
158 report_system("disabling global namespace guard")
159 unprotect("global")
160 end
161end)
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 |