github.com/xyproto/gopher-lua@v1.0.2/loadlib.go (about) 1 package lua 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 ) 9 10 /* load lib {{{ */ 11 12 var loLoaders = []LGFunction{loLoaderPreload, loLoaderLua} 13 14 func loGetPath(env string, defpath string) string { 15 path := os.Getenv(env) 16 if len(path) == 0 { 17 path = defpath 18 } 19 path = strings.Replace(path, ";;", ";"+defpath+";", -1) 20 if os.PathSeparator != '/' { 21 dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 22 if err != nil { 23 panic(err) 24 } 25 path = strings.Replace(path, "!", dir, -1) 26 } 27 return path 28 } 29 30 func loFindFile(L *LState, name, pname string) (string, string) { 31 name = strings.Replace(name, ".", string(os.PathSeparator), -1) 32 lv := L.GetField(L.GetField(L.Get(EnvironIndex), "package"), pname) 33 path, ok := lv.(LString) 34 if !ok { 35 L.RaiseError("package.%s must be a string", pname) 36 } 37 messages := []string{} 38 for _, pattern := range strings.Split(string(path), ";") { 39 luapath := strings.Replace(pattern, "?", name, -1) 40 if _, err := os.Stat(luapath); err == nil { 41 return luapath, "" 42 } else { 43 messages = append(messages, err.Error()) 44 } 45 } 46 return "", strings.Join(messages, "\n\t") 47 } 48 49 func OpenPackage(L *LState) int { 50 packagemod := L.RegisterModule(LoadLibName, loFuncs) 51 52 L.SetField(packagemod, "preload", L.NewTable()) 53 54 loaders := L.CreateTable(len(loLoaders), 0) 55 for i, loader := range loLoaders { 56 L.RawSetInt(loaders, i+1, L.NewFunction(loader)) 57 } 58 L.SetField(packagemod, "loaders", loaders) 59 L.SetField(L.Get(RegistryIndex), "_LOADERS", loaders) 60 61 loaded := L.NewTable() 62 L.SetField(packagemod, "loaded", loaded) 63 L.SetField(L.Get(RegistryIndex), "_LOADED", loaded) 64 65 L.SetField(packagemod, "path", LString(loGetPath(LuaPath, LuaPathDefault))) 66 L.SetField(packagemod, "cpath", emptyLString) 67 68 L.SetField(packagemod, "config", LString(LuaDirSep+"\n"+LuaPathSep+ 69 "\n"+LuaPathMark+"\n"+LuaExecDir+"\n"+LuaIgMark+"\n")) 70 71 L.Push(packagemod) 72 return 1 73 } 74 75 var loFuncs = map[string]LGFunction{ 76 "loadlib": loLoadLib, 77 "seeall": loSeeAll, 78 } 79 80 func loLoaderPreload(L *LState) int { 81 name := L.CheckString(1) 82 preload := L.GetField(L.GetField(L.Get(EnvironIndex), "package"), "preload") 83 if _, ok := preload.(*LTable); !ok { 84 L.RaiseError("package.preload must be a table") 85 } 86 lv := L.GetField(preload, name) 87 if lv == LNil { 88 L.Push(LString(fmt.Sprintf("no field package.preload['%s']", name))) 89 return 1 90 } 91 L.Push(lv) 92 return 1 93 } 94 95 func loLoaderLua(L *LState) int { 96 name := L.CheckString(1) 97 path, msg := loFindFile(L, name, "path") 98 if len(path) == 0 { 99 L.Push(LString(msg)) 100 return 1 101 } 102 fn, err1 := L.LoadFile(path) 103 if err1 != nil { 104 L.RaiseError(err1.Error()) 105 } 106 L.Push(fn) 107 return 1 108 } 109 110 func loLoadLib(L *LState) int { 111 L.RaiseError("loadlib is not supported") 112 return 0 113 } 114 115 func loSeeAll(L *LState) int { 116 mod := L.CheckTable(1) 117 mt := L.GetMetatable(mod) 118 if mt == LNil { 119 mt = L.CreateTable(0, 1) 120 L.SetMetatable(mod, mt) 121 } 122 L.SetField(mt, "__index", L.Get(GlobalsIndex)) 123 return 0 124 } 125 126 /* }}} */ 127 128 //