Repository navigation
Expand file tree
/
Copy pathmodule.c
More file actions
230 lines (200 loc) · 6.28 KB
/
Copy pathmodule.c
File metadata and controls
230 lines (200 loc) · 6.28 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/*
* Copyright (c) 1993-2012 David Gay and Gustav Hållberg
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose, without fee, and without written agreement is hereby granted,
* provided that the above copyright notice and the following two paragraphs
* appear in all copies of this software.
*
* IN NO EVENT SHALL DAVID GAY OR GUSTAV HALLBERG BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF DAVID GAY OR
* GUSTAV HALLBERG HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* DAVID GAY AND GUSTAV HALLBERG SPECIFICALLY DISCLAIM ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
* "AS IS" BASIS, AND DAVID GAY AND GUSTAV HALLBERG HAVE NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include "alloc.h"
#include "global.h"
#include "module.h"
#include "table.h"
#include "runtime/mudlle-string.h"
/* Module states automaton:
-> unloaded <-
/ | \
| | \
| loading |
| / \ |
\ / \ /
error loaded
|
|
protected
*/
enum {
vmodule_status,
vmodule_seclev,
vmodule_size
};
struct table *module_data;
static ulong load_library_gidx;
enum module_status module_status(const char *name)
/* Returns: Status of module name:
module_unloaded: module has never been loaded, or has been unloaded
module_loaded: module loaded successfully
module_error: attempt to load module led to error
*/
{
struct symbol *sym = table_lookup(module_data, name);
if (sym == NULL)
return module_unloaded;
return intval(((struct vector *)sym->data)->data[vmodule_status]);
}
int module_seclevel(const char *name)
{
struct symbol *sym = table_lookup(module_data, name);
if (sym == NULL)
return -1;
return intval(((struct vector *)sym->data)->data[vmodule_seclev]);
}
void module_set(const char *name, enum module_status status, seclev_t seclev)
/* Effects: Sets module status
*/
{
struct symbol *sym = table_lookup(module_data, name);
if (sym)
{
struct vector *v = sym->data;
v->data[vmodule_status] = makeint(status);
v->data[vmodule_seclev] = makeint(seclev);
return;
}
assert(strlen(name) <= MAX_MODULE_NAME_LENGHT);
struct vector *v = alloc_vector(vmodule_size);
v->data[vmodule_status] = makeint(status);
v->data[vmodule_seclev] = makeint(seclev);
table_set(module_data, name, v);
}
bool module_unload(const char *name)
/* Effects: Removes all knowledge about module 'name' (eg prior to
reloading it)
module_status(name) will return module_unloaded if this operation is
successful
Sets to null all variables that belonged to name, and resets their status
to var_normal
Returns: false if name was protected or loading
*/
{
switch (module_status(name))
{
case module_unloaded:
return true;
case module_loading:
case module_protected:
return false;
case module_error:
case module_loaded:
break;
}
ulong gsize = nglobals();
for (ulong i = 0; i < gsize; i++)
{
struct string *v = mvars->data[i];
/* Unset module vars */
if (pointerp(v) && strcasecmp(name, v->str) == 0)
{
mvars->data[i] = makeint(var_normal);
GVAR(i) = NULL;
}
}
/* Safe even if name comes from a mudlle string,
because we know that entry name already exists */
module_set(name, module_unloaded, 0);
return true;
}
static enum module_status module_load(const char *name)
/* Effects: Attempts to load module name by calling mudlle hook
Error/warning messages are sent to muderr
Sets erred to true in case of error
Updates module status
Modifies: erred
Requires: module_status(name) == module_unloaded
Returns: New module status
*/
{
if (callablep(GVAR(load_library_gidx), 1))
{
struct string *mname = alloc_string(name);
mcatch_call("load library", GVAR(load_library_gidx), mname);
}
return module_status(name);
}
enum module_status module_require(const char *name)
/* Effects: Does module_load(name) if module_status(name) == module_unloaded
Other effects as in module_load
*/
{
enum module_status status = module_status(name);
if (status == module_unloaded)
status = module_load(name);
return status;
}
enum vstatus module_vstatus(long n, struct string **name)
/* Returns: status of global variable n:
var_normal: normal global variable, no writes
var_write: global variable which is written
var_module: defined symbol of a module
module name is stored in *name
Modifies: name
Requires: n be a valid global variable offset
*/
{
assert(n >= 0 && n < nglobals());
*name = NULL;
value v = mvars->data[n];
if (integerp(v)) return intval(v);
if (v == NULL) return var_system_write;
assert(TYPE(v, string));
*name = v;
return var_module;
}
bool module_vset(long n, enum vstatus status, struct string *name,
bool dry_run)
/* Effects: Sets status of global variable n to status.
name is the module name for status var_module
Returns: true if successful, false if the change is impossible
(i.e., status was already var_module or var_system_{mutable,write})
*/
{
assert(n >= 0 && n < nglobals());
assert(status >= 0 && status <= var_system_mutable);
assert((name != NULL) == (status == var_module));
value old_state = mvars->data[n];
if (dry_run
&& name != NULL
&& TYPE(old_state, string)
&& string_equalp(old_state, name))
return true;
if (GCONSTANT(n) || old_state == makeint(var_system_mutable))
return false;
if (dry_run)
return true;
if (status == var_module)
mvars->data[n] = name;
else if (status == var_system_write)
mvars->data[n] = NULL;
else
mvars->data[n] = makeint(status);
return true;
}
void module_init(void)
/* Initialise this module */
{
module_data = alloc_table(DEF_TABLE_SIZE);
staticpro(&module_data);
load_library_gidx = global_lookup("load_library");
}