serious bugfix in Raise_IdxError (number got formatted as string, causing a segmentat...
[vox.git] / src / stdlib / oslib.cpp
blobbbfa0f289502ac1ce61fbf36a1047a8dbe93669c
3 #include <boost/filesystem.hpp>
4 #include "helper.hpp"
6 namespace fslib = boost::filesystem;
7 typedef fslib::filesystem_error fslib_error;
9 struct VXPopen: VXIOBase
11 FILE* fn_base_open(const char* path, const char* mode)
13 return popen(path, mode);
16 void fn_base_close(FILE* handle)
18 pclose(handle);
23 const char* oshelper_strerror(int errval)
25 #if defined(VOX_PLATFORM_MSWINDOWS)
26 LPCSTR tempmessage;
27 ::FormatMessage(
28 FORMAT_MESSAGE_FROM_SYSTEM |
29 FORMAT_MESSAGE_ALLOCATE_BUFFER |
30 FORMAT_MESSAGE_IGNORE_INSERTS,
31 NULL, errval, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
32 (LPTSTR)&tempmessage,0,NULL);
33 return (const char*)tempmessage;
34 #else
35 return strerror(errval);
36 #endif
39 int oshelper_errno()
41 #if defined(VOX_PLATFORM_MSWINDOWS)
42 return ::GetLastError();
43 #else
44 return errno;
45 #endif
48 const char* oshelper_lasterror()
50 return oshelper_strerror(oshelper_errno());
53 bool oshelper_killpid(int pid, int sign)
55 bool failed;
56 #if defined(VOX_PLATFORM_UNIX)
57 failed = (kill(pid, sign) == -1);
58 #elif defined(VOX_PLATFORM_MSWINDOWS)
59 int retv;
60 HANDLE hnd = OpenProcess(1, 0, pid);
61 failed = (0 != TerminateProcess(hnd, 0));
62 #endif
63 return failed;
66 int oshelper_sleep(VXFloat milisec)
68 #ifdef VOX_PLATFORM_MSWINDOWS
69 ::Sleep(milisec);
70 #else
71 timespec req = {0, 0};
72 time_t sec;
73 if (milisec == 0)
75 return -1;
77 sec = (milisec/1000);
78 milisec = milisec - (sec * 1000);
79 req.tv_sec = sec;
80 req.tv_nsec = milisec*1000000L;
81 while(nanosleep(&req, &req) == -1)
83 continue;
85 #endif
86 return -1;
89 bool oshelper_chdir(const std::string& path)
91 int status;
92 #if defined(VOX_PLATFORM_MSWINDOWS)
93 status = _chdir(path.c_str());
94 #elif defined(VOX_PLATFORM_UNIX)
95 status = chdir(path.c_str());
96 #endif
97 return status;
100 bool oshelper_chmod(const std::string& path, unsigned int octal)
102 int status;
103 #if defined(VOX_PLATFORM_MSWINDOWS)
104 status = _chmod(path.c_str(), octal);
105 #elif defined(VOX_PLATFORM_UNIX)
106 status = chmod(path.c_str(), octal);
107 #endif
108 return (status == 0);
111 bool oshelper_mkdir(const std::string& path, int octal)
113 int status;
114 #if defined(VOX_PLATFORM_MSWINDOWS)
115 (void)octal;
116 status = _mkdir(path.c_str());
117 #elif defined(VOX_PLATFORM_UNIX)
118 status = mkdir(path.c_str(), octal);
119 #endif
120 return (status == -1);
123 template<typename Type>
124 inline static const char* oshelper_exception_message(Type& err)
126 return err.code().message().c_str();
129 VXInteger oslib_getenv(VXState* v)
131 const char* env_name;
132 const char* env_value;
133 v->GetString(2, &env_name, NULL);
134 env_value = getenv(env_name);
135 if(env_value != NULL)
137 v->Push(v->NewString(env_value));
138 return 1;
140 return 0;
143 VXInteger oslib_system(VXState* v)
145 const char* shellcmd;
146 if(system(NULL) == 0)
148 return v->ThrowError("system() is not available");
150 v->GetString(2, &shellcmd, NULL);
151 v->Push(VXInteger(system(shellcmd)));
152 return 1;
156 VXInteger oslib_clock(VXState* v)
158 v->Push(VXFloat(clock()) / VXFloat(CLOCKS_PER_SEC));
159 return 1;
162 VXInteger oslib_time(VXState* v)
164 time_t t;
165 time(&t);
166 v->Push(VXInteger(t));
167 return 1;
170 VXInteger oslib_remove(VXState* v)
172 const char* path;
173 v->GetString(2, &path, NULL);
176 fslib::remove(path);
178 catch(fslib_error& err)
180 return v->ThrowError(oshelper_exception_message(err));
182 return 0;
185 VXInteger oslib_remove_all(VXState* v)
187 const char* path;
188 v->GetString(2, &path, NULL);
191 fslib::remove_all(path);
193 catch(fslib_error& err)
195 return v->ThrowError(oshelper_exception_message(err));
197 return 0;
200 VXInteger oslib_exit(VXState* v)
202 VXInteger status;
203 if(VX_FAILED(v->GetInteger(2, &status)))
205 status = -1;
207 exit(status);
208 return 0;
212 VXInteger oslib_rename(VXState* v)
214 const char* oldpath;
215 const char* newpath;
216 v->GetString(2, &oldpath, NULL);
217 v->GetString(3, &newpath, NULL);
220 fslib::rename(oldpath, newpath);
222 catch(fslib_error& err)
224 return v->ThrowError(oshelper_exception_message(err));
226 return 0;
229 VXInteger oslib_date(VXState* v)
231 time_t t;
232 VXInteger it;
233 VXInteger top;
234 VXInteger format = 'l';
235 if(v->GetTop() > 1)
237 v->GetInteger(2,&it);
238 t = it;
239 if(v->GetTop() > 2)
241 v->GetInteger(3, (VXInteger*)&format);
244 else
246 time(&t);
248 tm *date;
249 if(format == 'u')
251 date = gmtime(&t);
253 else
255 date = localtime(&t);
257 if(!date)
259 return v->ThrowError("crt api failure");
261 VXTableObj* tb = v->NewTable();
262 tb->NewSlot(v->NewString("sec"), VXInteger(date->tm_sec));
263 tb->NewSlot(v->NewString("min"), VXInteger(date->tm_min));
264 tb->NewSlot(v->NewString("hour"), VXInteger(date->tm_hour));
265 tb->NewSlot(v->NewString("day"), VXInteger(date->tm_mday));
266 tb->NewSlot(v->NewString("month"), VXInteger(date->tm_mon));
267 tb->NewSlot(v->NewString("year"), VXInteger(date->tm_year));
268 tb->NewSlot(v->NewString("wday"), VXInteger(date->tm_wday));
269 tb->NewSlot(v->NewString("yday"), VXInteger(date->tm_yday));
270 v->Push(tb);
271 return 1;
274 VXInteger oslib_listdir(VXState* v)
276 const char* path;
277 std::string s_itm;
278 v->GetString(2, &path, NULL);
281 fslib::directory_iterator end;
282 fslib::directory_iterator iter(path);
283 VXArrayObj* arr = v->NewArray();
284 for(; iter!=end; iter++)
286 s_itm = (*iter).path().string();
287 arr->Append(v->NewString(s_itm.c_str(), s_itm.length()));
289 v->Push(arr);
291 catch(fslib_error& err)
293 return v->ThrowError(oshelper_exception_message(err));
295 return 1;
298 VXInteger oslib_kill(VXState* v)
300 VXInteger pid;
301 VXInteger sign;
302 v->GetInteger(2, &pid);
303 if(VX_FAILED(v->GetInteger(3, &sign)))
305 sign = SIGINT;
307 v->PushInteger(oshelper_killpid(pid, sign));
308 return 1;
311 VXInteger oslib_mkdir(VXState* v)
313 const char* path;
314 VXInteger permissions;
315 v->GetString(2, &path, NULL);
316 if(VX_FAILED(v->GetInteger(3, &permissions)))
318 permissions = 0755;
320 if(oshelper_mkdir(path, permissions) == false)
322 return v->ThrowError(oshelper_lasterror());
324 return 0;
327 VXInteger oslib_chmod(VXState* v)
329 const char* path;
330 VXInteger permissions;
331 v->GetString(2, &path, NULL);
332 v->GetInteger(3, &permissions);
333 if(oshelper_chmod(path, permissions) == false)
335 return v->ThrowError(oshelper_lasterror());
337 return 0;
340 VXInteger oslib_basename(VXState* v)
342 const char* path;
343 std::string newpath;
344 v->GetString(2, &path, NULL);
345 newpath = fslib::path(path).filename().string();
346 v->Push(v->NewString(newpath.c_str(), newpath.length()));
347 return 1;
350 VXInteger oslib_dirname(VXState* v)
352 const char* path;
353 std::string newpath;
354 v->GetString(2, &path, NULL);
355 fslib::path _tmp(path);
356 newpath = fslib::path(path).parent_path().string();
357 v->Push(v->NewString(newpath.c_str(), newpath.length()));
358 return 1;
361 VXInteger oslib_usleep(VXState* v)
363 VXFloat howlong;
364 v->GetFloat(2, &howlong);
365 oshelper_sleep(howlong);
366 return 0;
369 VXInteger oslib_sleep(VXState* v)
371 VXInteger howlong;
372 v->GetInteger(2, &howlong);
373 oshelper_sleep(howlong * 1000);
374 return 0;
377 VXInteger oslib_filesize(VXState* v)
379 const char* path;
380 v->GetString(2, &path, NULL);
383 v->Push(VXInteger(fslib::file_size(path)));
385 catch(fslib_error& err)
387 return v->ThrowError(oshelper_exception_message(err));
389 return 1;
392 VXInteger oslib_exists(VXState* v)
394 const char* path;
395 v->GetString(2, &path, NULL);
398 v->Push(bool(fslib::exists(path)));
400 catch(fslib_error& err)
402 return v->ThrowError(oshelper_exception_message(err));
404 return 1;
407 VXInteger oslib_isfile(VXState* v)
409 const char* path;
410 v->GetString(2, &path, NULL);
411 v->Push(bool(fslib::is_regular_file(path)));
412 return 1;
415 VXInteger oslib_isdir(VXState* v)
417 const char* path;
418 v->GetString(2, &path, NULL);
421 v->Push(bool(fslib::is_directory(path)));
423 catch(fslib_error& err)
425 return v->ThrowError(oshelper_exception_message(err));
427 return 1;
430 VXInteger oslib_stat(VXState* v)
432 const char* path;
433 struct stat buf;
434 v->GetString(2, &path, NULL);
435 if(stat(path, &buf) == 0)
437 VXTableObj* tb = v->NewTable();
439 v->Push(tb);
440 return 1;
442 return v->ThrowError(oshelper_lasterror());
445 /* popen */
447 VXInteger popenclass_fn_releasehook(VXUserPointer p, VXInteger size)
449 (void)size;
450 VXPopen* self = (VXPopen*)p;
451 if(self->isclosed == false)
453 self->close();
455 delete self;
456 return 1;
459 VXInteger popenclass_fn_constructor(VXState* v)
461 const char* path;
462 const char* mode;
463 VXPopen* self;
464 self = new VXPopen;
465 v->GetString(2, &path, NULL);
466 if(VX_FAILED(v->GetString(3, &mode, NULL)))
468 mode = "r";
470 if(!self->open(path, mode))
472 return v->ThrowError(oshelper_lasterror());
474 v->SetInstanceUp(1, (VXUserPointer*)&self);
475 v->SetReleaseHook(1, popenclass_fn_releasehook);
476 return 0;
479 VXInteger popenclass_fn_read(VXState* v)
481 char* buffer;
482 VXInteger howmuch;
483 VXInteger haveread;
484 VXPopen* self;
485 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
486 if(VX_FAILED(v->GetInteger(2, &howmuch)))
488 howmuch = 1024;
490 buffer = new char[howmuch+1];
491 haveread = self->readbuf(buffer, howmuch);
492 if(haveread > 0)
494 buffer[haveread] = 0;
495 v->PushString(buffer, haveread);
497 else
499 v->PushNull();
501 delete[] buffer;
502 return 1;
505 VXInteger popenclass_fn_flush(VXState* v)
507 VXPopen* self;
508 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
509 v->Push(self->flushstream());
510 return 1;
513 VXInteger popenclass_fn_name(VXState* v)
515 VXPopen* self;
516 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
517 v->PushString(self->name);
518 return 1;
521 VXInteger popenclass_fn_readline(VXState* v)
523 VXPopen* self;
524 std::string buffer;
525 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
526 if(self->eof())
528 return 0;
530 self->readline(buffer);
531 v->Push(v->NewString(buffer.c_str(), buffer.length()));
532 return 1;
535 VXInteger popenclass_fn_readchar(VXState* v)
537 VXPopen* self;
538 VXInteger c;
539 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
540 c = self->readchar();
541 if(c == EOF)
543 v->PushNull();
545 else
547 v->Push(c);
549 return 1;
553 VXInteger popenclass_fn_close(VXState* v)
555 VXPopen* self;
556 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
557 v->Push(self->close());
558 return 1;
561 VXInteger popenclass_fn_write(VXState* v)
563 const char* data;
564 VXInteger len;
565 VXInteger written;
566 VXPopen* self;
567 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
568 v->GetString(2, &data, &len);
569 if(self->write(data, len, &written) == true)
571 v->Push(written);
572 return 0;
574 /* when the file got opened in readonly mode, write()
575 will fail, so don't just ignore it, but handle it */
576 return v->ThrowError(self->error());
579 VXInteger popenclass_fn_eof(VXState* v)
581 VXPopen* self;
582 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
583 v->Push(bool(self->eof()));
584 return 1;
587 static VXRegFunction popen_funcs[]=
589 {"constructor", popenclass_fn_constructor, -2, ".ss"},
590 {"name", popenclass_fn_name, -1, ".n"},
591 {"read", popenclass_fn_read, -1, ".n"},
592 {"readchar", popenclass_fn_readchar, 1, NULL},
593 {"readline", popenclass_fn_readline, -1, NULL},
594 {"write", popenclass_fn_write, 2, ".s"},
595 {"close", popenclass_fn_close, 1, NULL},
596 {"flush", popenclass_fn_flush, 1, "x"},
597 {"eof", popenclass_fn_eof, 1, "x"},
598 {0, 0, 0, 0}
601 VXInteger oslib_uname(VXState* v)
603 #if defined(VOX_PLATFORM_UNIX)
604 struct utsname buf;
605 if(uname(&buf) == 0)
607 VXTableObj* tb = v->NewTable();
608 tb->NewSlot(v->NewString("sysname"), v->NewString(buf.sysname));
609 tb->NewSlot(v->NewString("nodename"), v->NewString(buf.nodename));
610 tb->NewSlot(v->NewString("release"), v->NewString(buf.release));
611 tb->NewSlot(v->NewString("version"), v->NewString(buf.version));
612 tb->NewSlot(v->NewString("machine"), v->NewString(buf.machine));
613 v->Push(tb);
614 return 1;
616 return v->ThrowError(oshelper_lasterror());
617 #else
618 return v->ThrowError("uname() is not available on this platform");
619 #endif
624 VXInteger oslib_tempname(VXState* v)
626 char* result; // char*, because it needs to be free()'d
627 const char* path;
628 const char* tpl;
629 if(VX_FAILED(v->GetString(2, &path, NULL)))
630 path = NULL;
631 if(VX_FAILED(v->GetString(3, &tpl, NULL)))
632 tpl = NULL;
633 result = tempnam(path, tpl);
634 v->Push(v->NewString(result));
635 free(result);
636 return 1;
639 VXInteger oslib_joinpath(VXState* v)
641 VXInteger i;
642 VXObject strval;
643 VXObject ob;
644 std::string fullpath;
645 fslib::path p;
646 for(i=2; i!=(v->GetTop()+1); i++)
648 std::string str;
649 ob = v->StackGet(i);
650 v->ToString(ob, strval);
651 strval.String()->Get(&str);
652 p /= str;
653 ob.Null();
655 fullpath = p.string();
656 v->Push(v->NewString(fullpath.c_str(), fullpath.length()));
657 return 1;
660 VXInteger oslib_abspath(VXState* v)
662 std::string subject;
663 std::string fullpath;
664 v->GetString(2, &subject);
665 fslib::path p(subject);
666 fullpath = p.string();
667 v->Push(v->NewString(fullpath.c_str(), fullpath.length()));
668 return 1;
671 VXRegFunction oslib_funcs[]=
673 {"getenv", oslib_getenv, 2, ".s"},
674 {"system", oslib_system, 2, ".s"},
675 {"date", oslib_date, -1, ".nn"},
676 {"remove", oslib_remove, 2, ".s"},
677 {"remove_all", oslib_remove_all, 2, ".s"},
678 {"listdir", oslib_listdir, 2, ".s"},
679 {"rename", oslib_rename, 3, ".ss"},
680 {"clock", oslib_clock, 0, NULL},
681 {"time", oslib_time, 1, NULL},
682 {"exit", oslib_exit, -1, ".n"},
683 {"kill", oslib_kill, -1, ".nn"},
684 {"chmod", oslib_chmod, 3, ".sn"},
685 {"mkdir", oslib_mkdir, 3, ".s|.n"},
686 {"basename", oslib_basename, 2, ".s"},
687 {"dirname", oslib_dirname, 2, ".s"},
688 {"usleep", oslib_usleep, 2, ".n"},
689 {"sleep", oslib_sleep, 2, ".n"},
690 {"exists", oslib_exists, 2, ".s"},
691 {"isdir", oslib_isdir, 2, ".s"},
692 {"isfile", oslib_isfile, 2, ".s"},
693 {"abspath", oslib_abspath, 2, ".s"},
694 {"joinpath", oslib_joinpath, -1, "."},
695 {"filesize", oslib_filesize, 2, ".s"},
696 {"uname", oslib_uname, 1, NULL},
697 {"tempname", oslib_tempname, -1, ".ss"},
698 {0, 0, 0, 0}
701 VXInteger voxstd_register_oslib(VXState* v)
703 VXTableObj* tb = v->NewTable();
704 v->RegisterLib("os", oslib_funcs, true, tb);
705 tb->Set(v->NewString("popen"), v->RegClass(popen_funcs));
706 #ifndef VX_NO_LOADLIB
707 oslib_register_libload(v, tb);
708 #endif
709 return 1;