3 // For platform information:
5 #include <sys/utsname.h>
7 typedef struct utsname
{
15 int uname(struct utsname
*un
) {
17 DWORD dwMajorVersion
= 0;
18 DWORD dwMinorVersion
= 0;
22 strcpy(un
->sysname
,"Win64");
24 strcpy(un
->sysname
,"Win32");
27 dwVersion
= GetVersion();
28 if (dwVersion
< 0x80000000) dwBuild
= (DWORD
)(HIWORD(dwVersion
)); else dwBuild
=0;
29 sprintf(un
->release
, "%d", dwBuild
);
30 sprintf(un
->version
, "%d %d", (DWORD
)(LOBYTE(LOWORD(dwVersion
))), (DWORD
)(HIBYTE(LOWORD(dwVersion
))));
33 strcpy(un
->machine
,"x64");
35 strcpy(un
->machine
,"x86");
38 if(gethostname(un
->nodename
, 256)!=0) strcpy(un
->nodename
, "localhost");
46 return GetProcessId();
50 //Template for defining Slate primitive signatures. Not a macro because IDEs don't process it:
51 //#define SLATE_PRIM(prim_name) void prim_name(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer)
53 #ifdef SLATE_DAEMONIZE
59 void prim_fixme(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
60 struct Object
* x
= args
[0];
61 printf("UNIMPLEMENTED PRIMITIVE\n");
62 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_TYPE_ERROR_ON
), x
, NULL
, resultStackPointer
);
67 void prim_isIdenticalTo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
68 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (args
[0]==args
[1])? oh
->cached
.true_object
: oh
->cached
.false_object
;
71 void prim_identity_hash(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
73 /* print_detail(oh, args[0]);
74 print_backtrace(oh);*/
75 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(object_hash(args
[0]));
78 void prim_identity_hash_univ(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
80 /* print_detail(oh, args[0]);
81 print_backtrace(oh);*/
82 if (object_is_smallint(args
[0])) {
83 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = args
[0];
85 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(object_hash(args
[0]));
89 /* Root forwardTo: anotherObject */
90 void prim_forward_to(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
91 struct Object
* x
= args
[0];
92 struct Object
* y
= args
[1];
93 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = y
;
94 /* since some objects like roleTables store pointers to things like Nil in byte arrays rather than oop arrays,
95 * we must make sure that these special objects do not move.
97 if (x
== get_special(oh
, SPECIAL_OOP_NIL
)
98 || x
== get_special(oh
, SPECIAL_OOP_TRUE
)
99 || x
== get_special(oh
, SPECIAL_OOP_FALSE
)) {
100 printf("Error... you cannot call forwardTo on this special object (did you add a slot to Nil/True/False?)\n");
101 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_TYPE_ERROR_ON
), x
, NULL
, resultStackPointer
); \
105 if (!object_is_smallint(x
) && !object_is_smallint(y
) && x
!= y
) {
106 heap_forward(oh
, x
, y
);
113 /* Root atSlotNamed: symbol */
114 void prim_at_slot_named(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
117 struct SlotEntry
* se
;
122 if (object_is_smallint(obj
)) {
123 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
125 se
= slot_table_entry_for_name(oh
, obj
->map
->slotTable
, (struct Symbol
*)name
);
127 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
129 word_t offset
= object_to_smallint(se
->offset
);
130 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_slot_value_at_offset(obj
, offset
);
135 /* Root atSlotNamed: symbol put: value */
136 void prim_at_slot_named_put(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
137 struct Object
* obj
=args
[0], *val
=args
[2];
138 struct Object
* name
= args
[1];
139 struct SlotEntry
* se
;
142 if (object_is_smallint(obj
)) {
143 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
147 if (object_is_immutable(obj
)) {
148 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_IMMUTABLE
), obj
, NULL
, resultStackPointer
);
153 se
= slot_table_entry_for_name(oh
, map
->slotTable
, (struct Symbol
*)name
);
156 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
158 word_t offset
= object_to_smallint(se
->offset
);
159 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_slot_value_at_offset_put(oh
, obj
, offset
, val
);
162 /*note: not supporting delegate slots*/
166 void prim_clone(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
167 if (object_is_smallint(args
[0])) {
168 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = args
[0];
170 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = heap_clone(oh
, args
[0]);
174 /* Cloneable cloneSettingSlots: slotNamesArray to: valuesArray */
175 void prim_clone_setting_slots(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
176 struct Object
*obj
= args
[0], *slotArray
= args
[1], *valueArray
= args
[2], *newObj
;
179 if (object_is_smallint(obj
)) {
180 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = obj
;
183 newObj
= heap_clone(oh
, obj
);
185 /*fix, check that arrays are same size, and signal errors*/
187 for (i
= 0; i
< object_array_size(slotArray
); i
++) {
188 struct Symbol
* name
= (struct Symbol
*)object_array_get_element(slotArray
, i
);
189 struct SlotEntry
* se
= slot_table_entry_for_name(oh
, obj
->map
->slotTable
, name
);
191 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, (struct Object
*)name
, NULL
, resultStackPointer
);
193 /*since the object was just cloned, we aren't expecting a tenured obj to point to a new one*/
194 object_slot_value_at_offset_put(oh
, newObj
, object_to_smallint(se
->offset
), object_array_get_element(valueArray
, i
));
198 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = newObj
;
201 void prim_clone_with_slot_valued(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
202 struct Object
* obj
= args
[0], *value
= args
[2];
203 struct Symbol
* name
= (struct Symbol
*)args
[1];
205 if (object_is_smallint(obj
)) {
206 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, (struct Object
*)name
, NULL
, resultStackPointer
);
208 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_add_slot_named(oh
, obj
, name
, value
);
212 void prim_clone_without_slot(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
213 struct Object
* obj
= args
[0];
214 struct Symbol
* name
= (struct Symbol
*)args
[1];
216 if (object_is_smallint(obj
)) {
217 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, (struct Object
*)name
, NULL
, resultStackPointer
);
219 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_remove_slot(oh
, obj
, name
);
225 void prim_map(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
229 if (object_is_smallint(obj
)) {
230 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
232 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)obj
->map
;
238 void prim_set_map(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
239 GC_VOLATILE
struct Object
* obj
;
240 GC_VOLATILE
struct Map
* map
;
242 map
= (struct Map
*)args
[1];
244 if (object_is_smallint(obj
) || object_is_immutable(obj
)) {
245 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
247 object_change_map(oh
, obj
, map
);
248 heap_store_into(oh
, args
[0], args
[1]);
249 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)map
;
256 void prim_applyto(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
257 struct Closure
*method
= (struct Closure
*)args
[0];
258 struct OopArray
* argArray
= (struct OopArray
*) args
[1];
259 struct OopArray
* real_opts
= NULL
;
261 if (opts
!= NULL
&& opts
->elements
[1] != oh
->cached
.nil
) {
262 real_opts
= (struct OopArray
*) opts
->elements
[1];
264 interpreter_apply_to_arity_with_optionals(oh
, oh
->cached
.interpreter
, method
,
265 argArray
->elements
, array_size(argArray
), real_opts
, resultStackPointer
);
268 void prim_findon(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
269 struct MethodDefinition
* def
;
270 struct Symbol
* selector
= (struct Symbol
*) args
[0];
271 struct OopArray
* arguments
= (struct OopArray
*) args
[1];
274 def
= method_dispatch_on(oh
, selector
, arguments
->elements
, array_size(arguments
), NULL
);
276 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (def
== NULL
? oh
->cached
.nil
: (struct Object
*) def
->method
);
279 void prim_ensure(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
281 struct Closure
* body
= (struct Closure
*) args
[0];
282 struct Object
* ensureHandler
= args
[1];
283 interpreter_apply_to_arity_with_optionals(oh
, oh
->cached
.interpreter
, body
, NULL
, 0, NULL
, resultStackPointer
);
284 /*the registers are already allocated on the stack so we don't worry about overwriting them*/
285 interpreter_stack_push(oh
, oh
->cached
.interpreter
, oh
->cached
.interpreter
->ensureHandlers
);
286 interpreter_stack_push(oh
, oh
->cached
.interpreter
, ensureHandler
);
287 oh
->cached
.interpreter
->ensureHandlers
= smallint_to_object(oh
->cached
.interpreter
->stackPointer
- 2);
288 #ifdef PRINT_DEBUG_ENSURE
289 printf("ensure handlers at %" PRIdPTR
"\n", oh
->cached
.interpreter
->stackPointer
- 2);
294 void prim_send_to(struct object_heap
* oh
, struct Object
* args
[], word_t n
, struct OopArray
* optionals
, word_t resultStackPointer
) {
295 struct Symbol
* selector
= (struct Symbol
*)args
[0];
296 struct OopArray
* opts
, *arguments
= (struct OopArray
*)args
[1];
298 if (optionals
== NULL
) {
301 opts
= (struct OopArray
*)optionals
->elements
[1];
302 if (opts
== (struct OopArray
*)oh
->cached
.nil
) opts
= NULL
;
304 send_to_through_arity_with_optionals(oh
, selector
, array_elements(arguments
), array_elements(arguments
), array_size(arguments
), opts
, resultStackPointer
);
307 void prim_send_to_through(struct object_heap
* oh
, struct Object
* args
[], word_t n
, struct OopArray
* optionals
, word_t resultStackPointer
) {
308 struct Symbol
* selector
= (struct Symbol
*)args
[0];
309 struct OopArray
* opts
, * arguments
= (struct OopArray
*)args
[1], *dispatchers
= (struct OopArray
*)args
[2];
311 if (optionals
== NULL
) {
314 opts
= (struct OopArray
*)optionals
->elements
[1];
315 if (opts
== (struct OopArray
*)oh
->cached
.nil
) opts
= NULL
;
317 /*fix check array sizes are the same*/
318 send_to_through_arity_with_optionals(oh
, selector
, array_elements(arguments
), array_elements(dispatchers
), array_size(arguments
), opts
, resultStackPointer
);
321 /* Method asMethod: selector on: rolesArray */
322 void prim_as_method_on(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
323 struct MethodDefinition
* def
;
324 GC_VOLATILE
struct Object
*method
= args
[0], *roles
=args
[2];
325 struct Symbol
*selector
= (struct Symbol
*)args
[1];
326 struct Object
* traitsWindow
= method
->map
->delegates
->elements
[0];
329 if (traitsWindow
== get_special(oh
, SPECIAL_OOP_CLOSURE_WINDOW
)) {
330 GC_VOLATILE
struct Closure
* closure
= (struct Closure
*)heap_clone(oh
, method
);
331 heap_fixed_add(oh
, (struct Object
*)closure
);
332 closure
->method
= (struct CompiledMethod
*)heap_clone(oh
, (struct Object
*)closure
->method
);
333 heap_fixed_remove(oh
, (struct Object
*)closure
);
334 heap_store_into(oh
, (struct Object
*)closure
, (struct Object
*)closure
->method
);
335 closure
->method
->method
= closure
->method
;
336 closure
->method
->selector
= selector
;
337 method
= (struct Object
*)closure
;
339 GC_VOLATILE
struct CompiledMethod
* closure
= (struct CompiledMethod
*)heap_clone(oh
, method
);
340 closure
->method
= closure
;
341 closure
->selector
= selector
;
342 method
= (struct Object
*) closure
;
344 def
= method_define(oh
, method
, (struct Symbol
*)selector
, ((struct OopArray
*)roles
)->elements
, object_array_size(roles
));
345 def
->slotAccessor
= oh
->cached
.nil
;
346 method_flush_cache(oh
, selector
);
347 #ifdef PRINT_DEBUG_DEFUN
349 printf("Defining function '"); print_symbol(selector
);
351 if (!print_printname(oh
, ((struct OopArray
*)roles
)->elements
[0])) printf("NoRole");
354 for (i
= 1; i
< object_array_size(roles
); i
++) {
356 if (!print_printname(oh
, ((struct OopArray
*)roles
)->elements
[i
])) printf("NoRole");
363 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = method
;
366 /* Method removeFrom: rolesArray */
367 void prim_removefrom(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
369 struct Object
*method
= args
[0], *traitsWindow
;
370 struct OopArray
* roles
= (struct OopArray
*)args
[1];
371 struct Symbol
* selector
= (struct Symbol
*)oh
->cached
.nil
;
372 struct MethodDefinition
* def
;
375 traitsWindow
= method
->map
->delegates
->elements
[0];
377 if (traitsWindow
== oh
->cached
.closure_method_window
|| traitsWindow
== oh
->cached
.compiled_method_window
) {
378 selector
= ((struct Closure
*)method
)->method
->selector
;
380 /*May only remove a CompiledMethod or Closure.*/
384 def
= method_is_on_arity(oh
, method
, selector
, array_elements(roles
), array_size(roles
));
386 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = method
;
390 for (i
= 0; i
< array_size(roles
); i
++) {
391 struct Object
* role
= array_elements(roles
)[i
];
392 if (!object_is_smallint(role
)) {
393 object_remove_role(oh
, role
, selector
, def
);
396 method_flush_cache(oh
, selector
);
397 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = method
;
400 void prim_as_accessor(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
401 GC_VOLATILE
struct Object
*method
= args
[0], *slot
= args
[2];
402 struct OopArray
*roles
= (struct OopArray
*)args
[3];
403 struct Symbol
* selector
= (struct Symbol
*)args
[1];
404 struct Object
* traitsWindow
= method
->map
->delegates
->elements
[0];
405 struct MethodDefinition
* def
;
407 if (traitsWindow
== oh
->cached
.closure_method_window
) {
408 GC_VOLATILE
struct Closure
* closure
= (struct Closure
*)heap_clone(oh
, method
);
409 heap_fixed_add(oh
, (struct Object
*)closure
);
410 closure
->method
= (struct CompiledMethod
*)heap_clone(oh
, (struct Object
*)closure
->method
);
411 heap_fixed_remove(oh
, (struct Object
*)closure
);
412 heap_store_into(oh
, (struct Object
*)closure
, (struct Object
*)closure
->method
);
413 closure
->method
->method
= closure
->method
;
414 closure
->method
->selector
= selector
;
415 method
= (struct Object
*)closure
;
416 } else if (traitsWindow
== oh
->cached
.compiled_method_window
){
417 GC_VOLATILE
struct CompiledMethod
* closure
= (struct CompiledMethod
*)heap_clone(oh
, method
);
418 closure
->method
= closure
;
419 closure
->selector
= selector
;
420 method
= (struct Object
*) closure
;
423 def
= method_define(oh
, method
, selector
, roles
->elements
, array_size(roles
));
424 def
->slotAccessor
= slot
;
425 method_flush_cache(oh
, selector
);
426 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = method
;
428 #ifdef PRINT_DEBUG_DEFUN
430 printf("Defining accessor '"); print_symbol(selector
);
432 if (!print_printname(oh
, ((struct OopArray
*)roles
)->elements
[0])) printf("NoRole");
435 for (i
= 1; i
< array_size(roles
); i
++) {
437 if (!print_printname(oh
, ((struct OopArray
*)roles
)->elements
[i
])) printf("NoRole");
447 void prim_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
448 struct Object
* array
;
452 i
= object_to_smallint(args
[1]);
453 ASSURE_SMALLINT_ARG(1);
454 if (i
< object_array_size(array
) && i
>= 0) {
455 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = ((struct OopArray
*)array
)->elements
[i
];
457 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[1], args
[0], NULL
, resultStackPointer
);
461 void prim_at_put(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
462 struct Object
*array
= args
[0], *i
= args
[1], *val
= args
[2];
463 word_t index
= object_to_smallint(i
);
465 ASSURE_SMALLINT_ARG(1);
466 if (object_is_immutable(array
)) {
467 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_IMMUTABLE
), array
, NULL
, resultStackPointer
);
471 if (index
< object_array_size(array
)) {
472 heap_store_into(oh
, array
, val
);
473 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = ((struct OopArray
*)array
)->elements
[index
] = val
;
475 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), i
, array
, NULL
, resultStackPointer
);
479 void prim_ooparray_newsize(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
480 /*struct Object* array = args[0];*/
481 struct Object
* i
= args
[1];
482 if (object_is_smallint(i
)) {
483 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)
484 heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
),
485 object_to_smallint(i
));
487 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
491 void prim_size(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
492 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(object_array_size(args
[0]));
495 #pragma mark ByteArray
497 void prim_bytearray_newsize(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
498 struct Object
* obj
, *i
;
502 if (!object_is_smallint(i
)) {
503 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
507 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
508 (struct Object
*)heap_clone_byte_array_sized(oh
, obj
, (object_to_smallint(i
) < 0) ? 0 : object_to_smallint(i
));
511 void prim_bytesize(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
512 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(payload_size(args
[0]));
515 void prim_byteat_put(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
516 struct Object
* obj
= args
[0], *i
=args
[1], *val
= args
[2];
519 index
= object_to_smallint(i
);
521 ASSURE_SMALLINT_ARG(1);
522 ASSURE_SMALLINT_ARG(2);
524 if (object_is_immutable(obj
)) {
525 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_IMMUTABLE
), obj
, NULL
, resultStackPointer
);
529 if (index
< byte_array_size((struct ByteArray
*)obj
)) {
530 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(byte_array_set_element((struct ByteArray
*)obj
, index
, object_to_smallint(val
)));
532 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), i
, obj
, NULL
, resultStackPointer
);
537 void prim_byteat(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
538 struct Object
* obj
, *i
;
543 index
= object_to_smallint(i
);
545 ASSURE_SMALLINT_ARG(1);
547 if (index
< byte_array_size((struct ByteArray
*)obj
)) {
548 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(byte_array_get_element(obj
, index
));
550 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), i
, obj
, NULL
, resultStackPointer
);
557 void prim_atEndOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
558 word_t handle
= object_to_smallint(args
[1]);
559 ASSURE_SMALLINT_ARG(1);
560 if (endOfFile(oh
, handle
)) {
561 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
563 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
567 void prim_sizeOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
568 word_t handle
= object_to_smallint(args
[1]);
569 word_t retval
= sizeOfFile(oh
, handle
);
570 ASSURE_SMALLINT_ARG(1);
571 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
574 void prim_flush_output(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
575 /*struct Object *console=args[0];*/
578 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
581 void prim_handle_for(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
583 struct Object
/**file=args[0],*/ *fname
=args
[1];
585 handle
= openFile(oh
, (struct ByteArray
*)fname
, SF_READ
|SF_WRITE
);
587 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(handle
);
589 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
594 void prim_handleForNew(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
596 struct Object
/**file=args[0],*/ *fname
=args
[1];
598 handle
= openFile(oh
, (struct ByteArray
*)fname
, SF_READ
|SF_WRITE
|SF_CLEAR
|SF_CREATE
);
600 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(handle
);
602 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
607 void prim_handle_for_input(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
609 struct Object
/**file=args[0],*/ *fname
=args
[1];
611 handle
= openFile(oh
, (struct ByteArray
*)fname
, SF_READ
);
613 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(handle
);
615 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
620 void prim_closePipe(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
621 word_t handle
= object_to_smallint(args
[0]);
624 ASSURE_SMALLINT_ARG(0);
626 retval
= closesocket(handle
);
628 retval
= close(handle
);
630 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(retval
);
634 void prim_readFromPipe(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
635 struct ByteArray
* array
= (struct ByteArray
*) args
[0];
636 word_t handle
= object_to_smallint(args
[1]);
637 word_t start
= object_to_smallint(args
[2]), end
= object_to_smallint(args
[3]);
640 ASSURE_TYPE_ARG(0, TYPE_BYTE_ARRAY
);
641 ASSURE_SMALLINT_ARG(1);
642 ASSURE_SMALLINT_ARG(2);
643 ASSURE_SMALLINT_ARG(3);
645 if (start
< 0 || start
>= byte_array_size(array
)) {
646 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[2], args
[0], NULL
, resultStackPointer
);
650 if (end
< start
|| end
> byte_array_size(array
)) {
651 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[3], args
[0], NULL
, resultStackPointer
);
655 retval
= recv(handle
, byte_array_elements(array
)+start
, end
- start
, 0);
658 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(retval
);
663 void prim_writeToPipe(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
664 struct ByteArray
* array
= (struct ByteArray
*) args
[0];
665 word_t handle
= object_to_smallint(args
[1]);
666 word_t start
= object_to_smallint(args
[2]), end
= object_to_smallint(args
[3]);
669 ASSURE_TYPE_ARG(0, TYPE_BYTE_ARRAY
);
670 ASSURE_SMALLINT_ARG(1);
671 ASSURE_SMALLINT_ARG(2);
672 ASSURE_SMALLINT_ARG(3);
674 if (start
< 0 || start
>= byte_array_size(array
)) {
675 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[2], args
[0], NULL
, resultStackPointer
);
679 if (end
< start
|| end
> byte_array_size(array
)) {
680 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[3], args
[0], NULL
, resultStackPointer
);
684 retval
= send(handle
, byte_array_elements(array
)+start
, end
- start
, 0);
686 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(retval
);
690 /*FIXME this is a copy of the last function with only the select call changed*/
691 void prim_selectOnWritePipesFor(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
693 GC_VOLATILE
struct OopArray
* selectOn
= (struct OopArray
*) args
[0];
694 GC_VOLATILE
struct OopArray
* readyPipes
;
695 word_t waitTime
= object_to_smallint(args
[1]);
696 int retval
, fdCount
, maxFD
;
701 ASSURE_SMALLINT_ARG(1);
703 if ((fdCount
= socket_select_setup(selectOn
, &fdList
, &maxFD
)) < 0) {
704 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
709 tv
.tv_sec
= waitTime
/ 1000000;
710 tv
.tv_usec
= waitTime
% 1000000;
711 retval
= select(maxFD
+1, NULL
, &fdList
, NULL
, &tv
);
714 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
719 readyPipes
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), retval
);
720 socket_select_find_available(selectOn
, &fdList
, readyPipes
, retval
);
722 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)readyPipes
;
728 void prim_socketCreate(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
729 word_t domain
= object_to_smallint(args
[0]);
730 word_t type
= object_to_smallint(args
[1]);
731 word_t protocol
= object_to_smallint(args
[2]);
732 word_t ret
= socket(socket_lookup_domain(domain
), socket_lookup_type(type
), socket_lookup_protocol(protocol
));
735 ASSURE_SMALLINT_ARG(0);
736 ASSURE_SMALLINT_ARG(1);
737 ASSURE_SMALLINT_ARG(2);
740 ret2
= socket_set_nonblocking(ret
);
742 perror("socket create");
746 perror("set nonblocking");
747 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(-1);
749 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
753 void prim_socketListen(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
754 word_t fd
= object_to_smallint(args
[0]);
755 word_t size
= object_to_smallint(args
[1]);
758 ASSURE_SMALLINT_ARG(0);
759 ASSURE_SMALLINT_ARG(1);
761 ret
= listen(fd
, size
);
763 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
767 void prim_socketAccept(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
768 word_t fd
= object_to_smallint(args
[0]);
770 struct sockaddr_storage addr
;
772 GC_VOLATILE
struct ByteArray
* addrArray
;
773 GC_VOLATILE
struct OopArray
* result
;
775 ASSURE_SMALLINT_ARG(0);
778 ret
= accept(fd
, (struct sockaddr
*)&addr
, &len
);
781 addrArray
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), sizeof(struct sockaddr_in
));
783 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
787 heap_fixed_add(oh
, (struct Object
*)addrArray
);
788 result
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), 2);
789 heap_fixed_remove(oh
, (struct Object
*)addrArray
);
791 object_array_set_element(oh
, (struct Object
*)result
, 0, smallint_to_object(ret
));
792 object_array_set_element(oh
, (struct Object
*)result
, 1, (struct Object
*)addrArray
);
794 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)result
;
798 void prim_socketBind(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
799 word_t fd
= object_to_smallint(args
[0]);
800 struct ByteArray
* address
= (struct ByteArray
*) args
[1];
803 ASSURE_SMALLINT_ARG(0);
805 ret
= bind(fd
, (const struct sockaddr
*)byte_array_elements(address
), (socklen_t
)byte_array_size(address
));
806 if (ret
< 0) perror("bind");
807 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
810 void prim_socketConnect(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
811 word_t fd
= object_to_smallint(args
[0]);
812 struct ByteArray
* address
= (struct ByteArray
*) args
[1];
815 ASSURE_SMALLINT_ARG(0);
817 ret
= connect(fd
, (const struct sockaddr
*)byte_array_elements(address
), (socklen_t
)byte_array_size(address
));
819 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
823 void prim_socketGetError(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
824 word_t fd
= object_to_smallint(args
[0]);
829 ASSURE_SMALLINT_ARG(0);
831 ret
= getsockopt(fd
, SOL_SOCKET
, SO_ERROR
, &optval
, (socklen_t
*)&optlen
);
834 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(optval
);
836 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
841 void prim_getAddrInfo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
842 struct ByteArray
* hostname
= (struct ByteArray
*)args
[1];
843 struct ByteArray
* service
= (struct ByteArray
*)args
[2];
844 word_t family
= object_to_smallint(args
[3]);
845 word_t type
= object_to_smallint(args
[4]);
846 word_t protocol
= object_to_smallint(args
[5]);
847 word_t flags
= object_to_smallint(args
[6]);
848 word_t ret
, serviceSize
, hostnameSize
;
850 ASSURE_TYPE_ARG(1, TYPE_BYTE_ARRAY
);
851 ASSURE_SMALLINT_ARG(3);
852 ASSURE_SMALLINT_ARG(4);
853 ASSURE_SMALLINT_ARG(5);
854 ASSURE_SMALLINT_ARG(6);
856 if ((struct Object
*)hostname
== oh
->cached
.nil
) {
859 hostnameSize
= byte_array_size(hostname
)+1;
862 if ((struct Object
*)service
== oh
->cached
.nil
) {
865 ASSURE_TYPE_ARG(2, TYPE_BYTE_ARRAY
);
866 serviceSize
= byte_array_size(service
)+1;
869 ret
= socket_getaddrinfo(oh
, hostname
, hostnameSize
, service
, serviceSize
, family
, type
, protocol
, flags
);
871 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
875 void prim_getAddrInfoResult(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
876 word_t ticket
= object_to_smallint(args
[0]);
877 if (ticket
>= oh
->socketTicketCount
|| ticket
< 0
878 || oh
->socketTickets
[ticket
].inUse
== 0 || oh
->socketTickets
[ticket
].finished
== 0) {
879 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
882 if (oh
->socketTickets
[ticket
].result
< 0) {
883 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(socket_return(oh
->socketTickets
[ticket
].result
));
886 struct addrinfo
* ai
= oh
->socketTickets
[ticket
].addrResult
;
887 struct addrinfo
* current
= ai
;
888 GC_VOLATILE
struct OopArray
* retval
;
890 while (current
!= NULL
) {
891 current
= current
->ai_next
;
895 retval
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), count
);
896 heap_fixed_add(oh
, (struct Object
*)retval
);
897 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)retval
;
898 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)retval
);
900 for (i
= 0; i
< count
; i
++) {
901 GC_VOLATILE
struct OopArray
* aResult
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), 6);
902 struct ByteArray
* aResultAddr
;
903 struct ByteArray
* aResultCanonName
;
904 word_t canonNameLen
= (current
->ai_canonname
== NULL
)? 0 : strlen(current
->ai_canonname
);
905 retval
->elements
[i
] = (struct Object
*)aResult
;
906 heap_store_into(oh
, (struct Object
*)retval
, retval
->elements
[i
]);
907 aResult
->elements
[0] = smallint_to_object(current
->ai_flags
);
908 aResult
->elements
[1] = smallint_to_object(socket_reverse_lookup_domain(current
->ai_family
));
909 aResult
->elements
[2] = smallint_to_object(socket_reverse_lookup_type(current
->ai_socktype
));
910 aResult
->elements
[3] = smallint_to_object(socket_reverse_lookup_protocol(current
->ai_protocol
));
912 aResultAddr
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), current
->ai_addrlen
);
913 aResult
->elements
[4] = (struct Object
*)aResultAddr
;
914 heap_store_into(oh
, (struct Object
*)aResult
, aResult
->elements
[4]);
915 copy_bytes_into((byte_t
*)current
->ai_addr
, current
->ai_addrlen
, aResultAddr
->elements
);
916 if (canonNameLen
== 0) {
917 aResult
->elements
[5] = oh
->cached
.nil
;
919 aResultCanonName
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), canonNameLen
);
920 aResult
->elements
[5] = (struct Object
*)aResultCanonName
;
921 heap_store_into(oh
, (struct Object
*)aResult
, aResult
->elements
[5]);
922 copy_bytes_into((byte_t
*)current
->ai_canonname
, canonNameLen
, aResultCanonName
->elements
);
925 current
= current
->ai_next
;
928 heap_fixed_remove(oh
, (struct Object
*)retval
);
934 void prim_freeAddrInfoResult(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
935 word_t ticket
= object_to_smallint(args
[0]);
936 if (ticket
>= oh
->socketTicketCount
|| ticket
< 0
937 || oh
->socketTickets
[ticket
].inUse
== 0 || oh
->socketTickets
[ticket
].finished
== 0) {
938 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
941 free(oh
->socketTickets
[ticket
].hostname
);
942 oh
->socketTickets
[ticket
].hostname
= 0;
943 free(oh
->socketTickets
[ticket
].service
);
944 oh
->socketTickets
[ticket
].service
= 0;
945 freeaddrinfo(oh
->socketTickets
[ticket
].addrResult
);
946 oh
->socketTickets
[ticket
].addrResult
= 0;
948 oh
->socketTickets
[ticket
].inUse
= 0;
949 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
953 void prim_socketCreateIP(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
954 word_t domain
= object_to_smallint(args
[0]);
955 struct Object
* address
= args
[1];
956 word_t port
= object_to_smallint(args
[2]);
957 /* struct OopArray* options = (struct OopArray*) args[3];*/
958 struct sockaddr_in
* sin
;
959 struct sockaddr_in6
* sin6
;
960 struct sockaddr_un
* sun
;
961 GC_VOLATILE
struct ByteArray
* ret
;
963 ASSURE_SMALLINT_ARG(0);
967 case SLATE_DOMAIN_LOCAL
:
970 if (byte_array_size((struct ByteArray
*)address
) > 100) {
971 ret
= (struct ByteArray
*)oh
->cached
.nil
;
974 ret
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), sizeof(struct sockaddr_un
));
975 sun
= (struct sockaddr_un
*)byte_array_elements(ret
);
976 sun
->sun_family
= socket_lookup_domain(domain
);
977 ASSURE_TYPE_ARG(1, TYPE_BYTE_ARRAY
);
978 strncpy(sun
->sun_path
, (char*)byte_array_elements((struct ByteArray
*)address
), 100);
979 sun
->sun_path
[byte_array_size((struct ByteArray
*)address
)] = '\0';
983 case SLATE_DOMAIN_IPV4
:
984 ASSURE_SMALLINT_ARG(2);
985 if (object_array_size(address
) < 4) {
986 ret
= (struct ByteArray
*)oh
->cached
.nil
;
989 ret
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), sizeof(struct sockaddr_in
));
990 sin
= (struct sockaddr_in
*)byte_array_elements(ret
);
991 sin
->sin_family
= socket_lookup_domain(domain
);
992 sin
->sin_port
= htons((uint16_t)port
);
993 ASSURE_TYPE_ARG(1, TYPE_OOP_ARRAY
);
994 sin
->sin_addr
.s_addr
= htonl(((object_to_smallint(object_array_get_element(address
, 0)) & 0xFF) << 24)
995 | ((object_to_smallint(object_array_get_element(address
, 1)) & 0xFF) << 16)
996 | ((object_to_smallint(object_array_get_element(address
, 2)) & 0xFF) << 8)
997 | (object_to_smallint(object_array_get_element(address
, 3)) & 0xFF));
1001 case SLATE_DOMAIN_IPV6
:
1002 ASSURE_SMALLINT_ARG(2);
1003 if (object_array_size(address
) < 16) {
1004 ret
= (struct ByteArray
*)oh
->cached
.nil
;
1007 ret
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), sizeof(struct sockaddr_in6
));
1008 sin6
= (struct sockaddr_in6
*)byte_array_elements(ret
);
1009 sin6
->sin6_family
= socket_lookup_domain(domain
);
1010 sin6
->sin6_port
= htons((uint16_t)port
);
1011 ASSURE_TYPE_ARG(1, TYPE_OOP_ARRAY
);
1014 for (i
= 0; i
< 16; i
++)
1015 sin6
->sin6_addr
.s6_addr
[i
] = object_to_smallint(object_array_get_element(address
, i
)) & 0xFF;
1020 ret
= (struct ByteArray
*)oh
->cached
.nil
;
1024 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)ret
;
1028 void prim_write_to_starting_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1029 struct Object
*console
=args
[0], *n
=args
[1], *handle
=args
[2], *seq
=args
[3], *start
=args
[4];
1030 byte_t
* bytes
= &((struct ByteArray
*)seq
)->elements
[0] + object_to_smallint(start
);
1031 word_t size
= object_to_smallint(n
);
1034 ASSURE_SMALLINT_ARG(2);
1035 ASSURE_SMALLINT_ARG(4);
1037 assert(arity
== 5 && console
!= NULL
);
1039 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1040 smallint_to_object(fwrite(bytes
, 1, size
, (object_to_smallint(handle
) == 0)? stdout
: stderr
));
1044 void prim_close(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1045 word_t handle
= object_to_smallint(args
[1]);
1046 ASSURE_SMALLINT_ARG(1);
1048 closeFile(oh
, handle
);
1049 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1053 void prim_readConsole_from_into_starting_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1054 word_t
/*handle = object_to_smallint(args[2]),*/ n
= object_to_smallint(args
[1]), start
= object_to_smallint(args
[4]);
1055 struct ByteArray
* bytes
= (struct ByteArray
*)args
[3];
1058 ASSURE_SMALLINT_ARG(1);
1059 ASSURE_SMALLINT_ARG(4);
1061 retval
= fread((char*)(byte_array_elements(bytes
) + start
), 1, n
, stdin
);
1062 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
1066 void prim_read_from_into_starting_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1067 word_t handle
= object_to_smallint(args
[2]), n
= object_to_smallint(args
[1]), start
= object_to_smallint(args
[4]);
1068 struct ByteArray
* bytes
= (struct ByteArray
*)args
[3];
1070 ASSURE_SMALLINT_ARG(1);
1071 ASSURE_SMALLINT_ARG(4);
1072 retval
= readFile(oh
, handle
, n
, (char*)(byte_array_elements(bytes
) + start
));
1073 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
1076 void prim_write_to_from_starting_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1077 word_t handle
= object_to_smallint(args
[2]), n
= object_to_smallint(args
[1]), start
= object_to_smallint(args
[4]);
1078 struct ByteArray
* bytes
= (struct ByteArray
*)args
[3];
1080 ASSURE_SMALLINT_ARG(1);
1081 ASSURE_SMALLINT_ARG(4);
1082 retval
= writeFile(oh
, handle
, n
, (char*)(byte_array_elements(bytes
) + start
));
1083 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
1086 void prim_reposition_to(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1087 word_t handle
= object_to_smallint(args
[1]), n
= object_to_smallint(args
[2]);
1088 word_t retval
= seekFile(oh
, handle
, n
);
1089 ASSURE_SMALLINT_ARG(1);
1090 ASSURE_SMALLINT_ARG(2);
1091 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
1094 void prim_positionOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1095 word_t handle
= object_to_smallint(args
[1]);
1096 word_t retval
= tellFile(oh
, handle
);
1097 ASSURE_SMALLINT_ARG(1);
1098 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
1101 #pragma mark Directory
1103 void prim_getcwd(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1104 struct ByteArray
* buf
= (struct ByteArray
*)args
[1];
1105 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(getCurrentDirectory(buf
));
1107 void prim_setcwd(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1108 struct ByteArray
* buf
= (struct ByteArray
*)args
[1];
1109 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(setCurrentDirectory(buf
));
1112 #pragma mark Platform
1114 void prim_bytesPerWord(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1115 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(sizeof(word_t
));
1118 int slate_refresh_systeminfo() {
1119 return !(&info
&& uname(&info
));
1122 void prim_system_name(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1123 GC_VOLATILE
struct ByteArray
*result
;
1125 if (slate_refresh_systeminfo()) {
1126 resultLength
= strlen(info
.nodename
);
1127 result
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), strlen(info
.nodename
));
1128 copy_bytes_into((byte_t
*)info
.nodename
, resultLength
, result
->elements
);
1130 result
= (struct ByteArray
*)oh
->cached
.nil
;
1132 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)result
;
1133 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)result
);
1136 void prim_system_release(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1137 GC_VOLATILE
struct ByteArray
*result
;
1139 if (slate_refresh_systeminfo()) {
1140 resultLength
= strlen(info
.release
);
1141 result
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), strlen(info
.release
));
1142 copy_bytes_into((byte_t
*)info
.release
, resultLength
, result
->elements
);
1144 result
= (struct ByteArray
*)oh
->cached
.nil
;
1146 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)result
;
1147 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)result
);
1150 void prim_system_version(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1151 GC_VOLATILE
struct ByteArray
*result
;
1153 if (slate_refresh_systeminfo()) {
1154 resultLength
= strlen(info
.version
);
1155 result
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), strlen(info
.version
));
1156 copy_bytes_into((byte_t
*)info
.version
, resultLength
, result
->elements
);
1158 result
= (struct ByteArray
*)oh
->cached
.nil
;
1160 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)result
;
1161 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)result
);
1164 void prim_system_platform(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1165 GC_VOLATILE
struct ByteArray
*result
;
1167 if (slate_refresh_systeminfo()) {
1168 resultLength
= strlen(info
.sysname
);
1169 result
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), strlen(info
.sysname
));
1170 copy_bytes_into((byte_t
*)info
.sysname
, resultLength
, result
->elements
);
1172 result
= (struct ByteArray
*)oh
->cached
.nil
;
1174 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)result
;
1175 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)result
);
1178 void prim_system_machine(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1179 GC_VOLATILE
struct ByteArray
*result
;
1181 if (slate_refresh_systeminfo()) {
1182 resultLength
= strlen(info
.machine
);
1183 result
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), strlen(info
.machine
));
1184 copy_bytes_into((byte_t
*)info
.machine
, resultLength
, result
->elements
);
1186 result
= (struct ByteArray
*)oh
->cached
.nil
;
1188 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)result
;
1189 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)result
);
1192 void prim_environment_removekey(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1193 struct Object
*keyString
= args
[1];
1194 size_t keyLength
= payload_size(keyString
);
1195 char key
[SLATE_FILE_NAME_LENGTH
];
1196 memcpy(key
, (char*)byte_array_elements((struct ByteArray
*)keyString
), keyLength
);
1197 key
[keyLength
] = '\0';
1199 SetEnvironmentVariable(key
, "");
1203 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1206 void prim_environment_atput(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1207 struct Object
*keyString
= args
[1];
1208 struct Object
*valueString
= args
[2];
1209 size_t keyLength
= payload_size(keyString
);
1210 size_t valueLength
= payload_size(valueString
);
1211 char key
[SLATE_FILE_NAME_LENGTH
], value
[SLATE_FILE_NAME_LENGTH
];
1213 memcpy(key
, (char*)byte_array_elements((struct ByteArray
*)keyString
), keyLength
);
1214 key
[keyLength
] = '\0';
1215 memcpy(value
, (char*)byte_array_elements((struct ByteArray
*)valueString
), valueLength
);
1216 value
[valueLength
] = '\0';
1218 success
= SetEnvironmentVariable(key
, value
);
1220 success
= setenv(key
, value
, 1);
1222 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (success
? oh
->cached
.false_object
: oh
->cached
.true_object
);
1225 void prim_isLittleEndian(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1227 char little_endian
= *(char*)&x
;
1228 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = ((little_endian
== 1) ? oh
->cached
.true_object
: oh
->cached
.false_object
);
1231 void prim_system_execute(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1232 struct Object
*commandString
= args
[1];
1233 size_t commandLength
= payload_size(commandString
);
1234 char command
[SLATE_FILE_NAME_LENGTH
];
1235 memcpy(command
, (char*)byte_array_elements((struct ByteArray
*)commandString
), commandLength
);
1236 command
[commandLength
] = '\0';
1237 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (system(command
) ? oh
->cached
.false_object
: oh
->cached
.true_object
);
1242 #ifdef WIN32 // gettimeofday() ported to WIN32 for prim_timeSinceEpoch()
1244 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
1245 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
1247 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
1252 int tz_minuteswest
; /* minutes W of Greenwich */
1253 int tz_dsttime
; /* type of dst correction */
1256 int gettimeofday(struct timeval
*tv
, struct timezone
*tz
)
1259 unsigned __int64 tmpres
= 0;
1260 static int tzflag
= 0;
1264 GetSystemTimeAsFileTime(&ft
);
1266 tmpres
|= ft
.dwHighDateTime
;
1268 tmpres
|= ft
.dwLowDateTime
;
1270 tmpres
/= 10; /*convert into microseconds*/
1271 /*converting file time to unix epoch*/
1272 tmpres
-= DELTA_EPOCH_IN_MICROSECS
;
1273 tv
->tv_sec
= (long)(tmpres
/ 1000000UL);
1274 tv
->tv_usec
= (long)(tmpres
% 1000000UL);
1284 tz
->tz_minuteswest
= _timezone
/ 60;
1285 tz
->tz_dsttime
= _daylight
;
1293 void prim_timeSinceEpoch(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1297 GC_VOLATILE
struct ByteArray
* timeArray
;
1298 const int arraySize
= 8;
1300 timeArray
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), arraySize
);
1302 gettimeofday(&tv
, NULL
);
1303 time
= (int64_t)tv
.tv_sec
* 1000000 + (int64_t)tv
.tv_usec
;
1305 for (i
= 0; i
< arraySize
; i
++) {
1306 timeArray
->elements
[i
] = ((time
>> (i
* 8)) & 0xFF);
1309 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)timeArray
;
1310 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)timeArray
);
1313 void prim_addressOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1314 struct Object
*handle
=args
[1], *offset
=args
[2];
1315 struct ByteArray
* addressBuffer
=(struct ByteArray
*) args
[3];
1316 ASSURE_SMALLINT_ARG(1);
1317 ASSURE_SMALLINT_ARG(2);
1318 if (object_is_smallint(handle
) && object_is_smallint(offset
) && byte_array_size(addressBuffer
) >= sizeof(word_t
)) {
1319 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1320 smallint_to_object(addressOfMemory(oh
,
1321 (int)object_to_smallint(handle
),
1322 (int)object_to_smallint(offset
),
1323 byte_array_elements(addressBuffer
)));
1325 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1330 #pragma mark ExternalLibrary
1332 void prim_library_open(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1333 struct Object
*libname
=args
[1], *handle
= args
[2];
1335 if (openExternalLibrary(oh
, (struct ByteArray
*)libname
, (struct ByteArray
*)handle
)) {
1336 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1338 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
1343 void prim_library_close(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1344 struct Object
*handle
=args
[1];
1346 if (closeExternalLibrary(oh
, (struct ByteArray
*) handle
)) {
1347 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1349 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
1354 void prim_procAddressOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1355 struct Object
*handle
=args
[2], *symname
=args
[1];
1356 struct ByteArray
* addressBuffer
=(struct ByteArray
*) args
[3];
1358 if (lookupExternalLibraryPrimitive(oh
, (struct ByteArray
*) handle
, (struct ByteArray
*) symname
, addressBuffer
)) {
1359 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1361 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
1366 void prim_extlibError(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1367 struct ByteArray
* messageBuffer
=(struct ByteArray
*) args
[1];
1369 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(readExternalLibraryError(messageBuffer
));
1372 void prim_applyExternal(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1374 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1375 applyExternalLibraryPrimitive(oh
, (struct ByteArray
*)args
[1],
1376 (struct OopArray
*)args
[2],
1379 (struct OopArray
*)args
[5]);
1383 #pragma mark MemoryArea
1385 void prim_memory_new(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1386 struct Object
*size
=args
[1];
1389 if (!object_is_smallint(size
)) {
1390 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1394 handle
= (word_t
)openMemory(oh
, object_to_smallint(size
));
1396 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(handle
);
1398 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1403 void prim_memory_close(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1405 struct Object
* handle
= args
[1];
1406 if (object_is_smallint(handle
)) {
1407 closeMemory(oh
, object_to_smallint(handle
));
1409 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1413 void prim_memory_size(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1415 struct Object
* handle
= args
[1];
1416 if (object_is_smallint(handle
)) {
1417 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(sizeOfMemory(oh
, object_to_smallint(handle
)));
1419 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1424 void prim_memory_addRef(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1426 struct Object
* handle
= args
[1];
1427 if (object_is_smallint(handle
)) {
1428 addRefMemory(oh
, object_to_smallint(handle
));
1431 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1435 void prim_memory_read(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1437 struct ByteArray
* buf
= (struct ByteArray
*)args
[0];
1438 word_t amount
= object_to_smallint(args
[1]), startingAt
= object_to_smallint(args
[3]),
1439 handle
= object_to_smallint(args
[2]);
1441 ASSURE_SMALLINT_ARG(1);
1442 ASSURE_SMALLINT_ARG(2);
1443 ASSURE_SMALLINT_ARG(3);
1445 if (!validMemoryHandle(oh
, handle
)
1446 || byte_array_size(buf
) < amount
1447 || startingAt
+ amount
>= oh
->memory_sizes
[handle
]) {
1448 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(-1);
1452 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1453 smallint_to_object(writeMemory(oh
, handle
, startingAt
, amount
, byte_array_elements(buf
)));
1457 void prim_memory_write(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1459 struct ByteArray
* buf
= (struct ByteArray
*)args
[0];
1460 word_t amount
= object_to_smallint(args
[1]), startingAt
= object_to_smallint(args
[3]),
1461 handle
= object_to_smallint(args
[2]);
1463 ASSURE_SMALLINT_ARG(1);
1464 ASSURE_SMALLINT_ARG(2);
1465 ASSURE_SMALLINT_ARG(3);
1467 if (!validMemoryHandle(oh
, handle
)
1468 || byte_array_size(buf
) < amount
1469 || startingAt
+ amount
>= oh
->memory_sizes
[handle
]) {
1470 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(-1);
1474 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1475 smallint_to_object(readMemory(oh
, handle
, startingAt
, amount
, byte_array_elements(buf
)));
1479 void prim_memory_resizeTo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1481 struct Object
* handle
= args
[1], *size
= args
[2];
1482 if (object_is_smallint(handle
) && object_is_smallint(size
)) {
1483 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1484 smallint_to_object(resizeMemory(oh
, object_to_smallint(handle
), object_to_smallint(size
)));
1487 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1492 void prim_smallint_at_slot_named(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1494 struct Object
* name
;
1495 struct SlotEntry
* se
;
1496 struct Object
* proto
;
1500 proto
= get_special(oh
, SPECIAL_OOP_SMALL_INT_PROTO
);
1501 se
= slot_table_entry_for_name(oh
, proto
->map
->slotTable
, (struct Symbol
*)name
);
1503 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
1505 word_t offset
= object_to_smallint(se
->offset
);
1506 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_slot_value_at_offset(proto
, offset
);
1512 void prim_frame_pointer_of(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1514 struct Interpreter
* i
= (struct Interpreter
*)args
[0];
1515 struct Symbol
* selector
= (struct Symbol
*) args
[1];
1516 struct CompiledMethod
* method
;
1517 word_t frame
= i
->framePointer
;
1521 while (frame
> FUNCTION_FRAME_SIZE
) {
1522 method
= (struct CompiledMethod
*) i
->stack
->elements
[frame
-3];
1523 method
= method
->method
; /*incase it's a closure and not a compiledmethod*/
1524 if (method
->selector
== selector
) {
1525 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(frame
);
1528 frame
= object_to_smallint(i
->stack
->elements
[frame
-1]);
1531 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1535 #pragma mark Clone/Daemonize System
1537 void prim_cloneSystem(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1539 #pragma message("TODO WIN32 port forking/cloning the system")
1544 GC_VOLATILE
struct OopArray
* array
;
1546 /* make two pipes that we can use exclusively in each process to talk to the other */
1547 /*FIXME remap fds for safety*/
1548 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, pipes
) == -1) {
1549 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1555 if (retval
== (pid_t
)-1) {
1556 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1560 array
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), 2);
1561 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)array
;
1563 if (!retval
) { /* child */
1564 array
->elements
[0] = oh
->cached
.false_object
;
1565 array
->elements
[1] = smallint_to_object(pipes
[0]);
1566 } else { /* parent */
1567 array
->elements
[0] = oh
->cached
.true_object
;
1568 array
->elements
[1] = smallint_to_object(pipes
[1]);
1575 void prim_cloneSystemInProcess(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
1577 #pragma message("TODO WIN32 port cloning/threading a system")
1584 #ifdef SLATE_DAEMONIZE
1586 /* Change this to whatever your daemon is called */
1587 #define DAEMON_NAME "slatedaemon"
1589 /* Change this to the user under which to run */
1590 #define RUN_AS_USER "root"
1592 static void child_handler(int signum
) {
1594 case SIGALRM
: exit(EXIT_FAILURE
); break;
1595 case SIGUSR1
: exit(EXIT_SUCCESS
); break;
1596 case SIGCHLD
: exit(EXIT_FAILURE
); break;
1600 void prim_daemonizeSystem(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1601 const char* lock_filename
= (char*)byte_array_elements((struct ByteArray
*) args
[1]);
1603 #pragma message("TODO WIN32 port daemonizing a system")
1605 pid_t pid
, sid
, parent
;
1608 /* already a daemon */
1609 if (getppid() == 1) return;
1611 /* Create the lock file as the current user */
1612 if (lock_filename
&& lock_filename
[0]) {
1613 lfp
= open(lock_filename
,O_RDWR
|O_CREAT
,0640);
1615 printf("Unable to create lock file %s, code=%d (%s)",
1616 lock_filename
, errno
, strerror(errno
));
1621 /* Drop user if there is one, and we were run as root */
1622 if (getuid() == 0 || geteuid() == 0) {
1623 struct passwd
*pw
= getpwnam(RUN_AS_USER
);
1626 printf("Setting user to " RUN_AS_USER
);
1631 /* Trap signals that we expect to receive */
1632 signal(SIGCHLD
,child_handler
);
1633 signal(SIGUSR1
,child_handler
);
1634 signal(SIGALRM
,child_handler
);
1636 /* Fork off the parent process */
1639 printf("Unable to fork daemon, code=%d (%s)",
1640 errno
, strerror(errno
));
1643 /* If we got a good PID, then we can exit the parent process. */
1646 /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
1647 for two seconds to elapse (SIGALRM). pause() should not return. */
1654 /* At this point we are executing as the child process */
1657 /* Cancel certain signals */
1658 signal(SIGCHLD
,SIG_DFL
); /* A child process dies */
1659 signal(SIGTSTP
,SIG_IGN
); /* Various TTY signals */
1660 signal(SIGTTOU
,SIG_IGN
);
1661 signal(SIGTTIN
,SIG_IGN
);
1662 signal(SIGHUP
, SIG_IGN
); /* Ignore hangup signal */
1663 signal(SIGTERM
,SIG_DFL
); /* Die on SIGTERM */
1665 /* Change the file mode mask */
1668 /* Create a new SID for the child process */
1671 printf("Unable to create a new session, code %d (%s)",
1672 errno
, strerror(errno
));
1676 /* Change the current working directory. This prevents the current
1677 directory from being locked; hence not being able to remove it. */
1678 if ((chdir("/")) < 0) {
1679 printf("Unable to change directory to %s, code %d (%s)",
1680 "/", errno
, strerror(errno
));
1684 /* Redirect standard files to /dev/null */
1685 freopen("/dev/null", "r", stdin
);
1686 freopen("/dev/null", "w", stdout
);
1687 freopen("/dev/null", "w", stderr
);
1689 /* Tell the parent process that we are A-okay */
1690 kill(parent
, SIGUSR1
);
1692 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1695 #endif //SLATE_DAEMONIZE
1697 #pragma mark VM invocation arguments
1700 void prim_run_args_into(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1701 struct ByteArray
* arguments
= (struct ByteArray
*)args
[1];
1702 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1703 smallint_to_object(write_args_into(oh
, (char*)byte_array_elements(arguments
), byte_array_size(arguments
)));
1708 void prim_vmArgCount(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1709 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(oh
->argcSaved
);
1712 void prim_vmArg(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1715 GC_VOLATILE
struct ByteArray
* array
;
1716 ASSURE_SMALLINT_ARG(1);
1717 i
= object_to_smallint(args
[1]);
1718 len
= strlen(oh
->argvSaved
[i
]);
1720 array
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), len
);
1721 copy_bytes_into((byte_t
*)oh
->argvSaved
[i
], len
, array
->elements
);
1722 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)array
;
1723 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)array
);
1726 void prim_environmentVariables(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1729 GC_VOLATILE
struct OopArray
* array
;
1732 while (oh
->envp
[len
]) len
++;
1734 array
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), len
);
1735 heap_fixed_add(oh
, (struct Object
*)array
);
1737 for (i
= 0; i
< len
; i
++) {
1738 lenstr
= strlen(oh
->envp
[i
]);
1739 array
->elements
[i
] = (struct Object
*) heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), lenstr
);
1740 copy_bytes_into((byte_t
*)oh
->envp
[i
], lenstr
, ((struct ByteArray
*)array
->elements
[i
])->elements
);
1744 heap_fixed_remove(oh
, (struct Object
*)array
);
1746 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)array
;
1747 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)array
);
1750 void prim_heap_gc(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1752 printf("Collecting garbage...\n");
1757 void prim_save_image(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1758 char nameString
[SLATE_FILE_NAME_LENGTH
];
1759 struct slate_image_header sih
;
1760 struct Object
* name
= args
[1];
1761 size_t nameLength
= payload_size(name
);
1764 word_t totalSize
, forwardPointerEntryCount
;
1765 byte_t
* memoryStart
;
1766 struct Object
*writeObject
;
1767 struct ForwardPointerEntry
* forwardPointers
;
1768 /* do a full gc, allocate a new chunk of memory the size of the young and old combined,
1769 * copy all the non-free objects to the new memory while keeping an array of the position changes,
1770 * go through the memory and fix up the pointers, adjust points to start from 0 instead of memoryStart,
1771 * and write the header and the memory out to disk
1774 /*push true so if it resumes from the save image, it will do init code*/
1776 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1778 if (nameLength
>= sizeof(nameString
)) {
1779 /*interpreter_stack_pop(oh, oh->cached.interpreter);*/
1781 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1784 memcpy(nameString
, (char*)byte_array_elements((struct ByteArray
*)name
), nameLength
);
1785 nameString
[nameLength
] = '\0';
1787 imageFile
= fopen(nameString
, "wb");
1789 /*interpreter_stack_pop(oh, oh->cached.interpreter);*/
1791 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1795 printf("Saving image to %s\n", nameString
);
1797 totalSize
= oh
->memoryOldSize
+ oh
->memoryYoungSize
;
1798 forwardPointerEntryCount
= ((totalSize
/ 4) + sizeof(struct ForwardPointerEntry
) - 1) / sizeof(struct ForwardPointerEntry
);
1799 memoryStart
= calloc(1, totalSize
);
1800 writeObject
= (struct Object
*)memoryStart
;
1801 forwardPointers
= calloc(1, forwardPointerEntryCount
* sizeof(struct ForwardPointerEntry
));
1802 assert(memoryStart
!= NULL
);
1803 copy_used_objects(oh
, &writeObject
, oh
->memoryOld
, oh
->memoryOldSize
, forwardPointers
, forwardPointerEntryCount
);
1804 copy_used_objects(oh
, &writeObject
, oh
->memoryYoung
, oh
->memoryYoungSize
, forwardPointers
, forwardPointerEntryCount
);
1805 totalSize
= (byte_t
*)writeObject
- memoryStart
;
1806 adjust_object_fields_with_table(oh
, memoryStart
, totalSize
, forwardPointers
, forwardPointerEntryCount
);
1807 adjust_oop_pointers_from(oh
, 0-(word_t
)memoryStart
, memoryStart
, totalSize
);
1808 sih
.magic
= SLATE_IMAGE_MAGIC
;
1809 sih
.size
= totalSize
;
1810 sih
.next_hash
= heap_new_hash(oh
);
1811 sih
.special_objects_oop
= (byte_t
*) (forward_pointer_hash_get(forwardPointers
, forwardPointerEntryCount
, (struct Object
*)oh
->special_objects_oop
)->toObj
) - memoryStart
;
1812 sih
.current_dispatch_id
= oh
->current_dispatch_id
;
1814 if (fwrite(&sih
, sizeof(struct slate_image_header
), 1, imageFile
) != 1
1815 || fwrite(memoryStart
, 1, totalSize
, imageFile
) != totalSize
) {
1816 fprintf(stderr
, "Error writing image!\n");
1819 free(forwardPointers
);
1822 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
1824 interpreter_stack_pop(oh, oh->cached.interpreter);
1825 interpreter_push_false(oh, oh->cached.interpreter);
1829 void prim_exit(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1830 /* print_stack_types(oh, 128);*/
1831 /* print_backtrace(oh);*/
1833 printf("Slate process %d exiting...\n", getpid());
1838 #pragma mark SmallInteger
1840 void prim_equals(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1841 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (args
[0] == args
[1])?oh
->cached
.true_object
:oh
->cached
.false_object
;
1844 void prim_less_than(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1846 ASSURE_SMALLINT_ARG(0);
1847 ASSURE_SMALLINT_ARG(1);
1848 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1849 (object_to_smallint(args
[0])<object_to_smallint(args
[1]))?oh
->cached
.true_object
:oh
->cached
.false_object
;
1852 void prim_bitand(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1853 ASSURE_SMALLINT_ARG(0);
1854 ASSURE_SMALLINT_ARG(1);
1855 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)((word_t
)args
[0] & (word_t
)args
[1]);
1857 void prim_bitor(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1858 ASSURE_SMALLINT_ARG(0);
1859 ASSURE_SMALLINT_ARG(1);
1860 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)((word_t
)args
[0] | (word_t
)args
[1]);
1862 void prim_bitxor(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1863 ASSURE_SMALLINT_ARG(0);
1864 ASSURE_SMALLINT_ARG(1);
1865 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)(((word_t
)args
[0] ^ (word_t
)args
[1])|SMALLINT_MASK
);
1867 void prim_bitnot(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1868 ASSURE_SMALLINT_ARG(0);
1869 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)(~((word_t
)args
[0]) | SMALLINT_MASK
);
1872 void prim_smallIntegerMinimum(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1873 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)(((word_t
)1<< (sizeof(word_t
)*8-1))|1); /*top and smallint bit set*/
1876 void prim_smallIntegerMaximum(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1877 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)LONG_MAX
; /*has all bits except the top set*/
1880 void prim_plus(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1881 struct Object
* x
= args
[0];
1882 struct Object
* y
= args
[1];
1883 word_t z
= object_to_smallint(x
) + object_to_smallint(y
);
1886 ASSURE_SMALLINT_ARG(0);
1887 ASSURE_SMALLINT_ARG(1);
1890 if (smallint_fits_object(z
)) {
1891 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(z
);
1893 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_ADD_OVERFLOW
), x
, y
, NULL
, resultStackPointer
);
1897 void prim_exponent(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1898 struct ByteArray
* x
= (struct ByteArray
*)args
[0];
1899 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object((*(word_t
*)float_part(x
) >> FLOAT_EXPONENT_OFFSET
) & 0xFF);
1903 void prim_significand(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1904 struct ByteArray
* x
= (struct ByteArray
*)args
[0];
1905 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(*(word_t
*)float_part(x
) & FLOAT_SIGNIFICAND
);
1909 void prim_withSignificand_exponent(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1910 /*this is really a bytearray*/
1911 word_t significand
= object_to_smallint(args
[1]), exponent
= object_to_smallint(args
[2]);
1912 struct ByteArray
* f
= heap_new_float(oh
);
1913 *((word_t
*)float_part(f
)) = significand
| exponent
<< FLOAT_EXPONENT_OFFSET
;
1915 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)f
;
1919 /* SmallInteger bitShift: SmallInteger */
1920 void prim_bitshift(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1921 word_t bits
= object_to_smallint(args
[0]);
1922 word_t shift
= object_to_smallint(args
[1]);
1925 ASSURE_SMALLINT_ARG(0);
1926 ASSURE_SMALLINT_ARG(1);
1929 if (shift
>= __WORDSIZE
&& bits
!= 0) {
1930 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_BIT_SHIFT_OVERFLOW
), args
[0], args
[1], NULL
, resultStackPointer
);
1936 if (!smallint_fits_object(z
) || z
>> shift
!= bits
) {
1937 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_BIT_SHIFT_OVERFLOW
), args
[0], args
[1], NULL
, resultStackPointer
);
1941 } else if (shift
<= -__WORDSIZE
) {
1942 z
= bits
>> (__WORDSIZE
-1);
1947 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(z
);
1951 /* SmallInteger - SmallInteger */
1952 void prim_minus(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1953 struct Object
* x
= args
[0];
1954 struct Object
* y
= args
[1];
1955 word_t z
= object_to_smallint(x
) - object_to_smallint(y
);
1957 ASSURE_SMALLINT_ARG(0);
1958 ASSURE_SMALLINT_ARG(1);
1960 if (smallint_fits_object(z
)) {
1961 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(z
);
1963 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SUBTRACT_OVERFLOW
), x
, y
, NULL
, resultStackPointer
);
1967 /* SmallInteger * SmallInteger */
1968 void prim_times(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1969 word_t x
= object_to_smallint(args
[0]);
1970 word_t y
= object_to_smallint(args
[1]);
1974 ASSURE_SMALLINT_ARG(0);
1975 ASSURE_SMALLINT_ARG(1);
1978 if (y
!= 0 && (z
/ y
!= x
|| !smallint_fits_object(z
))) { /*thanks slava*/
1979 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_MULTIPLY_OVERFLOW
), args
[0], args
[1], NULL
, resultStackPointer
);
1981 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(z
);
1985 /* SmallInteger quo: SmallInteger */
1986 void prim_quo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1987 struct Object
* x
= args
[0];
1988 struct Object
* y
= args
[1];
1990 ASSURE_SMALLINT_ARG(0);
1991 ASSURE_SMALLINT_ARG(1);
1993 if (object_to_smallint(y
) == 0) {
1994 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_DIVIDE_BY_ZERO
), x
, y
, NULL
, resultStackPointer
);
1996 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(object_to_smallint(x
) / object_to_smallint(y
));
2002 void prim_float_equals(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2003 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
2004 if (*float_part(x
) == *float_part(y
)) {
2005 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
2007 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
2011 void prim_float_less_than(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2012 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
2013 if (*float_part(x
) < *float_part(y
)) {
2014 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
2016 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
2020 void prim_float_plus(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2021 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
2022 struct ByteArray
* z
= heap_new_float(oh
);
2023 *float_part(z
) = *float_part(x
) + *float_part(y
);
2024 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
2027 void prim_float_minus(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2028 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
2029 struct ByteArray
* z
= heap_new_float(oh
);
2030 *float_part(z
) = *float_part(x
) - *float_part(y
);
2031 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
2035 void prim_float_times(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2036 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
2037 struct ByteArray
* z
= heap_new_float(oh
);
2038 *float_part(z
) = *float_part(x
) * *float_part(y
);
2039 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
2042 void prim_float_divide(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2043 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
2044 struct ByteArray
* z
= heap_new_float(oh
);
2045 *float_part(z
) = *float_part(x
) / *float_part(y
);
2046 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
2049 void prim_float_raisedTo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2050 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
2051 struct ByteArray
* z
= heap_new_float(oh
);
2052 *float_part(z
) = pow(*float_part(x
), *float_part(y
));
2053 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
2056 void prim_float_ln(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2057 struct ByteArray
*x
= (struct ByteArray
*)args
[0];
2058 struct ByteArray
* z
= heap_new_float(oh
);
2059 *float_part(z
) = log(*float_part(x
));
2060 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
2063 void prim_float_exp(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2064 struct ByteArray
*x
= (struct ByteArray
*)args
[0];
2065 struct ByteArray
* z
= heap_new_float(oh
);
2066 *float_part(z
) = exp(*float_part(x
));
2067 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
2070 void prim_float_sin(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
2071 struct ByteArray
*x
= (struct ByteArray
*)args
[0];
2072 struct ByteArray
* z
= heap_new_float(oh
);
2073 *float_part(z
) = sin(*float_part(x
));
2074 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
2078 void (*primitives
[]) (struct object_heap
* oh
, struct Object
* args
[], word_t n
, struct OopArray
* opts
, word_t resultStackPointer
) = {
2080 /*0-9*/ prim_as_method_on
, prim_as_accessor
, prim_map
, prim_set_map
, prim_fixme
, prim_removefrom
, prim_clone
, prim_clone_setting_slots
, prim_clone_with_slot_valued
, prim_fixme
,
2081 /*10-9*/ prim_fixme
, prim_fixme
, prim_clone_without_slot
, prim_at_slot_named
, prim_smallint_at_slot_named
, prim_at_slot_named_put
, prim_forward_to
, prim_bytearray_newsize
, prim_bytesize
, prim_byteat
,
2082 /*20-9*/ prim_byteat_put
, prim_ooparray_newsize
, prim_size
, prim_at
, prim_at_put
, prim_ensure
, prim_applyto
, prim_send_to
, prim_send_to_through
, prim_findon
,
2083 /*30-9*/ prim_fixme
, prim_run_args_into
, prim_exit
, prim_isIdenticalTo
, prim_identity_hash
, prim_identity_hash_univ
, prim_equals
, prim_less_than
, prim_bitor
, prim_bitand
,
2084 /*40-9*/ prim_bitxor
, prim_bitnot
, prim_bitshift
, prim_plus
, prim_minus
, prim_times
, prim_quo
, prim_fixme
, prim_fixme
, prim_frame_pointer_of
,
2085 /*50-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_heap_gc
, prim_bytesPerWord
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
,
2086 /*60-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_readConsole_from_into_starting_at
, prim_write_to_starting_at
, prim_flush_output
, prim_handle_for
, prim_handle_for_input
, prim_fixme
,
2087 /*70-9*/ prim_handleForNew
, prim_close
, prim_read_from_into_starting_at
, prim_write_to_from_starting_at
, prim_reposition_to
, prim_positionOf
, prim_atEndOf
, prim_sizeOf
, prim_save_image
, prim_fixme
,
2088 /*80-9*/ prim_fixme
, prim_fixme
, prim_getcwd
, prim_setcwd
, prim_significand
, prim_exponent
, prim_withSignificand_exponent
, prim_float_equals
, prim_float_less_than
, prim_float_plus
,
2089 /*90-9*/ prim_float_minus
, prim_float_times
, prim_float_divide
, prim_float_raisedTo
, prim_float_ln
, prim_float_exp
, prim_float_sin
, prim_fixme
, prim_fixme
, prim_fixme
,
2090 /*00-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_memory_new
, prim_memory_close
, prim_memory_addRef
, prim_memory_write
, prim_memory_read
, prim_memory_size
, prim_memory_resizeTo
,
2091 /*10-9*/ prim_addressOf
, prim_library_open
, prim_library_close
, prim_procAddressOf
, prim_extlibError
, prim_applyExternal
, prim_timeSinceEpoch
, prim_cloneSystem
, prim_readFromPipe
, prim_writeToPipe
,
2092 /*20-9*/ prim_selectOnReadPipesFor
, prim_selectOnWritePipesFor
, prim_closePipe
, prim_socketCreate
, prim_socketListen
, prim_socketAccept
, prim_socketBind
, prim_socketConnect
, prim_socketCreateIP
, prim_smallIntegerMinimum
,
2093 /*30-9*/ prim_smallIntegerMaximum
, prim_socketGetError
, prim_getAddrInfo
, prim_getAddrInfoResult
, prim_freeAddrInfoResult
, prim_vmArgCount
, prim_vmArg
, prim_environmentVariables
, prim_environment_atput
, prim_environment_removekey
,
2094 /*40-9*/ prim_isLittleEndian
, prim_system_name
, prim_system_release
, prim_system_version
, prim_system_platform
, prim_system_machine
, prim_system_execute
, prim_fixme
, prim_fixme
, prim_fixme
,
2095 /*50-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
,