]> gitweb.factorcode.org Git - factor.git/blob - vm/os-windows.c
2001662ee1f790fa788274dd057c840c88666da2
[factor.git] / vm / os-windows.c
1 #include "factor.h"
2
3 F_STRING *get_error_message()
4 {
5         DWORD id = GetLastError();
6         char *msg = error_message(id);
7         F_STRING *string = from_char_string(msg);
8         LocalFree(msg);
9         return string;
10 }
11
12 /* You must LocalFree() the return value! */
13 char *error_message(DWORD id)
14 {
15         char *buffer;
16         int index;
17
18         FormatMessage(
19                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
20                 FORMAT_MESSAGE_FROM_SYSTEM,
21                 NULL,
22                 id,
23                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
24                 (LPTSTR) &buffer,
25                 0, NULL);
26
27         /* strip whitespace from end */
28         index = strlen(buffer) - 1;
29         while(index >= 0 && isspace(buffer[index]))
30                 buffer[index--] = 0;
31
32         return buffer;
33 }
34
35 s64 current_millis(void)
36 {
37         FILETIME t;
38         GetSystemTimeAsFileTime(&t);
39         return (((s64)t.dwLowDateTime | (s64)t.dwHighDateTime<<32)
40                 - EPOCH_OFFSET) / 10000;
41 }
42
43 void ffi_dlopen (F_DLL *dll, bool error)
44 {
45         HMODULE module = LoadLibrary(alien_offset(dll->path));
46
47         if (!module)
48         {
49                 dll->dll = NULL;
50                 if(error)
51                         simple_error(ERROR_FFI,F,
52                                 tag_object(get_error_message()));
53                 else
54                         return;
55         }
56
57         dll->dll = module;
58 }
59
60 void *ffi_dlsym (F_DLL *dll, char *symbol, bool error)
61 {
62         void *sym = GetProcAddress(
63                 dll ? (HMODULE)dll->dll : GetModuleHandle(NULL),
64                 symbol);
65
66         if (!sym)
67         {
68                 if(error)
69                         simple_error(ERROR_FFI,
70                                 tag_object(from_char_string(symbol)),
71                                 tag_object(get_error_message()));
72                 else
73                         return NULL;
74         }
75
76         return sym;
77 }
78
79 void ffi_dlclose (F_DLL *dll)
80 {
81         FreeLibrary((HMODULE)dll->dll);
82         dll->dll = NULL;
83 }
84
85 void primitive_stat(void)
86 {
87         WIN32_FILE_ATTRIBUTE_DATA st;
88
89         if(!GetFileAttributesEx(
90                 unbox_char_string(),
91                 GetFileExInfoStandard,
92                 &st))
93         {
94                 dpush(F);
95                 dpush(F);
96                 dpush(F);
97                 dpush(F);
98         }
99         else
100         {
101                 box_boolean(st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
102                 box_signed_4(0);
103                 box_unsigned_8(
104                         (s64)st.nFileSizeLow | (s64)st.nFileSizeHigh << 32);
105                 box_unsigned_8((int)
106                         ((*(s64*)&st.ftLastWriteTime - EPOCH_OFFSET) / 10000000));
107         }
108 }
109
110 void primitive_read_dir(void)
111 {
112         HANDLE dir;
113         WIN32_FIND_DATA find_data;
114         char path[MAX_PATH + 4];
115
116         sprintf(path, "%s\\*", unbox_char_string());
117
118         GROWABLE_ARRAY(result);
119
120         if(INVALID_HANDLE_VALUE != (dir = FindFirstFile(path, &find_data)))
121         {
122                 do
123                 {
124                         REGISTER_ARRAY(result);
125                         CELL name = tag_object(from_char_string(
126                                 find_data.cFileName));
127                         UNREGISTER_ARRAY(result);
128                         GROWABLE_ADD(result,name);
129                 }
130                 while (FindNextFile(dir, &find_data));
131                 CloseHandle(dir);
132         }
133
134         GROWABLE_TRIM(result);
135
136         dpush(tag_object(result));
137 }
138
139 void primitive_cwd(void)
140 {
141         char buf[MAX_PATH];
142
143         if(!GetCurrentDirectory(MAX_PATH, buf))
144                 io_error();
145
146         box_char_string(buf);
147 }
148
149 void primitive_cd(void)
150 {
151         SetCurrentDirectory(unbox_char_string());
152 }
153
154 F_SEGMENT *alloc_segment(CELL size)
155 {
156         SYSTEM_INFO si;
157         char *mem;
158         DWORD ignore;
159
160         GetSystemInfo(&si);
161         if((mem = (char *)VirtualAlloc(NULL, si.dwPageSize*2 + size, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
162                 fatal_error("VirtualAlloc() failed in alloc_segment()",0);
163
164         if (!VirtualProtect(mem, si.dwPageSize, PAGE_NOACCESS, &ignore))
165                 fatal_error("Cannot allocate low guard page", (CELL)mem);
166
167         if (!VirtualProtect(mem+size+si.dwPageSize, si.dwPageSize, PAGE_NOACCESS, &ignore))
168                 fatal_error("Cannot allocate high guard page", (CELL)mem);
169
170         F_SEGMENT *block = safe_malloc(sizeof(F_SEGMENT));
171
172         block->start = (int)mem + si.dwPageSize;
173         block->size = size;
174
175         return block;
176 }
177
178 void dealloc_segment(F_SEGMENT *block)
179 {
180         SYSTEM_INFO si;
181         GetSystemInfo(&si);
182         if(!VirtualFree((void*)(block->start - si.dwPageSize), 0, MEM_RELEASE))
183                 fatal_error("VirtualFree() failed",0);
184         free(block);
185 }
186
187 long getpagesize(void)
188 {
189         static long g_pagesize = 0;
190         if (! g_pagesize)
191         {
192                 SYSTEM_INFO system_info;
193                 GetSystemInfo (&system_info);
194                 g_pagesize = system_info.dwPageSize;
195         }
196         return g_pagesize;
197 }
198
199 const char *default_image_path(void)
200 {
201         return "factor.image";
202 }
203
204 /* SEH support. Proceed with caution. */
205 typedef long exception_handler_t(
206         PEXCEPTION_RECORD rec, void *frame, void *context, void *dispatch);
207
208 typedef struct exception_record
209 {
210         struct exception_record *next_handler;
211         void *handler_func;
212 } exception_record_t;
213
214 void seh_call(void (*func)(), exception_handler_t *handler)
215 {
216         exception_record_t record;
217         asm("mov %%fs:0, %0" : "=r" (record.next_handler));
218         asm("mov %0, %%fs:0" : : "r" (&record));
219         record.handler_func = handler;
220         func();
221         asm("mov %0, %%fs:0" : "=r" (record.next_handler));
222 }
223
224 static long exception_handler(PEXCEPTION_RECORD rec, void *frame, void *ctx, void *dispatch)
225 {
226         memory_protection_error(rec->ExceptionInformation[1],
227                 SIGSEGV,native_stack_pointer());
228         return -1; /* unreachable */
229 }
230
231 void run(void)
232 {
233         interpreter();
234 }
235
236 void run_toplevel(void)
237 {
238         seh_call(run, exception_handler);
239 }