Merge AddonLoader with Steve's documentation additions
[io.git] / libs / iovm / source / IoSystem.c
blob2c90e1e2cb18368c9ec95676dfc539293949161e
1 /*#io
2 System ioDoc(
3 docCopyright("Steve Dekorte", 2002)
4 docLicense("BSD revised")
5 docObject("System")
6 docDescription("Contains methods related to the IoVM.")
7 docCategory("Core")
8 */
10 #include "IoSystem.h"
11 #include "IoNumber.h"
12 #include "IoMessage_parser.h"
14 #if defined(linux)
15 #include <unistd.h>
16 #endif
18 #if defined(unix) || defined(__APPLE__) || defined(__NetBSD__)
19 #include <sys/utsname.h>
20 #ifdef __NetBSD__
21 # include <sys/param.h>
22 #endif
23 #ifndef __CYGWIN__
24 # include <sys/sysctl.h>
25 #endif
26 #endif
28 #ifdef WIN32
29 #include <windows.h>
31 static void setenv(const char *varName, const char* value, int force)
33 const char *safeValue;
34 char *buf;
36 if (!varName)
38 return;
41 if (!value)
43 safeValue = "";
45 else
47 safeValue = value;
50 // buffer for var and value plus '=' and the \0
51 buf = (char*)io_calloc(1, strlen(varName) + strlen(safeValue) + 2);
53 if (!buf)
55 return;
58 strcpy(buf, varName);
59 strcat(buf, "=");
60 strcat(buf, safeValue);
62 _putenv(buf);
63 io_free(buf);
66 //#define setenv(k, v, o) SetEnvironmentVariable((k), (v))
67 #endif
69 #if defined(__CYGWIN__) || defined(_WIN32)
70 #include <windows.h>
71 #endif
73 IoObject *IoSystem_proto(void *state)
75 IoMethodTable methodTable[] = {
76 #if defined(_WIN32)
77 {"shellExecute", IoObject_shellExecute},
78 #endif
79 {"errorNumber", IoObject_errorNumberDescription},
80 {"exit", IoObject_exit},
81 {"getEnvironmentVariable", IoObject_getEnvironmentVariable},
82 {"setEnvironmentVariable", IoObject_setEnvironmentVariable},
83 {"system", IoObject_system},
84 //{"memorySizeOfState", IoObject_memorySizeOfState},
85 //{"compactState", IoObject_compactState},
86 {"platform", IoObject_platform},
87 {"platformVersion", IoObject_platformVersion},
88 {"sleep", IoObject_sleep},
89 {"activeCpus", IoObject_activeCpus},
90 {"recycledObjectCount", IoObject_recycledObjectCount},
91 {"maxRecycledObjects", IoObject_maxRecycledObjects},
92 {"setMaxRecycledObjects", IoObject_setMaxRecycledObjects},
93 {"symbols", IoObject_symbols},
94 {"setLobby", IoObject_setLobby},
95 {NULL, NULL},
98 IoObject *self = IoObject_new(state);
99 IoObject_addMethodTable_(self, methodTable);
101 /*#io
102 docSlot("version", "Returns the Io version number.")
104 IoObject_setSlot_to_(self, IOSYMBOL("version"), IONUMBER(IO_VERSION_NUMBER));
106 //IoObject_setSlot_to_(self, IOSYMBOL("distribution"), IOSYMBOL("Io"));
107 IoObject_setSlot_to_(self, IOSYMBOL("type"), IOSYMBOL("System"));
109 #ifndef INSTALL_PREFIX
110 #define INSTALL_PREFIX "/usr/local"
111 #endif
114 /*#io
115 docSlot("installPrefix", "Returns the root path where io was install. The default is /usr/local.")
117 IoObject_setSlot_to_(self, IOSYMBOL("installPrefix"), IOSYMBOL(INSTALL_PREFIX));
119 return self;
122 /*#io
123 docSlot("args", "Returns the list of command line argument strings the program was run with.")
127 IoObject *IoObject_errorNumber(IoObject *self, IoObject *locals, IoMessage *m)
129 return IONUMBER(errno);
133 #include <stdio.h>
134 #include <errno.h>
136 #if defined(_WIN32)
137 #include <shellapi.h>
138 IoObject *IoObject_shellExecute(IoObject *self, IoObject *locals, IoMessage *m)
140 return IONUMBER((int) ShellExecute(NULL, "open", CSTRING(IoMessage_locals_symbolArgAt_(m, locals, 0)), NULL, NULL, SW_SHOWNORMAL));
142 #endif
144 IoObject *IoObject_errorNumberDescription(IoObject *self, IoObject *locals, IoMessage *m)
146 /*#io
147 docSlot("errorNumber", "Returns the C errno string.")
149 return errno ? IOSYMBOL(strerror(errno)) : IONIL(self);
152 IoObject *IoObject_exit(IoObject *self, IoObject *locals, IoMessage *m)
154 /*#io
155 docSlot("exit(optionalReturnCodeNumber)",
156 "Shutdown the IoState (io_free all objects) and return
157 control to the calling program (if any). ")
160 int returnCode = 0;
162 if (IoMessage_argCount(m))
164 returnCode = IoMessage_locals_intArgAt_(m, locals, 0);
167 IoState_exit(IOSTATE, returnCode);
168 return self;
171 IoObject *IoObject_getEnvironmentVariable(IoObject *self, IoObject *locals, IoMessage *m)
173 /*#io
174 docSlot("getEnvironmentVariable(nameString)",
175 "Returns a string with the value of the environment variable whose name is specified by nameString.")
178 IoSymbol *key = IoMessage_locals_symbolArgAt_(m, locals, 0);
179 char *s = getenv(CSTRING(key));
181 if (!s)
183 return ((IoState *)IOSTATE)->ioNil;
186 return IoState_symbolWithCString_(IOSTATE, s);
189 IoObject *IoObject_system(IoObject *self, IoObject *locals, IoMessage *m)
191 /*#io
192 docSlot("system(aString)",
193 "Makes a system call and returns a Number for the return value.")
196 IoSymbol *s = IoMessage_locals_symbolArgAt_(m, locals, 0);
197 int result = system(CSTRING(s))/ 256;
198 //printf("system result = %i\n", result);
199 return IONUMBER(result);
202 IoObject *IoObject_memorySizeOfState(IoObject *self, IoObject *locals, IoMessage *m)
205 docSlot("memorySizeOfState",
206 "Returns the number of bytes in the IoState
207 (this may not include memory allocated by C libraries).")
210 return IONUMBER(0);
211 //return IONUMBER(IoState_memorySize(IOSTATE));
214 IoObject *IoObject_compactState(IoObject *self, IoObject *locals, IoMessage *m)
217 docSlot("compactState",
218 "Attempt to compact the memory of the IoState if possible.")
221 //IoState_compact(IOSTATE);
222 return self;
225 IoObject *IoObject_setEnvironmentVariable(IoObject *self, IoObject *locals, IoMessage *m)
227 /*#io
228 docSlot("setEnvironmentVariable(keyString, valueString)", "Sets the environment variable keyString to the value valueString.")
231 // setenv() takes different args in different implementations
232 IoSymbol *key = IoMessage_locals_symbolArgAt_(m, locals, 0);
233 IoSymbol *value = IoMessage_locals_symbolArgAt_(m, locals, 1);
234 setenv(CSTRING(key), CSTRING(value), 1);
235 return self;
238 IoObject *IoObject_platform(IoObject *self, IoObject *locals, IoMessage *m)
240 /*#io
241 docSlot("platform", "Returns a string description of the platform.")
244 char *platform = "Unknown";
246 #if defined(__CYGWIN__)
248 platform = "cygwin";
250 #elif defined(__MINGW32__)
252 platform = "mingw";
254 #elif defined(_WIN32)
256 OSVERSIONINFO os;
258 os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
259 GetVersionEx(&os);
261 switch(os.dwPlatformId)
263 case VER_PLATFORM_WIN32_WINDOWS:
264 switch(os.dwMinorVersion)
266 case 0:
267 platform = "Windows 95";
268 break;
269 case 10:
270 platform = "Windows 98";
271 break;
272 case 90:
273 platform = "Windows ME";
274 break;
275 default:
276 platform = "Windows 9X";
277 break;
279 break;
281 case VER_PLATFORM_WIN32_NT:
282 if (os.dwMajorVersion == 3 || os.dwMajorVersion == 4)
284 platform = "Windows NT";
286 else if (os.dwMajorVersion == 5)
288 switch(os.dwMinorVersion)
290 case 0:
291 platform = "Windows 2000";
292 break;
293 case 1:
294 platform = "Windows XP";
295 break;
296 default:
297 platform = "Windows";
298 break;
301 else
303 platform = "Windows";
305 break;
307 default: platform = "Windows";
310 #elif defined(unix) || defined(__APPLE__) || defined(__NetBSD__)
311 /* Why Apple and NetBSD don't define 'unix' I'll never know. */
312 struct utsname os;
313 int ret = uname(&os);
315 if (ret == 0)
317 platform = os.sysname;
319 #endif
321 return IoState_symbolWithCString_(IOSTATE, platform);
324 IoObject *IoObject_platformVersion(IoObject *self, IoObject *locals, IoMessage *m)
326 char platformVersion[256];
328 /*#io
329 docSlot("platformVersion", "Returns the version id of the OS.")
332 #if defined(_WIN32)
334 OSVERSIONINFO os;
336 os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
337 GetVersionEx(&os);
339 snprintf(platformVersion, sizeof(platformVersion) - 1, "%d.%d",
340 os.dwMajorVersion, os.dwMinorVersion);
342 #elif defined(unix) || defined(__APPLE__) || defined(__NetBSD__)
343 /* Why Apple and NetBSD don't define 'unix' I'll never know. */
344 struct utsname os;
345 int ret = uname(&os);
347 if (ret == 0)
349 snprintf(platformVersion, sizeof(platformVersion) - 1, os.release);
351 #endif
353 return IoState_symbolWithCString_(IOSTATE, platformVersion);
356 IoObject *IoObject_activeCpus(IoObject *self, IoObject *locals, IoMessage *m)
358 /*#io
359 docSlot("activeCpus", "Returns the number of active CPUs.")
361 int cpus = 1;
362 #if defined(CTL_HW)
363 int mib[2];
364 size_t len = sizeof(cpus);
365 mib[0] = CTL_HW;
366 #if defined(HW_AVAILCPU)
367 mib[1] = HW_AVAILCPU;
368 #elif defined(HW_NCPU)
369 mib[1] = HW_NCPU;
370 #else
371 #error
372 #endif
373 sysctl(mib, 2, &cpus, &len, NULL, 0);
374 #elif defined(_SC_NPROCESSORS_ONLN)
375 cpus = sysconf(_SC_NPROCESSORS_ONLN);
376 #elif defined(_SC_NPROC_ONLN)
377 cpus = sysconf(_SC_NPROC_ONLN);
378 #elif defined(WIN32)
379 SYSTEM_INFO si;
380 GetSystemInfo(&si);
381 cpus = si.dwNumberOfProcessors;
382 #else
383 #error
384 #endif
385 return IONUMBER(cpus);
388 #include "PortableUsleep.h"
390 IoObject *IoObject_sleep(IoObject *self, IoObject *locals, IoMessage *m)
392 /*#io
393 docSlot("sleep(secondsNumber)", "Performs a *blocking* sleep call for specified number of seconds.")
396 double seconds = IoMessage_locals_doubleArgAt_(m, locals, 0);
397 unsigned int microseconds = (seconds * 1000000);
398 usleep(microseconds);
399 return self;
402 IoObject *IoObject_maxRecycledObjects(IoObject *self, IoObject *locals, IoMessage *m)
404 /*#io
405 docSlot("maxRecycledObjects", "Returns the max number of recycled objects used.")
408 return IONUMBER(IOSTATE->maxRecycledObjects);
411 IoObject *IoObject_setMaxRecycledObjects(IoObject *self, IoObject *locals, IoMessage *m)
413 /*#io
414 docSlot("setMaxRecycledObjects(aNumber)", "Sets the max number of recycled objects used.")
417 size_t max = IoMessage_locals_sizetArgAt_(m, locals, 0);
418 IOSTATE->maxRecycledObjects = max;
419 return self;
422 IoObject *IoObject_recycledObjectCount(IoObject *self, IoObject *locals, IoMessage *m)
424 /*#io
425 docSlot("recycledObjectCount", "Returns the current number of objects being held for recycling.")
428 return IONUMBER(List_size(IOSTATE->recycledObjects));
431 #include "IoList.h"
433 IoObject *IoObject_symbols(IoObject *self, IoObject *locals, IoMessage *m)
435 /*#io
436 docSlot("symbols", "Returns a List containing all Symbols currently in the system.")
438 IoList *list = IoList_new(IOSTATE);
439 SHASH_FOREACH(IOSTATE->symbols, i, v, IoList_rawAppend_(list, v));
440 return list;
443 IoObject *IoObject_setLobby(IoObject *self, IoObject *locals, IoMessage *m)
445 /*#io
446 docSlot("setLobby", "Sets the root object of the garbage collector.")
449 IoObject *v = IoMessage_locals_valueArgAt_(m, locals, 0);
450 IoState_setLobby_(IOSTATE, v);
451 return self;
454 /*#io
455 docSlot("version", "Returns a version number for Io.")
458 /*#io
459 docSlot("distribution", "Returns the Io distribution name as a string.")
462 // save ----------------------
465 IoObject *IoObject_setStateFile(IoObject *self, IoObject *locals, IoMessage *m)
467 IoSeq *fileName = IoMessage_locals_seqArgAt_(m, locals, 0);
470 IoObject *IoObject_saveState(IoObject *self, IoObject *locals, IoMessage *m)
472 IoState_saveState(IOSTATE);
475 int IoState_saveState(IoState *self)
477 Collector *collector = IOSTATE->collector;
478 self->store->open();
479 Collector_collect(collect);
480 COLLECTOR_FOREACH(collector, v, IoState_storeObject_(state, v));
481 self->store->close();
482 return 1;
485 int IoState_syncState(IoState *self)
487 Collector *collector = IOSTATE->collector;
488 self->store->open();
489 Collector_collect(collect);
490 COLLECTOR_FOREACH(collector, v,
491 if (!IoObject_persistentId(v) || IoObject_isDirty(v))
492 IoState_storeObject_(state, v)
494 self->store->close();
495 return 1;
498 PID_TYPE IoObject_pid(IoObject *self)
500 if (!IoObject_persistentId(self))
502 IoObject_persistentId_(self, IoState_newPid(IOSTATE));
505 return IoObject_persistentId(self);
508 PID_TYPE IoState_newPid(IoState *self)
510 return self->store->newPid();
513 int IoState_storeObject_(IoState *self, IoObject *v)
515 // IoObject_pid will request new pid from the state if needed
517 UArray *u = IoObject_asStorable(v);
518 self->store->atPut(state, IoObject_pid(v), UArray_bytes(u), UArray_sizeInBytes(u));
519 return 1;
522 // load ----------------------
524 int IoState_loadState(IoState *self, IoObject *v)
526 IoObject *lobby;
527 self->store->open();
528 Datum *d = self->store->at(state, 1); // pid of lobby
529 lobby = IoObject_fromDatum(self, d)
530 IoState_setLobby_(self, PObject_newWithPid(state, 1));
531 return 1;