mirror of https://github.com/bjornbytes/lovr.git
Style/functional fixes to args for PR. --inside is now --root
This commit is contained in:
parent
2213b3bcfd
commit
91daeae634
|
@ -263,8 +263,8 @@ static int l_lovrFilesystemMount(lua_State* L) {
|
|||
const char* path = luaL_checkstring(L, 1);
|
||||
const char* mountpoint = luaL_optstring(L, 2, NULL);
|
||||
bool append = lua_isnoneornil(L, 3) ? 0 : lua_toboolean(L, 3);
|
||||
const char* mountpointInner = luaL_optstring(L, 4, NULL);
|
||||
lua_pushboolean(L, !lovrFilesystemMount(path, mountpoint, append, mountpointInner));
|
||||
const char* root = luaL_optstring(L, 4, NULL);
|
||||
lua_pushboolean(L, !lovrFilesystemMount(path, mountpoint, append, root));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -362,13 +362,13 @@ int luaopen_lovr_filesystem(lua_State* L) {
|
|||
|
||||
lua_getglobal(L, "arg");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_rawgeti(L, -1, -1);
|
||||
lua_getfield(L, -1, "exe");
|
||||
const char* argExe = lua_tostring(L, -1);
|
||||
lua_rawgeti(L, -2, 0);
|
||||
const char* argGame = lua_tostring(L, -1);
|
||||
lua_getfield(L, -3, "inside");
|
||||
const char* argGameInner = luaL_optstring(L, -1, NULL);
|
||||
lovrFilesystemInit(argExe, argGame, argGameInner);
|
||||
lua_getfield(L, -3, "root");
|
||||
const char* argRoot = luaL_optstring(L, -1, NULL);
|
||||
lovrFilesystemInit(argExe, argGame, argRoot);
|
||||
lua_pop(L, 4);
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
|
|
|
@ -31,7 +31,7 @@ const char lovrDirSep = '/';
|
|||
|
||||
static FilesystemState state;
|
||||
|
||||
void lovrFilesystemInit(const char* argExe, const char* argGame, const char* argGameInner) {
|
||||
void lovrFilesystemInit(const char* argExe, const char* argGame, const char* argRoot) {
|
||||
if (state.initialized) return;
|
||||
state.initialized = true;
|
||||
|
||||
|
@ -49,12 +49,12 @@ void lovrFilesystemInit(const char* argExe, const char* argGame, const char* arg
|
|||
|
||||
// Try to mount either an archive fused to the executable or an archive from the command line
|
||||
lovrFilesystemGetExecutablePath(state.source, LOVR_PATH_MAX);
|
||||
if (lovrFilesystemMount(state.source, NULL, 1, argGameInner)) { // Attempt to load fused. If that fails...
|
||||
if (lovrFilesystemMount(state.source, NULL, 1, argRoot)) { // Attempt to load fused. If that fails...
|
||||
state.isFused = false;
|
||||
|
||||
if (argGame) {
|
||||
strncpy(state.source, argGame, LOVR_PATH_MAX);
|
||||
if (!lovrFilesystemMount(state.source, NULL, 1, argGameInner)) { // Attempt to load from arg. If success, init is done
|
||||
if (!lovrFilesystemMount(state.source, NULL, 1, argRoot)) { // Attempt to load from arg. If success, init is done
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -202,10 +202,10 @@ bool lovrFilesystemIsFused() {
|
|||
}
|
||||
|
||||
// Returns zero on success, nonzero on failure
|
||||
int lovrFilesystemMount(const char* path, const char* mountpoint, bool append, const char* mountpointInner) {
|
||||
int lovrFilesystemMount(const char* path, const char* mountpoint, bool append, const char* root) {
|
||||
bool success = PHYSFS_mount(path, mountpoint, append);
|
||||
if (success && mountpointInner) {
|
||||
success = PHYSFS_setRoot(path, mountpointInner);
|
||||
if (success && root) {
|
||||
success = PHYSFS_setRoot(path, root);
|
||||
}
|
||||
return !success;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ typedef struct {
|
|||
vec_str_t requirePattern[2];
|
||||
} FilesystemState;
|
||||
|
||||
void lovrFilesystemInit(const char* argExe, const char* argGame, const char* argGameInner);
|
||||
void lovrFilesystemInit(const char* argExe, const char* argGame, const char* argRoot);
|
||||
void lovrFilesystemDestroy();
|
||||
int lovrFilesystemCreateDirectory(const char* path);
|
||||
int lovrFilesystemGetAppdataDirectory(char* dest, unsigned int size);
|
||||
|
@ -41,7 +41,7 @@ int lovrFilesystemGetWorkingDirectory(char* dest, unsigned int size);
|
|||
bool lovrFilesystemIsDirectory(const char* path);
|
||||
bool lovrFilesystemIsFile(const char* path);
|
||||
bool lovrFilesystemIsFused();
|
||||
int lovrFilesystemMount(const char* path, const char* mountpoint, bool append, const char *mountpointInner);
|
||||
int lovrFilesystemMount(const char* path, const char* mountpoint, bool append, const char *root);
|
||||
void* lovrFilesystemRead(const char* path, size_t* bytesRead);
|
||||
int lovrFilesystemRemove(const char* path);
|
||||
int lovrFilesystemSetIdentity(const char* identity);
|
||||
|
|
|
@ -389,17 +389,20 @@ void bridgeLovrInit(BridgeLovrInitData *initData) {
|
|||
{
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "lovr");
|
||||
lua_rawseti(L, -2, -1);
|
||||
lua_pushstring(L, initData->apkPath);
|
||||
lua_rawseti(L, -2, 0);
|
||||
lua_pushvalue(L, -1); // Double at named key
|
||||
lua_setfield(L, -3, "exe");
|
||||
lua_rawseti(L, -2, -3);
|
||||
|
||||
// Mimic the arguments "--inside /assets" as parsed by lovrInit
|
||||
lua_pushstring(L, "--inside");
|
||||
// Mimic the arguments "--root /assets" as parsed by lovrInit
|
||||
lua_pushstring(L, "--root");
|
||||
lua_rawseti(L, -2, -2);
|
||||
lua_pushstring(L, "/assets");
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, "inside");
|
||||
lua_rawseti(L, -2, -3);
|
||||
lua_pushvalue(L, -1); // Double at named key
|
||||
lua_setfield(L, -3, "root");
|
||||
lua_rawseti(L, -2, -1);
|
||||
|
||||
lua_pushstring(L, initData->apkPath);
|
||||
lua_rawseti(L, -2, 0);
|
||||
|
||||
lua_setglobal(L, "arg");
|
||||
}
|
||||
|
|
75
src/main.c
75
src/main.c
|
@ -101,15 +101,9 @@ static void onGlfwError(int code, const char* description) {
|
|||
lovrThrow(description);
|
||||
}
|
||||
|
||||
typedef enum { // What is the argument parser doing?
|
||||
argparse_exe, // Interpreter
|
||||
argparse_flags,
|
||||
argparse_game // Game path and arguments
|
||||
} ArgParseState;
|
||||
|
||||
typedef enum { // In state argparse_flag, what flag is being searched for?
|
||||
argflag_none, // Not processing a flag
|
||||
argflag_inside
|
||||
typedef enum { // What flag is being searched for?
|
||||
ARGFLAG_NONE, // Not processing a flag
|
||||
ARGFLAG_ROOT
|
||||
} ArgFlag;
|
||||
|
||||
lua_State* lovrInit(lua_State* L, int argc, char** argv) {
|
||||
|
@ -119,51 +113,54 @@ lua_State* lovrInit(lua_State* L, int argc, char** argv) {
|
|||
|
||||
// arg table
|
||||
// Args follow the lua standard https://en.wikibooks.org/wiki/Lua_Programming/command_line_parameter
|
||||
// * The lovr interpreter and its arguments are in successive negative indexes starting at -1.
|
||||
// The interpreter will always be at arg[-1] and always non-nil.
|
||||
// * The "script" (in the case of Lovr, the "game") is at arg[0]. This may be nil (for a fused exe)
|
||||
// * Arguments intended for the script (the "game") are at positive indexes starting with 1.
|
||||
// Named arguments recognized by lovr will also be stored in the table at their names. This is not standard.
|
||||
// In this standard, the contents of argv are put in a global table named "arg", but with indices offset
|
||||
// such that the "script" (in lovr, the game path) is at index 0. So all arguments (if any) intended for
|
||||
// the script/game are at successive indices starting with 1, and the exe and its arguments are in normal
|
||||
// order but stored in negative indices.
|
||||
//
|
||||
// Lovr can be run in ways normal lua can't. It can be run with an empty argv, or with no script (if fused).
|
||||
// So in the case of lovr:
|
||||
// * The script path will always be at index 0, but it can be nil.
|
||||
// * For a fused executable, whatever is given in argv as script name is still at 0, but will be ignored.
|
||||
// * The exe (argv[0]) will always be the lowest-integer index. If it's present, it will always be -1 or less.
|
||||
// * Any named arguments parsed by Lovr will be stored in the arg table at their named keys.
|
||||
// * An exe name will always be stored in the arg table at string key "exe", even if none was supplied in argv.
|
||||
lua_newtable(L);
|
||||
// push dummy "lovr" in case argv is empty
|
||||
lua_pushstring(L, "lovr");
|
||||
lua_rawseti(L, -2, -1);
|
||||
lua_setfield(L, -2, "exe");
|
||||
|
||||
ArgParseState parseState = argparse_exe;
|
||||
ArgFlag currentFlag = argflag_none;
|
||||
int lovrArgs = 0, userArgs = 0;
|
||||
bool exeFound = false;
|
||||
ArgFlag currentFlag = ARGFLAG_NONE;
|
||||
int lovrArgs = 0; // Arg count up to but not including the game path
|
||||
// One pass to parse flags
|
||||
for (int i = 0; i < argc; i++) {
|
||||
// Handle flags first, so we can immediately reinterpret this as the game path if it isn't a flag
|
||||
if (parseState == argparse_flags) {
|
||||
if (lovrArgs > 0) {
|
||||
// This argument is an argument to a -- flag
|
||||
if (currentFlag == argflag_inside) {
|
||||
if (currentFlag == ARGFLAG_ROOT) {
|
||||
lua_pushstring(L, argv[i]);
|
||||
lua_setfield(L, -2, "inside");
|
||||
currentFlag = argflag_none;
|
||||
lua_setfield(L, -2, "root");
|
||||
currentFlag = ARGFLAG_NONE;
|
||||
|
||||
// This argument is a -- flag
|
||||
} else if (!strcmp(argv[1], "--inside") || !strcmp(argv[1], "-i")) {
|
||||
currentFlag = argflag_inside;
|
||||
} else if (!strcmp(argv[1], "--root") || !strcmp(argv[1], "-r")) {
|
||||
currentFlag = ARGFLAG_ROOT;
|
||||
|
||||
// No flags, this is the game path
|
||||
// This is the game path
|
||||
} else {
|
||||
parseState = argparse_game;
|
||||
break;
|
||||
}
|
||||
} else { // Found exe name
|
||||
lua_pushstring(L, argv[i]);
|
||||
lua_setfield(L, -2, "exe");
|
||||
}
|
||||
|
||||
lovrArgs++;
|
||||
}
|
||||
// Now that we know the negative offset to start at, copy all args in the table
|
||||
for (int i = 0; i < argc; i++) {
|
||||
lua_pushstring(L, argv[i]);
|
||||
lua_rawseti(L, -2, parseState == argparse_game ? (0 + userArgs) : (-1 - lovrArgs));
|
||||
|
||||
// Count flags
|
||||
if (parseState == argparse_game) {
|
||||
userArgs++;
|
||||
} else {
|
||||
lovrArgs++;
|
||||
|
||||
if (parseState == argparse_exe) {
|
||||
parseState = argparse_flags;
|
||||
}
|
||||
}
|
||||
lua_rawseti(L, -2, -lovrArgs + i);
|
||||
}
|
||||
|
||||
lua_setglobal(L, "arg");
|
||||
|
|
Loading…
Reference in New Issue