Mercurial
comparison third_party/luajit/src/lib_os.c @ 186:8cf4ec5e2191 hg-web
Fixed merge conflict.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 23 Jan 2026 22:38:59 -0800 |
| parents | 94705b5986b3 |
| children |
comparison
equal
deleted
inserted
replaced
| 176:fed99fc04e12 | 186:8cf4ec5e2191 |
|---|---|
| 1 /* | |
| 2 ** OS library. | |
| 3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h | |
| 4 ** | |
| 5 ** Major portions taken verbatim or adapted from the Lua interpreter. | |
| 6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h | |
| 7 */ | |
| 8 | |
| 9 #include <errno.h> | |
| 10 #include <time.h> | |
| 11 | |
| 12 #define lib_os_c | |
| 13 #define LUA_LIB | |
| 14 | |
| 15 #include "lua.h" | |
| 16 #include "lauxlib.h" | |
| 17 #include "lualib.h" | |
| 18 | |
| 19 #include "lj_obj.h" | |
| 20 #include "lj_gc.h" | |
| 21 #include "lj_err.h" | |
| 22 #include "lj_buf.h" | |
| 23 #include "lj_str.h" | |
| 24 #include "lj_lib.h" | |
| 25 | |
| 26 #if LJ_TARGET_POSIX | |
| 27 #include <unistd.h> | |
| 28 #else | |
| 29 #include <stdio.h> | |
| 30 #endif | |
| 31 | |
| 32 #if !LJ_TARGET_PSVITA | |
| 33 #include <locale.h> | |
| 34 #endif | |
| 35 | |
| 36 /* ------------------------------------------------------------------------ */ | |
| 37 | |
| 38 #define LJLIB_MODULE_os | |
| 39 | |
| 40 LJLIB_CF(os_execute) | |
| 41 { | |
| 42 #if LJ_NO_SYSTEM | |
| 43 #if LJ_52 | |
| 44 errno = ENOSYS; | |
| 45 return luaL_fileresult(L, 0, NULL); | |
| 46 #else | |
| 47 lua_pushinteger(L, -1); | |
| 48 return 1; | |
| 49 #endif | |
| 50 #else | |
| 51 const char *cmd = luaL_optstring(L, 1, NULL); | |
| 52 int stat = system(cmd); | |
| 53 #if LJ_52 | |
| 54 if (cmd) | |
| 55 return luaL_execresult(L, stat); | |
| 56 setboolV(L->top++, 1); | |
| 57 #else | |
| 58 setintV(L->top++, stat); | |
| 59 #endif | |
| 60 return 1; | |
| 61 #endif | |
| 62 } | |
| 63 | |
| 64 LJLIB_CF(os_remove) | |
| 65 { | |
| 66 const char *filename = luaL_checkstring(L, 1); | |
| 67 return luaL_fileresult(L, remove(filename) == 0, filename); | |
| 68 } | |
| 69 | |
| 70 LJLIB_CF(os_rename) | |
| 71 { | |
| 72 const char *fromname = luaL_checkstring(L, 1); | |
| 73 const char *toname = luaL_checkstring(L, 2); | |
| 74 return luaL_fileresult(L, rename(fromname, toname) == 0, fromname); | |
| 75 } | |
| 76 | |
| 77 LJLIB_CF(os_tmpname) | |
| 78 { | |
| 79 #if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PS5 || LJ_TARGET_PSVITA || LJ_TARGET_NX | |
| 80 lj_err_caller(L, LJ_ERR_OSUNIQF); | |
| 81 return 0; | |
| 82 #else | |
| 83 #if LJ_TARGET_POSIX | |
| 84 char buf[15+1]; | |
| 85 int fp; | |
| 86 strcpy(buf, "/tmp/lua_XXXXXX"); | |
| 87 fp = mkstemp(buf); | |
| 88 if (fp != -1) | |
| 89 close(fp); | |
| 90 else | |
| 91 lj_err_caller(L, LJ_ERR_OSUNIQF); | |
| 92 #else | |
| 93 char buf[L_tmpnam]; | |
| 94 if (tmpnam(buf) == NULL) | |
| 95 lj_err_caller(L, LJ_ERR_OSUNIQF); | |
| 96 #endif | |
| 97 lua_pushstring(L, buf); | |
| 98 return 1; | |
| 99 #endif | |
| 100 } | |
| 101 | |
| 102 LJLIB_CF(os_getenv) | |
| 103 { | |
| 104 #if LJ_TARGET_CONSOLE | |
| 105 lua_pushnil(L); | |
| 106 #else | |
| 107 lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ | |
| 108 #endif | |
| 109 return 1; | |
| 110 } | |
| 111 | |
| 112 LJLIB_CF(os_exit) | |
| 113 { | |
| 114 int status; | |
| 115 if (L->base < L->top && tvisbool(L->base)) | |
| 116 status = boolV(L->base) ? EXIT_SUCCESS : EXIT_FAILURE; | |
| 117 else | |
| 118 status = lj_lib_optint(L, 1, EXIT_SUCCESS); | |
| 119 if (L->base+1 < L->top && tvistruecond(L->base+1)) | |
| 120 lua_close(L); | |
| 121 exit(status); | |
| 122 return 0; /* Unreachable. */ | |
| 123 } | |
| 124 | |
| 125 LJLIB_CF(os_clock) | |
| 126 { | |
| 127 setnumV(L->top++, ((lua_Number)clock())*(1.0/(lua_Number)CLOCKS_PER_SEC)); | |
| 128 return 1; | |
| 129 } | |
| 130 | |
| 131 /* ------------------------------------------------------------------------ */ | |
| 132 | |
| 133 static void setfield(lua_State *L, const char *key, int value) | |
| 134 { | |
| 135 lua_pushinteger(L, value); | |
| 136 lua_setfield(L, -2, key); | |
| 137 } | |
| 138 | |
| 139 static void setboolfield(lua_State *L, const char *key, int value) | |
| 140 { | |
| 141 if (value < 0) /* undefined? */ | |
| 142 return; /* does not set field */ | |
| 143 lua_pushboolean(L, value); | |
| 144 lua_setfield(L, -2, key); | |
| 145 } | |
| 146 | |
| 147 static int getboolfield(lua_State *L, const char *key) | |
| 148 { | |
| 149 int res; | |
| 150 lua_getfield(L, -1, key); | |
| 151 res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); | |
| 152 lua_pop(L, 1); | |
| 153 return res; | |
| 154 } | |
| 155 | |
| 156 static int getfield(lua_State *L, const char *key, int d) | |
| 157 { | |
| 158 int res; | |
| 159 lua_getfield(L, -1, key); | |
| 160 if (lua_isnumber(L, -1)) { | |
| 161 res = (int)lua_tointeger(L, -1); | |
| 162 } else { | |
| 163 if (d < 0) | |
| 164 lj_err_callerv(L, LJ_ERR_OSDATEF, key); | |
| 165 res = d; | |
| 166 } | |
| 167 lua_pop(L, 1); | |
| 168 return res; | |
| 169 } | |
| 170 | |
| 171 LJLIB_CF(os_date) | |
| 172 { | |
| 173 const char *s = luaL_optstring(L, 1, "%c"); | |
| 174 time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); | |
| 175 struct tm *stm; | |
| 176 #if LJ_TARGET_POSIX | |
| 177 struct tm rtm; | |
| 178 #endif | |
| 179 if (*s == '!') { /* UTC? */ | |
| 180 s++; /* Skip '!' */ | |
| 181 #if LJ_TARGET_POSIX | |
| 182 stm = gmtime_r(&t, &rtm); | |
| 183 #else | |
| 184 stm = gmtime(&t); | |
| 185 #endif | |
| 186 } else { | |
| 187 #if LJ_TARGET_POSIX | |
| 188 stm = localtime_r(&t, &rtm); | |
| 189 #else | |
| 190 stm = localtime(&t); | |
| 191 #endif | |
| 192 } | |
| 193 if (stm == NULL) { /* Invalid date? */ | |
| 194 setnilV(L->top++); | |
| 195 } else if (strcmp(s, "*t") == 0) { | |
| 196 lua_createtable(L, 0, 9); /* 9 = number of fields */ | |
| 197 setfield(L, "sec", stm->tm_sec); | |
| 198 setfield(L, "min", stm->tm_min); | |
| 199 setfield(L, "hour", stm->tm_hour); | |
| 200 setfield(L, "day", stm->tm_mday); | |
| 201 setfield(L, "month", stm->tm_mon+1); | |
| 202 setfield(L, "year", stm->tm_year+1900); | |
| 203 setfield(L, "wday", stm->tm_wday+1); | |
| 204 setfield(L, "yday", stm->tm_yday+1); | |
| 205 setboolfield(L, "isdst", stm->tm_isdst); | |
| 206 } else if (*s) { | |
| 207 SBuf *sb = &G(L)->tmpbuf; | |
| 208 MSize sz = 0, retry = 4; | |
| 209 const char *q; | |
| 210 for (q = s; *q; q++) | |
| 211 sz += (*q == '%') ? 30 : 1; /* Overflow doesn't matter. */ | |
| 212 setsbufL(sb, L); | |
| 213 while (retry--) { /* Limit growth for invalid format or empty result. */ | |
| 214 char *buf = lj_buf_need(sb, sz); | |
| 215 size_t len = strftime(buf, sbufsz(sb), s, stm); | |
| 216 if (len) { | |
| 217 setstrV(L, L->top++, lj_str_new(L, buf, len)); | |
| 218 lj_gc_check(L); | |
| 219 break; | |
| 220 } | |
| 221 sz += (sz|1); | |
| 222 } | |
| 223 } else { | |
| 224 setstrV(L, L->top++, &G(L)->strempty); | |
| 225 } | |
| 226 return 1; | |
| 227 } | |
| 228 | |
| 229 LJLIB_CF(os_time) | |
| 230 { | |
| 231 time_t t; | |
| 232 if (lua_isnoneornil(L, 1)) { /* called without args? */ | |
| 233 t = time(NULL); /* get current time */ | |
| 234 } else { | |
| 235 struct tm ts; | |
| 236 luaL_checktype(L, 1, LUA_TTABLE); | |
| 237 lua_settop(L, 1); /* make sure table is at the top */ | |
| 238 ts.tm_sec = getfield(L, "sec", 0); | |
| 239 ts.tm_min = getfield(L, "min", 0); | |
| 240 ts.tm_hour = getfield(L, "hour", 12); | |
| 241 ts.tm_mday = getfield(L, "day", -1); | |
| 242 ts.tm_mon = getfield(L, "month", -1) - 1; | |
| 243 ts.tm_year = getfield(L, "year", -1) - 1900; | |
| 244 ts.tm_isdst = getboolfield(L, "isdst"); | |
| 245 t = mktime(&ts); | |
| 246 } | |
| 247 if (t == (time_t)(-1)) | |
| 248 lua_pushnil(L); | |
| 249 else | |
| 250 lua_pushnumber(L, (lua_Number)t); | |
| 251 return 1; | |
| 252 } | |
| 253 | |
| 254 LJLIB_CF(os_difftime) | |
| 255 { | |
| 256 lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), | |
| 257 (time_t)(luaL_optnumber(L, 2, (lua_Number)0)))); | |
| 258 return 1; | |
| 259 } | |
| 260 | |
| 261 /* ------------------------------------------------------------------------ */ | |
| 262 | |
| 263 LJLIB_CF(os_setlocale) | |
| 264 { | |
| 265 #if LJ_TARGET_PSVITA | |
| 266 lua_pushliteral(L, "C"); | |
| 267 #else | |
| 268 GCstr *s = lj_lib_optstr(L, 1); | |
| 269 const char *str = s ? strdata(s) : NULL; | |
| 270 int opt = lj_lib_checkopt(L, 2, 6, | |
| 271 "\5ctype\7numeric\4time\7collate\10monetary\1\377\3all"); | |
| 272 if (opt == 0) opt = LC_CTYPE; | |
| 273 else if (opt == 1) opt = LC_NUMERIC; | |
| 274 else if (opt == 2) opt = LC_TIME; | |
| 275 else if (opt == 3) opt = LC_COLLATE; | |
| 276 else if (opt == 4) opt = LC_MONETARY; | |
| 277 else if (opt == 6) opt = LC_ALL; | |
| 278 lua_pushstring(L, setlocale(opt, str)); | |
| 279 #endif | |
| 280 return 1; | |
| 281 } | |
| 282 | |
| 283 /* ------------------------------------------------------------------------ */ | |
| 284 | |
| 285 #include "lj_libdef.h" | |
| 286 | |
| 287 LUALIB_API int luaopen_os(lua_State *L) | |
| 288 { | |
| 289 LJ_LIB_REG(L, LUA_OSLIBNAME, os); | |
| 290 return 1; | |
| 291 } | |
| 292 |