1 /*
2
3 Copyright (c) 2009-2013 uim Project https://github.com/uim/uim
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of authors nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31
32 */
33
34 #include <config.h>
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdint.h>
40 #include <sys/types.h>
41 #ifdef HAVE_MMAP
42 #include <sys/mman.h>
43 #endif
44
45 #include "uim.h"
46 #include "uim-scm.h"
47 #include "uim-scm-abbrev.h"
48 #include "uim-posix.h"
49 #include "uim-notify.h"
50 #include "dynlib.h"
51
52 typedef struct {
53 int flag;
54 char *arg;
55 } opt_args;
56
57 static uim_lisp
make_arg_cons(const opt_args * arg)58 make_arg_cons(const opt_args *arg)
59 {
60 return CONS(MAKE_SYM(arg->arg), MAKE_INT(arg->flag));
61 }
62
63 static uim_lisp
make_arg_list(const opt_args * list)64 make_arg_list(const opt_args *list)
65 {
66 uim_lisp ret_;
67 int i = 0;
68
69 ret_ = uim_scm_null();
70 while (list[i].arg != 0) {
71 ret_ = CONS((uim_lisp)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)make_arg_cons,
72 (void *)&list[i]), ret_);
73 i++;
74 }
75 return ret_;
76 }
77
78 static uim_lisp
c_allocate(uim_lisp len_)79 c_allocate(uim_lisp len_)
80 {
81 return MAKE_PTR(malloc(C_INT(len_)));
82 }
83 static uim_lisp
c_free(uim_lisp pointer_)84 c_free(uim_lisp pointer_)
85 {
86 free(C_PTR(pointer_));
87 return uim_scm_t();
88 }
89 static uim_lisp
90
c_memory_fill(uim_lisp pointer_,uim_lisp c_,uim_lisp len_)91 c_memory_fill(uim_lisp pointer_, uim_lisp c_, uim_lisp len_)
92 {
93 int c;
94
95 if (CHARP(c_))
96 c = C_CHAR(c_);
97 else if (STRP(c_))
98 c = C_STR(c_)[0];
99 else
100 c = C_INT(c_);
101
102 memset(C_PTR(pointer_), c, C_INT(len_));
103 return uim_scm_t();
104 }
105 static uim_lisp
c_memory_move(uim_lisp dest_,uim_lisp src_,uim_lisp len_)106 c_memory_move(uim_lisp dest_, uim_lisp src_, uim_lisp len_)
107 {
108 if (STRP(src_))
109 strlcpy(C_PTR(dest_), REFER_C_STR(src_), C_INT(len_));
110 else
111 memmove(C_PTR(dest_), C_PTR(src_), C_INT(len_));
112 return uim_scm_t();
113 }
114
115 #ifdef HAVE_MMAP
116
117 const static opt_args mmap_prot_flags[] = {
118 { PROT_EXEC, "$PROT_EXEC" },
119 { PROT_READ, "$PROT_READ" },
120 { PROT_WRITE, "$PROT_WRITE" },
121 { PROT_NONE, "$PROT_NONE" },
122 { 0, 0 }
123 };
124
125 static uim_lisp uim_lisp_mmap_prot_flags;
126 static uim_lisp
c_mmap_prot_flags(void)127 c_mmap_prot_flags(void)
128 {
129 return uim_lisp_mmap_prot_flags;
130 }
131
132 const static opt_args mmap_flags[] = {
133 #ifdef MAP_ANON
134 { MAP_ANON, "$MAP_ANON" },
135 #endif
136 #ifdef MAP_ANONYMOUS
137 { MAP_ANONYMOUS, "$MAP_ANONYMOUS" },
138 #endif
139 #ifdef MAP_FILE
140 { MAP_FILE, "$MAP_FILE" },
141 #endif
142 #ifdef MAP_FIXED
143 { MAP_FIXED, "$MAP_FIXED" },
144 #endif
145 { MAP_PRIVATE, "$MAP_PRIVATE" },
146 { MAP_SHARED, "$MAP_SHARED" },
147 #ifdef MAP_COPY
148 { MAP_COPY, "$MAP_COPY" },
149 #endif
150 { 0, 0 }
151 };
152
153 static uim_lisp uim_lisp_mmap_flags;
154 static uim_lisp
c_mmap_flags(void)155 c_mmap_flags(void)
156 {
157 return uim_lisp_mmap_flags;
158 }
159
160 static uim_lisp
c_mmap(uim_lisp addr_,uim_lisp len_,uim_lisp prot_flags_,uim_lisp fd_,uim_lisp offset_)161 c_mmap(uim_lisp addr_, uim_lisp len_, uim_lisp prot_flags_, uim_lisp fd_, uim_lisp offset_)
162 {
163 void *p = mmap(C_PTR(addr_), C_INT(len_), C_INT(CAR(prot_flags_)), C_INT(CDR(prot_flags_)), C_INT(fd_), C_INT(offset_));
164
165 if (p == MAP_FAILED)
166 return uim_scm_f();
167 return MAKE_PTR(p);
168 }
169
170 static uim_lisp
c_munmap(uim_lisp addr_,uim_lisp len_)171 c_munmap(uim_lisp addr_, uim_lisp len_)
172 {
173 return MAKE_INT(munmap(C_PTR(addr_), C_INT(len_)));
174 }
175
176 #endif
177
178 static uim_lisp
c_null_pointer(void)179 c_null_pointer(void)
180 {
181 return MAKE_PTR(NULL);
182 }
183
184 static uim_lisp
c_pointer_offset(uim_lisp pointer_,uim_lisp nth_)185 c_pointer_offset(uim_lisp pointer_, uim_lisp nth_)
186 {
187 return MAKE_PTR((char *)C_PTR(pointer_) + C_INT(nth_));
188 }
189
190 #define c_pointer_X_ref(X, type) \
191 static uim_lisp \
192 c_pointer_ ## X ## _ref(uim_lisp pointer_) \
193 { \
194 type *p = C_PTR(pointer_); \
195 return MAKE_INT(*p); \
196 }
197
c_pointer_X_ref(u8,uint8_t)198 c_pointer_X_ref(u8, uint8_t)
199 c_pointer_X_ref(s8, int8_t)
200 c_pointer_X_ref(u16, uint16_t)
201 c_pointer_X_ref(s16, int16_t)
202 c_pointer_X_ref(u32, uint32_t)
203 c_pointer_X_ref(s32, int32_t)
204 c_pointer_X_ref(u64, uint64_t)
205 c_pointer_X_ref(s64, int64_t)
206
207 #define c_pointer_X_set(X, type) \
208 static uim_lisp \
209 c_pointer_ ## X ## _set(uim_lisp pointer_, uim_lisp val_) \
210 { \
211 type *p = C_PTR(pointer_); \
212 *p = C_INT(val_); \
213 return uim_scm_t(); \
214 }
215
216 c_pointer_X_set(u8, uint8_t)
217 c_pointer_X_set(s8, int8_t)
218 c_pointer_X_set(u16, uint16_t)
219 c_pointer_X_set(s16, int16_t)
220 c_pointer_X_set(u32, uint32_t)
221 c_pointer_X_set(s32, int32_t)
222 c_pointer_X_set(u64, uint64_t)
223 c_pointer_X_set(s64, int64_t)
224
225 static uim_lisp
226 c_string_to_pointer(uim_lisp str_)
227 {
228 return MAKE_PTR(C_STR(str_));
229 }
230 static uim_lisp
c_pointer_to_string(uim_lisp pointer_)231 c_pointer_to_string(uim_lisp pointer_)
232 {
233 return MAKE_STR(C_PTR(pointer_));
234 }
235
236
237 #define c_Xlist_to_pointer(X, type) \
238 static uim_lisp \
239 c_ ## X ## list_to_pointer(uim_lisp l_) \
240 { \
241 type *p; \
242 int i, len = uim_scm_length(l_); \
243 \
244 p = malloc(len * sizeof(type)); \
245 for (i = 0; i < len; i++) { \
246 uim_lisp h_ = CAR(l_); \
247 \
248 p[i] = (type)C_INT(h_); \
249 l_ = CDR(l_); \
250 } \
251 return MAKE_PTR(p); \
252 }
253
c_Xlist_to_pointer(s8,int8_t)254 c_Xlist_to_pointer(s8, int8_t)
255 c_Xlist_to_pointer(u8, uint8_t)
256 c_Xlist_to_pointer(s16, int16_t)
257 c_Xlist_to_pointer(u16, uint16_t)
258 c_Xlist_to_pointer(s32, int32_t)
259 c_Xlist_to_pointer(u32, uint32_t)
260 c_Xlist_to_pointer(s64, int64_t)
261 c_Xlist_to_pointer(u64, uint64_t)
262
263 #define c_pointer_to_Xlist(X, type) \
264 struct c__pointer_to_ ## X ## list_args { \
265 type *pointer; \
266 int len; \
267 }; \
268 \
269 static uim_lisp \
270 c_pointer_to_ ## X ## list_internal(struct c__pointer_to_ ## X ## list_args *args) \
271 { \
272 uim_lisp ret_ = uim_scm_null(); \
273 int i; \
274 type *p = args->pointer; \
275 \
276 for (i = 0; i < args->len; i++) \
277 ret_ = CONS(MAKE_INT(*p++), ret_); \
278 return ret_; \
279 } \
280 static uim_lisp \
281 c_pointer_to_ ## X ## list(uim_lisp pointer_, uim_lisp len_) \
282 { \
283 uim_lisp ret_; \
284 struct c__pointer_to_ ## X ## list_args args; \
285 \
286 args.pointer = C_PTR(pointer_); \
287 args.len = C_INT(len_); \
288 ret_ = (uim_lisp)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)c_pointer_to_ ## X ## list_internal, (void *)&args); \
289 return uim_scm_callf("reverse", "o", ret_); \
290 }
291
292 c_pointer_to_Xlist(u8, uint8_t)
293 c_pointer_to_Xlist(s8, int8_t)
294 c_pointer_to_Xlist(u16, uint16_t)
295 c_pointer_to_Xlist(s16, int16_t)
296 c_pointer_to_Xlist(u32, uint32_t)
297 c_pointer_to_Xlist(s32, int32_t)
298 c_pointer_to_Xlist(u64, uint64_t)
299 c_pointer_to_Xlist(s64, int64_t)
300
301
302 static uim_lisp
303 c_htons(uim_lisp u16_)
304 {
305 return MAKE_INT(htons(C_INT(u16_)));
306 }
307 static uim_lisp
c_htonl(uim_lisp u32_)308 c_htonl(uim_lisp u32_)
309 {
310 return MAKE_INT(htonl(C_INT(u32_)));
311 }
312
313 static uim_lisp
c_ntohs(uim_lisp u16_)314 c_ntohs(uim_lisp u16_)
315 {
316 return MAKE_INT(ntohs(C_INT(u16_)));
317 }
318 static uim_lisp
c_ntohl(uim_lisp u32_)319 c_ntohl(uim_lisp u32_)
320 {
321 return MAKE_INT(ntohl(C_INT(u32_)));
322 }
323
324
325 static uim_lisp
c_u16_to_u8list(uim_lisp u16_)326 c_u16_to_u8list(uim_lisp u16_)
327 {
328 uint16_t u16 = htons(C_INT(u16_));
329
330 return LIST2(MAKE_INT(u16 & 0xff),
331 MAKE_INT((u16 >> 8) & 0xff));
332 }
333 static uim_lisp
c_u32_to_u8list(uim_lisp u32_)334 c_u32_to_u8list(uim_lisp u32_)
335 {
336 uint32_t u32 = htonl(C_INT(u32_));
337
338 return LIST4(MAKE_INT(u32 & 0xff),
339 MAKE_INT((u32 >> 8) & 0xff),
340 MAKE_INT((u32 >> 16) & 0xff),
341 MAKE_INT((u32 >> 24) & 0xff));
342 }
343
344 /* (map char->integer (string->list str)) */
345 static uim_lisp
c_string_to_u8list(uim_lisp str_)346 c_string_to_u8list(uim_lisp str_)
347 {
348 const char *str = REFER_C_STR(str_);
349 uim_lisp ret_ = uim_scm_null();
350
351 while (*str) {
352 ret_ = CONS(MAKE_INT(*str & 0xff), ret_);
353 str++;
354 }
355 ret_ = CONS(MAKE_INT(0), ret_);
356 return uim_scm_callf("reverse", "o", ret_);
357 }
358
359 static uim_lisp
c_u8list_to_u16(uim_lisp u8list_)360 c_u8list_to_u16(uim_lisp u8list_)
361 {
362 uint8_t u8_1, u8_2;
363
364 u8_1 = C_INT(CAR(u8list_));
365 u8_2 = C_INT(CAR(CDR(u8list_)));
366 return MAKE_INT(ntohs(u8_1 |
367 (u8_2 << 8)));
368 }
369 static uim_lisp
c_u8list_to_u32(uim_lisp u8list_)370 c_u8list_to_u32(uim_lisp u8list_)
371 {
372 uint8_t u8_1, u8_2, u8_3, u8_4;
373
374 u8_1 = C_INT(CAR(u8list_));
375 u8_2 = C_INT(CAR(CDR(u8list_)));
376 u8_3 = C_INT(CAR(CDR(CDR(u8list_))));
377 u8_4 = C_INT(CAR(CDR(CDR(CDR(u8list_)))));
378 return MAKE_INT(ntohl(u8_1 |
379 (u8_2 << 8) |
380 (u8_3 << 16) |
381 (u8_4 << 24)));
382 }
383 static uim_lisp
c_u8list_to_string(uim_lisp u8list_)384 c_u8list_to_string(uim_lisp u8list_)
385 {
386 int len = uim_scm_length(u8list_);
387 int i;
388 char *str = uim_malloc(len + 1);
389
390 for (i = 0; i < len; i++) {
391 str[i] = (char)C_INT(CAR(u8list_));
392 u8list_ = CDR(u8list_);
393 }
394 str[len] = '\0';
395 return MAKE_STR_DIRECTLY(str);
396 }
397
398 static uim_lisp
c_u32_to_s32(uim_lisp u32_)399 c_u32_to_s32(uim_lisp u32_)
400 {
401 uint32_t u32 = C_INT(u32_);
402
403 return MAKE_INT((int32_t)u32);
404 }
405
406 void
uim_plugin_instance_init(void)407 uim_plugin_instance_init(void)
408 {
409 uim_scm_init_proc1("allocate", c_allocate);
410 uim_scm_init_proc1("free", c_free);
411
412 uim_scm_init_proc3("memory-fill!", c_memory_fill);
413 uim_scm_init_proc3("memory-move!", c_memory_move);
414
415 #ifdef HAVE_MMAP
416 uim_lisp_mmap_prot_flags = make_arg_list(mmap_prot_flags);
417 uim_scm_gc_protect(&uim_lisp_mmap_prot_flags);
418 uim_scm_init_proc0("mmap-prot-flags?", c_mmap_prot_flags);
419 uim_lisp_mmap_flags = make_arg_list(mmap_flags);
420 uim_scm_gc_protect(&uim_lisp_mmap_flags);
421 uim_scm_init_proc0("mmap-flags?", c_mmap_flags);
422
423 uim_scm_init_proc5("mmap", c_mmap);
424 uim_scm_init_proc2("munmap", c_munmap);
425 #endif
426
427 uim_scm_init_proc0("null-pointer", c_null_pointer);
428
429 uim_scm_init_proc2("pointer-offset", c_pointer_offset);
430
431 uim_scm_init_proc1("pointer-u8-ref", c_pointer_u8_ref);
432 uim_scm_init_proc1("pointer-s8-ref", c_pointer_s8_ref);
433 uim_scm_init_proc1("pointer-u16-ref", c_pointer_u16_ref);
434 uim_scm_init_proc1("pointer-s16-ref", c_pointer_s16_ref);
435 uim_scm_init_proc1("pointer-u32-ref", c_pointer_u32_ref);
436 uim_scm_init_proc1("pointer-s32-ref", c_pointer_s32_ref);
437 uim_scm_init_proc1("pointer-u64-ref", c_pointer_u64_ref);
438 uim_scm_init_proc1("pointer-s64-ref", c_pointer_s64_ref);
439
440 uim_scm_init_proc2("pointer-u8-set!", c_pointer_u8_set);
441 uim_scm_init_proc2("pointer-s8-set!", c_pointer_s8_set);
442 uim_scm_init_proc2("pointer-u16-set!", c_pointer_u16_set);
443 uim_scm_init_proc2("pointer-s16-set!", c_pointer_s16_set);
444 uim_scm_init_proc2("pointer-u32-set!", c_pointer_u32_set);
445 uim_scm_init_proc2("pointer-s32-set!", c_pointer_s32_set);
446 uim_scm_init_proc2("pointer-u64-set!", c_pointer_u64_set);
447 uim_scm_init_proc2("pointer-s64-set!", c_pointer_s64_set);
448
449 uim_scm_init_proc1("string->pointer", c_string_to_pointer);
450 uim_scm_init_proc1("pointer->string", c_pointer_to_string);
451
452 uim_scm_init_proc1("u8list->pointer", c_u8list_to_pointer);
453 uim_scm_init_proc1("s8list->pointer", c_s8list_to_pointer);
454 uim_scm_init_proc1("u16list->pointer", c_u16list_to_pointer);
455 uim_scm_init_proc1("s16list->pointer", c_s16list_to_pointer);
456 uim_scm_init_proc1("u32list->pointer", c_u32list_to_pointer);
457 uim_scm_init_proc1("s32list->pointer", c_s32list_to_pointer);
458 uim_scm_init_proc1("u64list->pointer", c_u64list_to_pointer);
459 uim_scm_init_proc1("s64list->pointer", c_s64list_to_pointer);
460
461 uim_scm_init_proc2("pointer->u8list", c_pointer_to_u8list);
462 uim_scm_init_proc2("pointer->s8list", c_pointer_to_s8list);
463 uim_scm_init_proc2("pointer->u16list", c_pointer_to_u16list);
464 uim_scm_init_proc2("pointer->s16list", c_pointer_to_s16list);
465 uim_scm_init_proc2("pointer->u32list", c_pointer_to_u32list);
466 uim_scm_init_proc2("pointer->s32list", c_pointer_to_s32list);
467 uim_scm_init_proc2("pointer->u64list", c_pointer_to_u64list);
468 uim_scm_init_proc2("pointer->s64list", c_pointer_to_s64list);
469
470 uim_scm_init_proc1("htons", c_htons);
471 uim_scm_init_proc1("htonl", c_htonl);
472 uim_scm_init_proc1("ntohs", c_ntohs);
473 uim_scm_init_proc1("ntohl", c_ntohl);
474
475 uim_scm_init_proc1("u16->u8list", c_u16_to_u8list);
476 uim_scm_init_proc1("u32->u8list", c_u32_to_u8list);
477 uim_scm_init_proc1("string->u8list", c_string_to_u8list);
478
479 uim_scm_init_proc1("u8list->u16", c_u8list_to_u16);
480 uim_scm_init_proc1("u8list->u32", c_u8list_to_u32);
481 uim_scm_init_proc1("u8list->string", c_u8list_to_string);
482
483 uim_scm_init_proc1("u32->s32", c_u32_to_s32);
484 }
485
486 void
uim_plugin_instance_quit(void)487 uim_plugin_instance_quit(void)
488 {
489 #ifdef HAVE_MMAP
490 uim_scm_gc_unprotect(&uim_lisp_mmap_prot_flags);
491 uim_scm_gc_unprotect(&uim_lisp_mmap_flags);
492 #endif
493 }
494