Added spec:commit task to commit changes to spec/ruby sources.
[rbx.git] / shotgun / lib / ffi_util.c
blob3201ea1e729dd5a8d787f49a7806c59df1b95bfa
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/un.h>
4 #include <netinet/in.h>
5 #include <netdb.h>
6 #include <errno.h>
7 #include <time.h>
9 #include "shotgun/lib/shotgun.h"
10 #include "shotgun/lib/symbol.h"
11 #include "shotgun/lib/object.h"
12 #include "shotgun/lib/tuple.h"
13 #include "shotgun/lib/hash.h"
14 #include "shotgun/lib/string.h"
15 #include "shotgun/lib/primitive_indexes.h"
17 int ffi_errno() { return errno; }
19 void ffi_set_errno(int n) {
20 errno = n;
23 time_t ffi_timezone() {
24 return timezone;
27 char* ffi_tzname(int dst) {
28 if(dst) {
29 return tzname[1];
30 } else {
31 return tzname[0];
36 int ffi_daylight() {
37 return daylight;
41 OBJECT ffi_new_pointer(STATE, void *ptr) {
42 void **code_start;
43 OBJECT obj;
45 NEW_STRUCT(obj, code_start, BASIC_CLASS(ffi_ptr), void*);
46 *code_start = (void*)ptr;
48 return obj;
51 void ffi_autorelease(OBJECT ptr, int ar) {
52 type_assert(ptr, MemPtrType, "passing a pointer");
53 ptr->RequiresCleanup = (ar ? 1 : 0);
56 void ffi_set_address(OBJECT ptr, void *addr) {
57 type_assert(ptr, MemPtrType, "passing a pointer");
58 *DATA_STRUCT(ptr, void**) = addr;
61 uintptr_t ffi_address(void *ptr) {
62 return (uintptr_t)ptr;
65 int ffi_write_int(int *ptr, int val) {
66 *ptr = val;
67 return val;
70 int ffi_read_int(int *ptr) {
71 return *ptr;
74 long ffi_write_long(long *ptr, long val) {
75 *ptr = val;
76 return val;
79 long ffi_read_long(long *ptr) {
80 return *ptr;
83 double ffi_write_float(double *ptr, double val) {
84 *ptr = val;
85 return val;
88 double ffi_read_float(double *ptr) {
89 return *ptr;
92 char *ffi_read_string(char *ptr) {
93 return ptr;
96 OBJECT ffi_read_string_length(STATE, void *ptr, int len) {
97 OBJECT str = string_new2(state, NULL, len);
99 memcpy(rbx_string_as_cstr(state, str), ptr, len);
101 return str;
104 int ffi_write_string_length(STATE, void *ptr, void* str, int len) {
105 void *src = rbx_string_as_cstr(state, str);
107 memcpy(ptr, src, len);
109 return len;
112 void *ffi_read_pointer(void **ptr) {
113 return *ptr;
116 char *ffi_sprintf_f(double value, int size, char *fmt) {
117 char *str = ALLOC_N(char, size);
118 snprintf(str, size, fmt, value);
119 return str;
122 char *ffi_sprintf_d(int value, int size, char *fmt) {
123 char *str = ALLOC_N(char, size);
124 snprintf(str, size, fmt, value);
125 return str;
128 OBJECT ffi_pack_sockaddr_un(STATE, char *path) {
129 struct sockaddr_un *sa;
131 sa = ALLOC(struct sockaddr_un);
132 memset(sa, 0, sizeof(struct sockaddr_un));
134 strncpy(sa->sun_path, path, sizeof(sa->sun_path) - 1);
136 return string_new2(state, (char*) sa, sizeof(struct sockaddr_un) );
139 OBJECT ffi_getnameinfo(STATE, struct sockaddr *sockaddr, socklen_t sockaddr_len,
140 int flags) {
141 char node[NI_MAXHOST], service[NI_MAXSERV];
142 OBJECT value, host, port, ip;
143 int err;
145 host = Qnil;
146 if(!(flags & NI_NUMERICHOST)) {
147 err = getnameinfo(sockaddr, sockaddr_len, node, NI_MAXHOST, NULL, 0, 0);
149 if(err != 0) {
150 return tuple_new2(state, 2, Qfalse,
151 string_new(state, gai_strerror(err)));
153 host = string_new2(state, node, strlen(node));
156 err = getnameinfo(sockaddr, sockaddr_len, node, NI_MAXHOST,
157 service, NI_MAXSERV, flags | NI_NUMERICHOST | NI_NUMERICSERV);
159 if(err != 0) {
160 return tuple_new2(state, 2, Qfalse,
161 string_new(state, gai_strerror(err)));
164 ip = string_new2(state, node, strlen(node));
165 port = I2N(atoi(service));
168 value = array_new(state, 0);
169 array_append(state, value, I2N(sockaddr->sa_family));
170 array_append(state, value, port);
171 array_append(state, value, host);
172 array_append(state, value, ip);
174 return tuple_new2(state, 2, Qtrue, value);
177 void *ffi_add_ptr(char *ptr, int offset) {
178 return (void*)(ptr + offset);
181 unsigned int ffi_cast(unsigned int val) {
182 return val;
185 long ffi_major(dev_t n) {
186 #if defined(major)
187 return major(n);
188 #else
189 return -1;
190 #endif
193 long ffi_minor(dev_t n) {
194 #if defined(minor)
195 return minor(n);
196 #else
197 return -1;
198 #endif
201 /* FIXME: these are TEMPORARY until we determine how to
202 * have FFI resolve symbols that may be macros. This is
203 * used rather than a primitive so that it is easier to
204 * replace (unlike primitives).
206 int ffi_stat(const char *path, struct stat *buf) {
207 return stat(path, buf);
210 int ffi_lstat(const char *path, struct stat *buf) {
211 return lstat(path, buf);