NewtFile.c

説明を見る。
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 /* HAVE_GETPWNAM */
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 /* HAVE_DLOPEN */
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 {   // UNIX の場合
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 {   // Windows の場合
00187     return NULL;
00188 }
00189 
00190 #endif /* HAVE_GETPWNAM */
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 /* HAVE_GETCWD */
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 /* HAVE_DLOPEN */
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             {NSSTR(".dylib"),           typeDylib},
00525             {NSSTR(".so"),              typeDylib},
00526             {NSSTR(".dll"),             typeDylib},
00527 */
00528             {NSSTR(__DYLIBSUFFIX__),    typeDylib},
00529 #endif /* HAVE_DLOPEN */
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 /* HAVE_DLOPEN */
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 

NEWT/0に対してThu Nov 23 16:50:42 2006に生成されました。  doxygen 1.5.0