00001
00013
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <unistd.h>
00017
00018 #include "NewtType.h"
00019
00020
00021 #if defined(__WIN32__)
00022 #include "win/dlfcn.h"
00023 #elif defined(HAVE_DLOPEN)
00024 #include <dlfcn.h>
00025 #endif
00026
00027 #ifdef HAVE_GETPWNAM
00028 #include <pwd.h>
00029 #endif
00030
00031
00032 #include "NewtCore.h"
00033 #include "NewtVM.h"
00034 #include "NewtBC.h"
00035 #include "NewtIO.h"
00036 #include "NewtFile.h"
00037
00038
00039
00040
00041 enum {
00042 typeScript,
00043 typeDylib,
00044 };
00045
00046
00047
00048
00050 typedef struct {
00051 newtRefVar ext;
00052 int type;
00053 } file_ext_t;
00054
00055
00056 #ifdef HAVE_DLOPEN
00057
00065 void * NewtDylibInstall(const char * fname)
00066 {
00067 newt_install_t install_call;
00068 void * lib;
00069
00070 lib = dlopen(fname, RTLD_LAZY);
00071
00072 if (lib != NULL)
00073 {
00074 install_call = (newt_install_t)dlsym(lib, "newt_install");
00075
00076 if (install_call == NULL)
00077 {
00078 dlclose(lib);
00079 return NULL;
00080 }
00081
00082 (*install_call)();
00083 }
00084
00085 return lib;
00086 }
00087
00088 #endif
00089
00090
00091
00100 bool NewtFileExists(char * path)
00101 {
00102 FILE * f;
00103
00104 f = fopen(path, "r");
00105
00106 if (f != NULL)
00107 {
00108 fclose(f);
00109 return true;
00110 }
00111
00112 return false;
00113 }
00114
00115
00116 #pragma mark -
00117
00123 char NewtGetFileSeparator(void)
00124 {
00125 return '/';
00126 }
00127
00128
00129
00140 #ifdef HAVE_GETPWNAM
00141
00142 char * NewtGetHomeDir(const char * s, char ** subdir)
00143 {
00144 struct passwd * pswd = NULL;
00145 uint32_t len;
00146 char * login = NULL;
00147 char * dir = NULL;
00148 char * sepp;
00149 char sep;
00150
00151 sep = NewtGetFileSeparator();
00152 sepp = strchr(s + 1, sep);
00153
00154 if (sepp != NULL)
00155 {
00156 len = sepp - (s + 1);
00157 login = malloc(len + 1);
00158 strncpy(login, s + 1, len);
00159 pswd = getpwnam(s + 1);
00160 }
00161 else
00162 {
00163 login = (char *)s + 1;
00164 }
00165
00166 if (*login)
00167 pswd = getpwnam(login);
00168 else
00169 pswd = getpwuid(getuid());
00170
00171 if (pswd != NULL)
00172 dir = pswd->pw_dir;
00173
00174 if (subdir != NULL)
00175 *subdir = sepp;
00176
00177 if (s + 1 != login)
00178 free(login);
00179
00180 return dir;
00181 }
00182
00183 #else
00184
00185 char * NewtGetHomeDir(const char * s, char ** subdir)
00186 {
00187 return NULL;
00188 }
00189
00190 #endif
00191
00192
00193
00205 char * NewtJoinPath(char * s1, char * s2, char sep)
00206 {
00207 char * path;
00208 uint32_t len;
00209 uint32_t len1;
00210 uint32_t len2;
00211
00212 len1 = strlen(s1);
00213 len2 = strlen(s2);
00214
00215 len = len1 + len2 + 2;
00216
00217 path = malloc(len);
00218 if (path == NULL) return NULL;
00219
00220 strcpy(path, s1);
00221
00222 path[len1] = sep;
00223 strncpy(path + len1 + 1, s2, len2 + 1);
00224
00225 return path;
00226 }
00227
00228
00229
00237 char * NewtRelToAbsPath(char * s)
00238 {
00239 char * src;
00240 char * dst;
00241 char sep;
00242
00243 sep = NewtGetFileSeparator();
00244
00245 for (src = dst = s; *src;)
00246 {
00247 if (src[0] == sep && src[1] == '.')
00248 {
00249 if (src[2] == sep || ! src[2])
00250 {
00251 src += 2;
00252 continue;
00253 }
00254 else if (src[2] == '.' && src[3] == sep)
00255 {
00256 src += 3;
00257
00258 while (s < dst)
00259 {
00260 dst--;
00261 if (*dst == sep) break;
00262 }
00263
00264 continue;
00265 }
00266 }
00267
00268 if (src != dst)
00269 *dst = *src;
00270
00271 src++;
00272 dst++;
00273 }
00274
00275 if (s < dst && *(dst - 1) == sep)
00276 *(dst - 1) = '0';
00277 else if (src != dst)
00278 *dst = '0';
00279
00280 return s;
00281 }
00282
00283
00284
00294 newtRef NewtExpandPath(const char * s)
00295 {
00296 newtRefVar r = kNewtRefUnbind;
00297 char * subdir = NULL;
00298 char * dir = NULL;
00299 char * wd = NULL;
00300 char sep;
00301
00302 sep = NewtGetFileSeparator();
00303
00304 if (*s == sep)
00305 {
00306 dir = (char *)s;
00307 }
00308 #ifdef __WIN32__
00309 else if (isalpha(*s) && s[1] == ':')
00310 {
00311 dir = (char *)s;
00312 }
00313 #endif
00314 else if (*s == '')
00315 {
00316 dir = NewtGetHomeDir(s, &subdir);
00317
00318 if (subdir != NULL && subdir[1])
00319 subdir++;
00320 else
00321 subdir = NULL;
00322 }
00323 else
00324 {
00325 subdir = (char *)s;
00326 }
00327
00328 if (dir == NULL)
00329 #ifdef HAVE_GETCWD
00330 dir = wd = getcwd(NULL, 0);
00331 #else
00332 dir = "";
00333 #endif
00334
00335 if (subdir != NULL)
00336 {
00337 dir = NewtJoinPath(dir, subdir, sep);
00338 NewtRelToAbsPath(dir);
00339 }
00340
00341 r = NSSTR(dir);
00342
00343 if (subdir != NULL)
00344 free(dir);
00345
00346 if (wd != NULL)
00347 free(wd);
00348
00349 return r;
00350 }
00351
00352
00353 #pragma mark -
00354
00363 char * NewtBaseName(char * s, uint32_t len)
00364 {
00365 uint32_t base = 0;
00366 uint32_t i;
00367 char sep;
00368
00369 sep = NewtGetFileSeparator();
00370
00371 for (i = 0; i < len; i++)
00372 {
00373 if (s[i] == sep)
00374 base = i + 1;
00375 }
00376
00377 if (base < len)
00378 return (s + base);
00379 else
00380 return NULL;
00381 }
00382
00383
00384 #pragma mark -
00385
00394 newtRef NsCompileFile(newtRefArg rcvr, newtRefArg r)
00395 {
00396 char * fname;
00397
00398 if (! NewtRefIsString(r))
00399 return NewtThrow(kNErrNotAString, r);
00400
00401 fname = NewtRefToString(r);
00402
00403 return NBCCompileFile(fname, true);
00404 }
00405
00406
00407
00416 #ifdef HAVE_DLOPEN
00417
00418 newtRef NsLoadLib(newtRefArg rcvr, newtRefArg r)
00419 {
00420 char * fname;
00421 void * lib;
00422
00423 if (! NewtRefIsString(r))
00424 return NewtThrow(kNErrNotAString, r);
00425
00426 fname = NewtRefToString(r);
00427 lib = NewtDylibInstall(fname);
00428
00429 if (lib != NULL)
00430 {
00431 return NewtMakeInteger((int32_t)lib);
00432 }
00433 else
00434 {
00435 const char * errmsg;
00436
00437 errmsg = dlerror();
00438
00439 if (errmsg != NULL)
00440 {
00441 NewtFprintf(stderr,"%sn", errmsg);
00442 }
00443
00444 return NewtThrow(kNErrDylibNotOpen, r);
00445 }
00446 }
00447
00448 #endif
00449
00450
00451
00452
00461 newtRef NsLoad(newtRefArg rcvr, newtRefArg r)
00462 {
00463 newtRefVar result = kNewtRefUnbind;
00464 newtRefVar fn;
00465
00466 fn = NsCompileFile(rcvr, r);
00467
00468 if (NewtRefIsNotNIL(fn))
00469 result = NVMCall(fn, 0, NULL);
00470
00471 return result;
00472 }
00473
00474
00475
00488 newtRef NcRequire0(newtRefArg r)
00489 {
00490 newtRefVar newtlib;
00491 newtRefVar requires;
00492 newtRefVar sym;
00493 newtRefVar env;
00494
00495 if (NewtRefIsSymbol(r))
00496 {
00497 sym = r;
00498 }
00499 else
00500 {
00501 if (! NewtRefIsString(r))
00502 return NewtThrow(kNErrNotASymbol, r);
00503
00504 sym = NcMakeSymbol(r);
00505 }
00506
00507 requires = NcGetGlobalVar(NSSYM0(requires));
00508
00509 if (! NewtRefIsFrame(requires))
00510 {
00511 requires = NcMakeFrame();
00512 NcDefGlobalVar(NSSYM0(requires), requires);
00513 }
00514
00515 if (NewtHasSlot(requires, sym))
00516 return kNewtRefNIL;
00517
00518 {
00519 newtRefVar initObj[] = {kNewtRefUnbind, kNewtRefUnbind};
00520 file_ext_t lib_exts[] = {
00521
00522 #ifdef HAVE_DLOPEN
00523
00524
00525
00526
00527
00528 {NSSTR(__DYLIBSUFFIX__), typeDylib},
00529 #endif
00530
00531 {NSSTR(".newt"), typeScript},
00532 };
00533
00534 newtRefVar lib;
00535 newtRefVar dir;
00536 newtRefVar patharray;
00537 newtRefVar path;
00538 uint32_t len;
00539 uint32_t i;
00540 uint32_t j;
00541
00542 patharray = NewtMakeArray2(kNewtRefNIL, sizeof(initObj) / sizeof(newtRefVar), initObj);
00543
00544 env = NcGetGlobalVar(NSSYM0(_ENV_));
00545 newtlib = NcGetVariable(env, NSSYM0(NEWTLIB));
00546
00547 if (NewtRefIsNIL(newtlib))
00548 {
00549 newtRefVar initPath[] = {NSSTR("."), NcGetGlobalVar(NSSYM0(_EXEDIR_))};
00550
00551 newtlib = NewtMakeArray2(kNewtRefNIL, sizeof(initPath) / sizeof(newtRefVar), initPath);
00552 }
00553
00554 len = NewtLength(newtlib);
00555
00556 for (i = 0; i < len; i++)
00557 {
00558 dir = NewtGetArraySlot(newtlib, i);
00559 NewtSetArraySlot(patharray, 0, NcJoinPath(dir, r));
00560
00561 for (j = 0; j < sizeof(lib_exts) / sizeof(lib_exts[0]); j++)
00562 {
00563 NewtSetArraySlot(patharray, 1, lib_exts[j].ext);
00564 path = NcStringer(patharray);
00565
00566 if (NewtFileExists(NewtRefToString(path)))
00567 {
00568 #ifdef HAVE_DLOPEN
00569 if (lib_exts[j].type == typeDylib)
00570 {
00571 lib = NcLoadLib(path);
00572 NcSetSlot(requires, sym, lib);
00573 }
00574 else
00575 #endif
00576 {
00577 NcSetSlot(requires, sym, path);
00578 NcLoad(path);
00579 }
00580
00581 return sym;
00582 }
00583 }
00584 }
00585 }
00586
00587 return kNewtRefUnbind;
00588 }
00589
00590
00591
00604 newtRef NsRequire(newtRefArg rcvr, newtRefArg r)
00605 {
00606 newtRefVar result;
00607
00608 result = NcRequire0(r);
00609
00610 if (result == kNewtRefUnbind)
00611 NewtThrow(kNErrFileNotFound, r);
00612
00613 return result;
00614 }
00615
00616
00617 #pragma mark -
00618
00630 newtRef NsFileExists(newtRefArg rcvr, newtRefArg r)
00631 {
00632 if (! NewtRefIsString(r))
00633 return NewtThrow(kNErrNotAString, r);
00634
00635 return NewtMakeBoolean(NewtFileExists(NewtRefToString(r)));
00636 }
00637
00638
00639 #pragma mark -
00640
00649 newtRef NsDirName(newtRefArg rcvr, newtRefArg r)
00650 {
00651 char * base;
00652 char * s;
00653 char sep;
00654
00655 if (! NewtRefIsString(r))
00656 return NewtThrow(kNErrNotAString, r);
00657
00658 s = NewtRefToString(r);
00659 base = NewtBaseName(s, NewtStringLength(r));
00660 sep = NewtGetFileSeparator();
00661
00662 if (base != NULL && s < base)
00663 {
00664 if (base - 1 != s && *(base - 1) == sep)
00665 base--;
00666
00667 if (s < base)
00668 return NewtMakeString2(s, base - s, false);
00669 }
00670
00671 return NSSTR(".");
00672 }
00673
00674
00675
00686 newtRef NsBaseName(newtRefArg rcvr, newtRefArg r)
00687 {
00688 char * base;
00689
00690 if (! NewtRefIsString(r))
00691 return NewtThrow(kNErrNotAString, r);
00692
00693 base = NewtBaseName(NewtRefToString(r), NewtStringLength(r));
00694
00695 if (base != NULL)
00696 return NSSTR(base);
00697 else
00698 return r;
00699 }
00700
00701
00702
00712 newtRef NsJoinPath(newtRefArg rcvr, newtRefArg r1, newtRefArg r2)
00713 {
00714 char sep = NewtGetFileSeparator();
00715 newtRefVar initObj[] = {r1, NewtMakeCharacter(sep), r2};
00716 newtRefVar r;
00717
00718 r = NewtMakeArray2(kNewtRefNIL, sizeof(initObj) / sizeof(newtRefVar), initObj);
00719
00720 return NcStringer(r);
00721 }
00722
00723
00724
00736 newtRef NsExpandPath(newtRefArg rcvr, newtRefArg r)
00737 {
00738 if (! NewtRefIsString(r))
00739 return NewtThrow(kNErrNotAString, r);
00740
00741 return NewtExpandPath(NewtRefToString(r));
00742 }
00743