static int searcher_Croot(lua_State *L) { const wchar_t *filename; const char *name = luaL_checkstring(L, 1); const char *p = strchr(name, '.'); int stat; if(p == NULL) return 0; /* is root */ lua_pushlstring(L, name, p - name); filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); if(filename == NULL) return 1; /* root not found */ if((stat = loadfunc(L, filename, name)) != 0) { if(stat != ERRFUNC) return checkload(L, 0, filename); /* real error */ else /* open function not found */ { push_utf8_string(L, filename, -1); lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, name, lua_tostring(L, -1)); return 1; } } push_utf8_string(L, filename, -1); /* will be 2nd argument to module */ return 2; }
int ustring_SearchPath(lua_State *L) { const wchar_t* lpPath = opt_utf8_string(L, 1, NULL); const wchar_t* lpFileName = check_utf8_string(L, 2, NULL); const wchar_t* lpExtension = opt_utf8_string(L, 3, NULL); wchar_t buf[2048]; wchar_t* lpFilePart; DWORD result = SearchPathW( lpPath, // address of search path lpFileName, // address of filename lpExtension, // address of extension sizeof(buf)/sizeof(wchar_t), // size, in characters, of buffer buf, // address of buffer for found filename &lpFilePart // address of pointer to file component ); if(result > 0) { push_utf8_string(L, buf, -1); push_utf8_string(L, lpFilePart, -1); return 2; } return 0; }
static const wchar_t *findfile (lua_State *L, const char *name, const char *pname) { const wchar_t *path; const wchar_t *wname; lua_pushstring(L, name); wname = utf8_to_utf16(L, -1, NULL); /* `name' is encoded in UTF-8 */ wname = LF_Gsub(L, wname, L".", L"\\"); lua_getfield(L, LUA_ENVIRONINDEX, pname); if (lua_tostring(L, -1) == NULL) luaL_error(L, LUA_QL("package.%s") " must be a string", pname); path = utf8_to_utf16(L, -1, NULL); if (path == NULL) luaL_error(L, LUA_QL("package.%s") " contains invalid UTF-8", pname); lua_pushliteral(L, ""); /* error accumulator */ while ((path = pushnexttemplate(L, path)) != NULL) { const wchar_t *filename; filename = LF_Gsub(L, (const wchar_t*)lua_tostring(L, -1), LUA_PATH_MARK, wname); lua_remove(L, -2); /* remove path template */ if (readable(filename)) /* does file exist and is readable? */ return filename; /* return that file name */ push_utf8_string(L, filename, -1); lua_pushfstring(L, "\n\tno file " LUA_QS, lua_tostring(L, -1)); lua_remove(L, -2); /* remove UTF-8 file name */ lua_remove(L, -2); /* remove UTF-16 file name */ lua_concat(L, 2); /* add entry to possible error message */ } return NULL; /* not found */ }
static const wchar_t *searchpath (lua_State *L, const char *name, const wchar_t *path, const wchar_t *sep, const wchar_t *dirsep) { const wchar_t *wname; luaL_Buffer msg; /* to build error message */ luaL_buffinit(L, &msg); lua_pushstring(L, name); wname = utf8_to_utf16(L, -1, NULL); /* `name' is encoded in UTF-8 */ if (*sep != 0) /* non-empty separator? */ wname = LF_Gsub(L, wname, sep, dirsep); /* replace it by 'dirsep' */ while ((path = pushnexttemplate(L, path)) != NULL) { const wchar_t *filename = LF_Gsub(L, (const wchar_t*)lua_tostring(L, -1), LUA_PATH_MARK, wname); lua_remove(L, -2); /* remove path template */ if (readable(filename)) /* does file exist and is readable? */ return filename; /* return that file name */ push_utf8_string(L, filename, -1); lua_pushfstring(L, "\n\tno file " LUA_QS, lua_tostring(L, -1)); lua_remove(L, -2); /* remove UTF-8 file name */ lua_remove(L, -2); /* remove UTF-16 file name */ luaL_addvalue(&msg); /* concatenate error msg. entry */ } luaL_pushresult(&msg); /* create error message */ return NULL; /* not found */ }
static int pushresult(lua_State *L, int stat, const wchar_t *filename) { int en = errno; /* calls to Lua API may change this value */ if(stat) { lua_pushboolean(L, 1); return 1; } else { lua_pushnil(L); if(filename) { const char *utf8name = push_utf8_string(L, filename, -1); lua_pushfstring(L, "%s: %s", utf8name, strerror(en)); lua_remove(L, -2); } else lua_pushfstring(L, "%s", strerror(en)); lua_pushinteger(L, en); return 3; } }
int ustring_Utf16ToUtf8(lua_State *L) { size_t len; const wchar_t *ws = (const wchar_t*) luaL_checklstring(L, 1, &len); push_utf8_string(L, ws, len/sizeof(wchar_t)); return 1; }
int _regex_gmatch_closure(lua_State *L, int is_wide) { TFarRegex* fr = (TFarRegex*)lua_touserdata(L, lua_upvalueindex(1)); struct RegExpSearch* pData = (struct RegExpSearch*)lua_touserdata(L, lua_upvalueindex(2)); FARAPIREGEXPCONTROL RegExpControl = GetRegExpControl(L); if ((pData->Position <= pData->Length) && RegExpControl(fr->hnd, RECTL_SEARCHEX, 0, pData)) { int i, skip = pData->Count>1 ? 1 : 0; for(i=skip; i<pData->Count; i++) { if (pData->Match[i].start >= 0) { if (is_wide) push_utf16_string(L, pData->Text+pData->Match[i].start, pData->Match[i].end-pData->Match[i].start); else push_utf8_string(L, pData->Text+pData->Match[i].start, pData->Match[i].end-pData->Match[i].start); } else lua_pushboolean(L, 0); } if (pData->Position < pData->Match[0].end) pData->Position = pData->Match[0].end; else pData->Position++; return (int)pData->Count - skip; } return lua_pushnil(L), 1; }
int ustring_GetCurrentDir (lua_State *L) { wchar_t buf[256]; DWORD num = GetCurrentDirectoryW(ARRSIZE(buf), buf); if(num) { if(num < ARRSIZE(buf)) push_utf8_string(L, buf, -1); else { wchar_t* alloc = (wchar_t*) malloc(num * sizeof(wchar_t)); num = GetCurrentDirectoryW(num, alloc); if(num) push_utf8_string(L, alloc, -1); free(alloc); } } return num ? 1 : SysErrorReturn(L); }
int ustring_OemToUtf8(lua_State *L) { size_t len; wchar_t* buf; (void) luaL_checklstring(L, 1, &len); buf = oem_to_utf16(L, 1, &len); push_utf8_string(L, buf, len); return 1; }
static int checkload (lua_State *L, int stat, const wchar_t *filename) { push_utf8_string(L, filename, -1); /* will be 2nd argument to module */ if (stat) { /* module loaded successfully? */ return 2; /* return open function and file name */ } else return luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", lua_tostring(L, 1), lua_tostring(L, -1), lua_tostring(L, -2)); }
int rx_find_match(lua_State *L, int op_find, int is_function, int is_wide) { size_t len; FARAPIREGEXPCONTROL RegExpControl = GetRegExpControl(L); TFarRegex* fr; struct RegExpSearch data; memset(&data, 0, sizeof(data)); if (is_function) { if (is_wide) data.Text = check_utf16_string(L, 1, &len); else data.Text = check_utf8_string(L, 1, &len); fr = push_far_regex(L, RegExpControl, check_regex_pattern(L, 2, 4)); lua_replace(L, 2); } else { fr = CheckFarRegex(L, 1); if (is_wide) data.Text = check_utf16_string(L, 2, &len); else data.Text = check_utf8_string(L, 2, &len); } data.Length = len; data.Position = luaL_optinteger(L, 3, 1); if (data.Position > 0 && --data.Position > data.Length) data.Position = data.Length; if (data.Position < 0 && (data.Position += data.Length) < 0) data.Position = 0; data.Count = RegExpControl(fr->hnd, RECTL_BRACKETSCOUNT, 0, 0); data.Match = (struct RegExpMatch*)lua_newuserdata(L, data.Count*sizeof(struct RegExpMatch)); if (RegExpControl(fr->hnd, RECTL_SEARCHEX, 0, &data)) { int i, skip; if (op_find) { lua_pushinteger(L, data.Match[0].start+1); lua_pushinteger(L, data.Match[0].end); } skip = (op_find || data.Count>1) ? 1 : 0; for(i=skip; i<data.Count; i++) { if (data.Match[i].start >= 0) { if (is_wide) push_utf16_string(L, data.Text+data.Match[i].start, data.Match[i].end-data.Match[i].start); else push_utf8_string(L, data.Text+data.Match[i].start, data.Match[i].end-data.Match[i].start); } else lua_pushboolean(L, 0); } return (op_find ? 2:0) + (int)data.Count - skip; } return lua_pushnil(L), 1; }
// This function was initially taken from Lua 5.0.2 (loadlib.c) void pusherrorcode(lua_State *L, int error) { wchar_t buffer[256]; const int BUFSZ = ARRSIZE(buffer); int num = FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, error, 0, buffer, BUFSZ, 0); if(num) push_utf8_string(L, buffer, num); else lua_pushfstring(L, "system error %d\n", error); }
// os.getenv does not always work correctly, hence the following. static int win_GetEnv(lua_State *L) { const wchar_t* name = check_utf8_string(L, 1, NULL); wchar_t buf[256]; DWORD res = GetEnvironmentVariableW(name, buf, ARRSIZE(buf)); lua_pushnil(L); if(res) { if(res < ARRSIZE(buf)) push_utf8_string(L, buf, -1); else { DWORD size = res + 1; wchar_t *p = (wchar_t*)lua_newuserdata(L, size * sizeof(wchar_t)); res = GetEnvironmentVariableW(name, p, size); if(res > 0 && res < size) push_utf8_string(L, p, -1); } } return 1; }
static void setpath (lua_State *L, const char *fieldname, const wchar_t *envname, const wchar_t *def) { const wchar_t *path = _wgetenv(envname); if (path == NULL) /* no environment variable? */ lua_pushlstring(L, (const char*)def, sizeof(wchar_t)*(1+wcslen(def))); /* use default */ else { /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ path = LF_Gsub(L, path, LUA_PATHSEP LUA_PATHSEP, LUA_PATHSEP AUXMARK LUA_PATHSEP); LF_Gsub(L, path, AUXMARK, def); lua_remove(L, -2); } setprogdir(L); push_utf8_string(L, (const wchar_t*)lua_tostring(L, -1), -1); lua_remove(L, -2); lua_setfield(L, -2, fieldname); }
LUAMOD_API int luaopen_upackage(lua_State *L) { int i; /* create new type _LOADLIB */ luaL_newmetatable(L, "_LOADLIB"); lua_pushcfunction(L, gctm); lua_setfield(L, -2, "__gc"); /* create `package' table */ luaL_newlib(L, pk_funcs); /* create 'searchers' table */ lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); /* fill it with pre-defined searchers */ for(i=0; searchers[i] != NULL; i++) { lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ lua_pushcclosure(L, searchers[i], 1); lua_rawseti(L, -2, i+1); } #if defined(LUA_COMPAT_LOADERS) lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ #endif lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ /* set field 'path' */ setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); /* set field 'cpath' */ setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); /* store config information */ push_utf8_string(L, LUA_DIRSEP L"\n" LUA_PATH_SEP L"\n" LUA_PATH_MARK L"\n" LUA_EXEC_DIR L"\n" LUA_IGMARK L"\n", -1); lua_setfield(L, -2, "config"); /* set field `loaded' */ luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); lua_setfield(L, -2, "loaded"); /* set field `preload' */ luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); lua_setfield(L, -2, "preload"); lua_pushglobaltable(L); lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ lua_pop(L, 1); /* pop global table */ return 1; /* return 'package' table */ }
int ustring_SHGetFolderPath(lua_State *L) { wchar_t pszPath[MAX_PATH]; int nFolder = (int)luaL_checkinteger(L, 1); DWORD dwFlags = (DWORD)luaL_optnumber(L, 2, 0); HRESULT result = SHGetFolderPathW( NULL, // __in HWND hwndOwner, nFolder, // __in int nFolder, NULL, // __in HANDLE hToken, dwFlags, // __in DWORD dwFlags, pszPath); // __out LPTSTR pszPath); if(result == S_OK) push_utf8_string(L, pszPath, -1); else lua_pushnil(L); return 1; }
static int io_open(lua_State *L) { const wchar_t *filename = check_utf8_string(L, 1, NULL); const wchar_t *mode = opt_utf8_string(L, 2, L"r"); FILE **pf = newfile(L); int i = 0; /* check whether 'mode' matches '[rwa]%+?b?' */ if(!(mode[i] != L'\0' && wcschr(L"rwa", mode[i++]) != NULL && (mode[i] != L'+' || ++i) && /* skip if char is '+' */ (mode[i] != L'b' || ++i) && /* skip if char is 'b' */ (mode[i] == L'\0'))) { push_utf8_string(L, mode, -1); return luaL_error(L, "invalid mode " LUA_QS " (should match " LUA_QL("[rwa]%%+?b?") ")", lua_tostring(L, -1)); } *pf = _wfopen(filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; }
// Result = EnumRegValue (Root, Key, Index [, samDesired]) // Root: [string], one of "HKLM", "HKCC", "HKCR", "HKCU", "HKU" // Key: registry key, [string] // Index: integer // samDesired: access mask, [flag] ("KEY_WOW64_32KEY" or "KEY_WOW64_64KEY"; the default is 0) // Returns: // Result: string or nil static int win_EnumRegValue(lua_State *L) { HKEY hKey; LONG ret; HKEY hRoot = CheckHKey(L, 1); wchar_t* Key = (wchar_t*)check_utf8_string(L, 2, NULL); DWORD dwIndex = (DWORD)luaL_checkinteger(L, 3); REGSAM samDesired = (REGSAM) OptFlags(L, 4, 0) | KEY_QUERY_VALUE; wchar_t Name[512]; DWORD NameSize = ARRSIZE(Name); DWORD Type; if(RegOpenKeyExW(hRoot, Key, 0, samDesired, &hKey)!=ERROR_SUCCESS) { lua_pushnil(L); lua_pushstring(L, "RegOpenKeyExW failed."); return 2; } ret = RegEnumValue( hKey, // handle of key to query dwIndex, // index of value to query Name, // address of buffer for value string &NameSize, // address for size of value buffer NULL, // reserved &Type, // address of buffer for type code NULL, // address of buffer for value data NULL // address for size of data buffer ); RegCloseKey(hKey); if (ret == ERROR_SUCCESS) push_utf8_string(L, Name, NameSize); else lua_pushnil(L); return 1; }
LUALIB_API int luaopen_upackage (lua_State *L) { int i; /* create new type _LOADLIB */ luaL_newmetatable(L, "_LOADLIB"); lua_pushcfunction(L, gctm); lua_setfield(L, -2, "__gc"); /* create `package' table */ luaL_register(L, LUA_LOADLIBNAME, pk_funcs); #if defined(LUA_COMPAT_LOADLIB) lua_getfield(L, -1, "loadlib"); lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); #endif lua_pushvalue(L, -1); lua_replace(L, LUA_ENVIRONINDEX); /* create `loaders' table */ lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); /* fill it with pre-defined loaders */ for (i=0; loaders[i] != NULL; i++) { lua_pushcfunction(L, loaders[i]); lua_rawseti(L, -2, i+1); } lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ /* store config information */ push_utf8_string(L, L"\\" L"\n" LUA_PATHSEP L"\n" LUA_PATH_MARK L"\n" LUA_EXECDIR L"\n" LUA_IGMARK, -1); lua_setfield(L, -2, "config"); /* set field `loaded' */ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); lua_setfield(L, -2, "loaded"); /* set field `preload' */ lua_newtable(L); lua_setfield(L, -2, "preload"); lua_pushvalue(L, LUA_GLOBALSINDEX); luaL_register(L, NULL, ll_funcs); /* open lib into global table */ lua_pop(L, 1); return 1; /* return 'package' table */ }
// Result = EnumRegKey (Root, Key, Index [, samDesired]) // Root: [string], one of "HKLM", "HKCC", "HKCR", "HKCU", "HKU" // Key: registry key, [string] // Index: integer // samDesired: access mask, [flag] ("KEY_WOW64_32KEY" or "KEY_WOW64_64KEY"; the default is 0) // Returns: // Result: string or nil static int win_EnumRegKey(lua_State *L) { HKEY hKey; LONG ret; HKEY hRoot = CheckHKey(L, 1); wchar_t* Key = (wchar_t*)check_utf8_string(L, 2, NULL); DWORD dwIndex = (DWORD)luaL_checkinteger(L, 3); REGSAM samDesired = (REGSAM) OptFlags(L, 4, 0) | KEY_ENUMERATE_SUB_KEYS; wchar_t Name[512]; DWORD NameSize = ARRSIZE(Name); FILETIME LastWriteTime; if(RegOpenKeyExW(hRoot, Key, 0, samDesired, &hKey)!=ERROR_SUCCESS) { lua_pushnil(L); lua_pushstring(L, "RegOpenKeyExW failed."); return 2; } ret = RegEnumKeyEx( hKey, // handle of key to enumerate dwIndex, // index of subkey to enumerate Name, // address of buffer for subkey name &NameSize, // address for size of subkey buffer NULL, // reserved NULL, // address of buffer for class string NULL, // address for size of class buffer &LastWriteTime); // address for time key last written to RegCloseKey(hKey); if (ret == ERROR_SUCCESS) push_utf8_string(L, Name, NameSize); else lua_pushnil(L); return 1; }
// ValueData, DataType = GetRegKey (Root, Key, ValueName [, samDesired]) // Root: [string], one of "HKLM", "HKCC", "HKCR", "HKCU", "HKU" // Key: registry key, [string] // ValueName: registry value name, [string] // samDesired: access mask, [flag] ("KEY_WOW64_32KEY" or "KEY_WOW64_64KEY"; the default is 0) // Returns: // ValueData: registry value data, [string | number | lstring] // DataType: "string", "expandstring", "multistring", "dword" or "binary", [string] static int win_GetRegKey(lua_State *L) { HKEY hKey; DWORD datatype, datasize; char *data; LONG ret; HKEY hRoot = CheckHKey(L, 1); wchar_t* Key = (wchar_t*)check_utf8_string(L, 2, NULL); const wchar_t* ValueName = check_utf8_string(L, 3, NULL); REGSAM samDesired = (REGSAM) OptFlags(L, 4, 0); hKey = OpenRegKey(hRoot, Key, samDesired); if(hKey == NULL) { lua_pushnil(L); lua_pushstring(L, "OpenRegKey failed."); return 2; } RegQueryValueExW(hKey, ValueName, NULL, &datatype, NULL, &datasize); data = (char*) malloc(datasize); ret = RegQueryValueExW(hKey, ValueName, NULL, &datatype, (BYTE*)data, &datasize); RegCloseKey(hKey); if(ret != ERROR_SUCCESS) { lua_pushnil(L); lua_pushstring(L, "RegQueryValueEx failed."); } else { switch(datatype) { case REG_BINARY: lua_pushlstring(L, data, datasize); lua_pushstring(L, "binary"); break; case REG_DWORD: lua_pushinteger(L, *(int*)data); lua_pushstring(L, "dword"); break; case REG_SZ: push_utf8_string(L, (wchar_t*)data, -1); lua_pushstring(L, "string"); break; case REG_EXPAND_SZ: push_utf8_string(L, (wchar_t*)data, -1); lua_pushstring(L, "expandstring"); break; case REG_MULTI_SZ: push_utf8_string(L, (wchar_t*)data, datasize/sizeof(wchar_t)); lua_pushstring(L, "multistring"); break; default: lua_pushnil(L); lua_pushstring(L, "unsupported value type"); break; } } free(data); return 2; }
void PutWStrToArray(lua_State *L, int key, const wchar_t* str, intptr_t numchars) { lua_pushinteger(L, key); push_utf8_string(L, str, numchars); lua_settable(L, -3); }
void PutWStrToTable(lua_State *L, const char* key, const wchar_t* str, intptr_t numchars) { push_utf8_string(L, str, numchars); lua_setfield(L, -2, key); }
static void fileerror(lua_State *L, int arg, const wchar_t *filename) { const char* utf8name = push_utf8_string(L, filename, -1); lua_pushfstring(L, "%s: %s", utf8name, strerror(errno)); luaL_argerror(L, arg, lua_tostring(L, -1)); }
static void loaderror (lua_State *L, const wchar_t *filename) { const char* utf8name = push_utf8_string (L, filename, -1); luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", lua_tostring(L, 1), utf8name, lua_tostring(L, -2)); }
int rx_gsub (lua_State *L, int is_function, int is_wide) { size_t len, flen; TFarRegex* fr; FARAPIREGEXPCONTROL RegExpControl = GetRegExpControl(L); const wchar_t *s, *f; int max_rep_capture, ftype, n, matches, reps; luaL_Buffer out; struct RegExpSearch data; memset(&data, 0, sizeof(data)); if (is_function) { if (is_wide) data.Text = check_utf16_string(L, 1, &len); else data.Text = check_utf8_string(L, 1, &len); fr = push_far_regex(L, RegExpControl, check_regex_pattern(L, 2, 5)); lua_replace(L, 2); } else { fr = CheckFarRegex(L, 1); if (is_wide) data.Text = check_utf16_string(L, 2, &len); else data.Text = check_utf8_string(L, 2, &len); } data.Length = len; s = data.Text; f = NULL; flen = 0; max_rep_capture = 0; ftype = lua_type(L, 3); if (ftype == LUA_TSTRING) { const wchar_t* p; f = check_utf8_string(L, 3, &flen); for (p=f; *p; p++) { if (*p == L'%') { int n, ch; if ((ch = *++p) == 0) break; n = (ch >= L'0' && ch <= L'9') ? ch - L'0' : (ch >= L'A' && ch <= L'Z') ? ch - L'A' + 10 : (ch >= L'a' && ch <= L'z') ? ch - L'a' + 10 : -1; if (max_rep_capture < n) max_rep_capture = n; } } } else if (ftype != LUA_TTABLE && ftype != LUA_TFUNCTION) luaL_argerror(L, 3, "string or table or function"); if (lua_isnoneornil(L, 4)) n = -1; else { n = (int)luaL_checkinteger(L, 4); if (n < 0) n = 0; } lua_settop(L, 3); data.Count = RegExpControl(fr->hnd, RECTL_BRACKETSCOUNT, 0, 0); if ( (ftype == LUA_TSTRING) && !(max_rep_capture == 1 && data.Count == 1) && (data.Count <= max_rep_capture)) luaL_error(L, "replace string: invalid capture index"); data.Match = (struct RegExpMatch*)lua_newuserdata(L, data.Count*sizeof(struct RegExpMatch)); data.Match[0].end = -1; matches = reps = 0; luaL_buffinit(L, &out); while (n < 0 || reps < n) { int rep; intptr_t from, to; intptr_t prev_end = data.Match[0].end; if (!RegExpControl(fr->hnd, RECTL_SEARCHEX, 0, &data)) break; if (data.Match[0].end == prev_end) { if (data.Position < data.Length) { luaL_addlstring(&out, (const char*)(s+data.Position), sizeof(wchar_t)); data.Position++; continue; } break; } matches++; rep = 0; from = data.Match[0].start; to = data.Match[0].end; luaL_addlstring(&out, (const char*)(s + data.Position), (from - data.Position) * sizeof(wchar_t)); if (ftype == LUA_TSTRING) { size_t i, start = 0; for (i=0; i<flen; i++) { if (f[i] == L'%') { if (++i < flen) { int ch = f[i]; int n = (ch >= L'0' && ch <= L'9') ? ch - L'0' : (ch >= L'A' && ch <= L'Z') ? ch - L'A' + 10 : (ch >= L'a' && ch <= L'z') ? ch - L'a' + 10 : -1; if (n >= 0) { if (n==1 && data.Count==1) n = 0; luaL_addlstring(&out, (const char*)(f+start), (i-1-start)*sizeof(wchar_t)); if (data.Match[n].start >= 0) { luaL_addlstring(&out, (const char*)(s + data.Match[n].start), (data.Match[n].end - data.Match[n].start) * sizeof(wchar_t)); } } else { // delete the percent sign luaL_addlstring(&out, (const char*)(f+start), (i-1-start)*sizeof(wchar_t)); luaL_addlstring(&out, (const char*)(f+i), sizeof(wchar_t)); } start = i+1; } else { luaL_addlstring(&out, (const char*)(f+start), (i-1-start)*sizeof(wchar_t)); start = flen; break; } } } rep++; luaL_addlstring(&out, (const char*)(f+start), (flen-start)*sizeof(wchar_t)); } else if (ftype == LUA_TTABLE) { int n = data.Count==1 ? 0:1; if (data.Match[n].start >= 0) { if (is_wide) push_utf16_string(L, s + data.Match[n].start, (data.Match[n].end - data.Match[n].start)); else push_utf8_string(L, s + data.Match[n].start, (data.Match[n].end - data.Match[n].start)); lua_gettable(L, 3); if (lua_isstring(L, -1)) { if (!is_wide) { size_t len; const wchar_t* ws = check_utf8_string(L, -1, &len); lua_pushlstring(L, (const char*)ws, len*sizeof(wchar_t)); lua_remove(L, -2); } luaL_addvalue(&out); rep++; } else if (lua_toboolean(L,-1)) luaL_error(L, "invalid replacement type"); else lua_pop(L, 1); } } else { // if (ftype == LUA_TFUNCTION) intptr_t i, skip = data.Count==1 ? 0:1; lua_checkstack(L, (int)(data.Count+1-skip)); lua_pushvalue(L, 3); for (i=skip; i<data.Count; i++) { if (data.Match[i].start >= 0) { if (is_wide) push_utf16_string(L, s + data.Match[i].start, (data.Match[i].end - data.Match[i].start)); else push_utf8_string(L, s + data.Match[i].start, (data.Match[i].end - data.Match[i].start)); } else lua_pushboolean(L, 0); } if (lua_pcall(L, (int)(data.Count-skip), 1, 0) == 0) { if (lua_isstring(L, -1)) { if (!is_wide) { size_t len; const wchar_t* ws = check_utf8_string(L, -1, &len); lua_pushlstring(L, (const char*)ws, len*sizeof(wchar_t)); lua_remove(L, -2); } luaL_addvalue(&out); rep++; } else if (lua_toboolean(L,-1)) luaL_error(L, "invalid return type"); else lua_pop(L, 1); } else luaL_error(L, lua_tostring(L, -1)); } if (rep) reps++; else luaL_addlstring(&out, (const char*)(s+from), (to-from)*sizeof(wchar_t)); if (data.Position < to) data.Position = to; else if (data.Position < data.Length) { luaL_addlstring(&out, (const char*)(s + data.Position), sizeof(wchar_t)); data.Position++; } else break; } luaL_addlstring(&out, (const char*)(s + data.Position), (data.Length - data.Position) * sizeof(wchar_t)); luaL_pushresult(&out); if (!is_wide) { push_utf8_string(L, (const wchar_t*)lua_tostring(L, -1), lua_objlen(L, -1) / sizeof(wchar_t)); } lua_pushinteger(L, matches); lua_pushinteger(L, reps); return 3; }