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
|
#include "rust_internal.h"
/* Native builtins. */
extern "C" CDECL rust_str*
last_os_error(rust_task *task) {
rust_dom *dom = task->dom;
task->log(rust_log::TASK, "last_os_error()");
#if defined(__WIN32__)
LPTSTR buf;
DWORD err = GetLastError();
DWORD res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &buf, 0, NULL);
if (!res) {
task->fail(1);
return NULL;
}
#elif defined(_GNU_SOURCE)
char cbuf[1024];
char *buf = strerror_r(errno, cbuf, sizeof(cbuf));
if (!buf) {
task->fail(1);
return NULL;
}
#else
char buf[1024];
int err = strerror_r(errno, buf, sizeof(buf));
if (err) {
task->fail(1);
return NULL;
}
#endif
size_t fill = strlen(buf) + 1;
size_t alloc = next_power_of_two(sizeof(rust_str) + fill);
void *mem = dom->malloc(alloc);
if (!mem) {
task->fail(1);
return NULL;
}
rust_str *st = new (mem) rust_str(dom, alloc, fill, (const uint8_t *)buf);
#ifdef __WIN32__
LocalFree((HLOCAL)buf);
#endif
return st;
}
extern "C" CDECL size_t
size_of(rust_task *task, type_desc *t) {
return t->size;
}
extern "C" CDECL size_t
align_of(rust_task *task, type_desc *t) {
return t->align;
}
extern "C" CDECL size_t
refcount(rust_task *task, type_desc *t, size_t *v) {
// Passed-in value has refcount 1 too high
// because it was ref'ed while making the call.
return (*v) - 1;
}
extern "C" CDECL void
gc(rust_task *task) {
task->gc(1);
}
extern "C" CDECL void
unsupervise(rust_task *task) {
task->unsupervise();
}
extern "C" CDECL rust_vec*
vec_alloc(rust_task *task, type_desc *t, type_desc *elem_t, size_t n_elts)
{
rust_dom *dom = task->dom;
task->log(rust_log::MEM,
"vec_alloc %" PRIdPTR " elements of size %" PRIdPTR,
n_elts, elem_t->size);
size_t fill = n_elts * elem_t->size;
size_t alloc = next_power_of_two(sizeof(rust_vec) + fill);
void *mem = task->malloc(alloc, t->is_stateful ? t : NULL);
if (!mem) {
task->fail(4);
return NULL;
}
rust_vec *vec = new (mem) rust_vec(dom, alloc, 0, NULL);
return vec;
}
extern "C" CDECL void *
vec_buf(rust_task *task, type_desc *ty, rust_vec *v, size_t offset)
{
return (void *)&v->data[ty->size * offset];
}
extern "C" CDECL size_t
vec_len(rust_task *task, type_desc *ty, rust_vec *v)
{
return v->fill / ty->size;
}
/* Helper for str_alloc and str_from_vec. Returns NULL as failure. */
static rust_str *
str_alloc_with_data(rust_task *task,
size_t n_bytes,
size_t fill,
uint8_t const *d)
{
rust_dom *dom = task->dom;
size_t alloc = next_power_of_two(sizeof(rust_str) + n_bytes);
void *mem = dom->malloc(alloc);
if (!mem)
return NULL;
rust_str *st = new (mem) rust_str(dom, alloc, fill, d);
return st;
}
extern "C" CDECL rust_str*
str_alloc(rust_task *task, size_t n_bytes)
{
rust_str *st = str_alloc_with_data(task,
n_bytes + 1, // +1 to fit at least ""
1,
(uint8_t const *)"");
if (!st) {
task->fail(2);
return NULL;
}
return st;
}
extern "C" CDECL char const *
str_buf(rust_task *task, rust_str *s)
{
return (char const *)&s->data[0];
}
extern "C" CDECL size_t
str_byte_len(rust_task *task, rust_str *s)
{
return s->fill - 1; // -1 for the '\0' terminator.
}
extern "C" CDECL rust_str *
str_from_vec(rust_task *task, rust_vec *v)
{
rust_str *st =
str_alloc_with_data(task,
v->fill + 1, // +1 to fit at least '\0'
v->fill,
v->fill ? (uint8_t const *)v->data : NULL);
if (!st) {
task->fail(2);
return NULL;
}
st->data[st->fill++] = '\0';
return st;
}
extern "C" CDECL void *
rand_new(rust_task *task)
{
rust_dom *dom = task->dom;
randctx *rctx = (randctx *) task->malloc(sizeof(randctx));
if (!rctx) {
task->fail(1);
return NULL;
}
isaac_init(dom, rctx);
return rctx;
}
extern "C" CDECL size_t
rand_next(rust_task *task, randctx *rctx)
{
return rand(rctx);
}
extern "C" CDECL void
rand_free(rust_task *task, randctx *rctx)
{
task->free(rctx);
}
//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
|