<commit_before>#include "resources/boot.lua.h"
#include "api/api.h"
#include "event/event.h"
#include "core/os.h"
#include "core/util.h"
#include <lualib.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>

#ifdef EMSCRIPTEN
#include <emscripten.h>

typedef struct {
  lua_State* L;
  lua_State* T;
  int argc;
  char** argv;
} lovrEmscriptenContext;

static void emscriptenLoop(void*);
#endif

int main(int argc, char** argv) {
  if (argc > 1 && (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-v"))) {
    lovrPlatformOpenConsole();
    printf("LOVR %d.%d.%d (%s)\n", LOVR_VERSION_MAJOR, LOVR_VERSION_MINOR, LOVR_VERSION_PATCH, LOVR_VERSION_ALIAS);
    exit(0);
  }

  lovrAssert(lovrPlatformInit(), "Failed to initialize platform");

  int status;
  bool restart;
  Variant cookie;
  cookie.type = TYPE_NIL;

  do {
    lovrPlatformSetTime(0.);
    lua_State* L = luaL_newstate();
    luax_setmainthread(L);
    luaL_openlibs(L);

    // arg table
    lua_newtable(L);
    lua_pushstring(L, argc > 0 ? argv[0] : "lovr");
    lua_setfield(L, -2, "exe");
    luax_pushvariant(L, &cookie);
    lua_setfield(L, -2, "restart");

    int argOffset = 1;
    for (int i = 1; i < argc; i++, argOffset++) {
      if (!strcmp(argv[i], "--console")) {
        lovrPlatformOpenConsole();
      } else {
        break; // This is the project path
      }
    }

    // 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, -argOffset + i);
    }
    lua_setglobal(L, "arg");

    lua_getglobal(L, "package");
    lua_getfield(L, -1, "preload");
    luax_register(L, lovrModules);
    lua_pop(L, 2);

    lua_pushcfunction(L, luax_getstack);
    if (luaL_loadbuffer(L, (const char*) src_resources_boot_lua, src_resources_boot_lua_len, "@boot.lua") || lua_pcall(L, 0, 1, -2)) {
      fprintf(stderr, "%s\n", lua_tostring(L, -1));
      return 1;
    }

    lua_State* T = lua_newthread(L);
    lua_pushvalue(L, -2);
    lua_xmove(L, T, 1);

    lovrSetErrorCallback(luax_vthrow, T);
    lovrSetLogCallback(luax_vlog, T);

#ifdef EMSCRIPTEN
    lovrEmscriptenContext context = { L, T, argc, argv };
    emscripten_set_main_loop_arg(emscriptenLoop, (void*) &context, 0, 1);
    return 0;
#endif

    while (luax_resume(T, 0) == LUA_YIELD) {
      lovrPlatformSleep(0.);
    }

    restart = lua_type(T, 1) == LUA_TSTRING && !strcmp(lua_tostring(T, 1), "restart");
    status = lua_tonumber(T, 1);
    luax_checkvariant(T, 2, &cookie);
    if (cookie.type == TYPE_OBJECT) {
      cookie.type = TYPE_NIL;
      memset(&cookie.value, 0, sizeof(cookie.value));
    }
    lua_close(L);
  } while (restart);

  lovrPlatformDestroy();

  return status;
}

#ifdef EMSCRIPTEN
// Called by JS
void lovrDestroy(void* arg) {
  if (arg) {
    lovrEmscriptenContext* context = arg;
    lua_State* L = context->L;
    emscripten_cancel_main_loop();
    lua_close(L);
    lovrPlatformDestroy();
  }
}

static void emscriptenLoop(void* arg) {
  lovrEmscriptenContext* context = arg;
  lua_State* T = context->T;

  if (luax_resume(T, 0) != LUA_YIELD) {
    bool restart = lua_type(T, -1) == LUA_TSTRING && !strcmp(lua_tostring(T, -1), "restart");
    int status = lua_tonumber(T, -1);

    lua_close(context->L);
    emscripten_cancel_main_loop();

    if (restart) {
      main(context->argc, context->argv);
    } else {
      lovrPlatformDestroy();
      exit(status);
    }
  }
}<commit_msg>Fix restart cookie on wasm;<commit_after>#include "resources/boot.lua.h"
#include "api/api.h"
#include "event/event.h"
#include "core/os.h"
#include "core/util.h"
#include <lualib.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>

#ifdef EMSCRIPTEN
#include <emscripten.h>

typedef struct {
  lua_State* L;
  lua_State* T;
  int argc;
  char** argv;
} lovrEmscriptenContext;

static void emscriptenLoop(void*);
#endif

static Variant cookie;

int main(int argc, char** argv) {
  if (argc > 1 && (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-v"))) {
    lovrPlatformOpenConsole();
    printf("LOVR %d.%d.%d (%s)\n", LOVR_VERSION_MAJOR, LOVR_VERSION_MINOR, LOVR_VERSION_PATCH, LOVR_VERSION_ALIAS);
    exit(0);
  }

  lovrAssert(lovrPlatformInit(), "Failed to initialize platform");

  int status;
  bool restart;

  do {
    lovrPlatformSetTime(0.);
    lua_State* L = luaL_newstate();
    luax_setmainthread(L);
    luaL_openlibs(L);

    // arg table
    lua_newtable(L);
    lua_pushstring(L, argc > 0 ? argv[0] : "lovr");
    lua_setfield(L, -2, "exe");
    luax_pushvariant(L, &cookie);
    lua_setfield(L, -2, "restart");

    int argOffset = 1;
    for (int i = 1; i < argc; i++, argOffset++) {
      if (!strcmp(argv[i], "--console")) {
        lovrPlatformOpenConsole();
      } else {
        break; // This is the project path
      }
    }

    // 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, -argOffset + i);
    }
    lua_setglobal(L, "arg");

    lua_getglobal(L, "package");
    lua_getfield(L, -1, "preload");
    luax_register(L, lovrModules);
    lua_pop(L, 2);

    lua_pushcfunction(L, luax_getstack);
    if (luaL_loadbuffer(L, (const char*) src_resources_boot_lua, src_resources_boot_lua_len, "@boot.lua") || lua_pcall(L, 0, 1, -2)) {
      fprintf(stderr, "%s\n", lua_tostring(L, -1));
      return 1;
    }

    lua_State* T = lua_newthread(L);
    lua_pushvalue(L, -2);
    lua_xmove(L, T, 1);

    lovrSetErrorCallback(luax_vthrow, T);
    lovrSetLogCallback(luax_vlog, T);

#ifdef EMSCRIPTEN
    lovrEmscriptenContext context = { L, T, argc, argv };
    emscripten_set_main_loop_arg(emscriptenLoop, (void*) &context, 0, 1);
    return 0;
#endif

    while (luax_resume(T, 0) == LUA_YIELD) {
      lovrPlatformSleep(0.);
    }

    restart = lua_type(T, 1) == LUA_TSTRING && !strcmp(lua_tostring(T, 1), "restart");
    status = lua_tonumber(T, 1);
    luax_checkvariant(T, 2, &cookie);
    if (cookie.type == TYPE_OBJECT) {
      cookie.type = TYPE_NIL;
      memset(&cookie.value, 0, sizeof(cookie.value));
    }
    lua_close(L);
  } while (restart);

  lovrPlatformDestroy();

  return status;
}

#ifdef EMSCRIPTEN
// Called by JS
void lovrDestroy(void* arg) {
  if (arg) {
    lovrEmscriptenContext* context = arg;
    lua_State* L = context->L;
    emscripten_cancel_main_loop();
    lua_close(L);
    lovrPlatformDestroy();
  }
}

static void emscriptenLoop(void* arg) {
  lovrEmscriptenContext* context = arg;
  lua_State* T = context->T;

  if (luax_resume(T, 0) != LUA_YIELD) {
    bool restart = lua_type(T, 1) == LUA_TSTRING && !strcmp(lua_tostring(T, 1), "restart");
    int status = lua_tonumber(T, 1);
    luax_checkvariant(T, 2, &cookie);
    if (cookie.type == TYPE_OBJECT) {
      cookie.type = TYPE_NIL;
      memset(&cookie.value, 0, sizeof(cookie.value));
    }

    lua_close(context->L);
    emscripten_cancel_main_loop();

    if (restart) {
      main(context->argc, context->argv);
    } else {
      lovrPlatformDestroy();
      exit(status);
    }
  }
}
{'fraction_non_alphanumeric': 0.15643785824129736, 'fraction_numerical': 0.010345309660282399, 'mean_word_length': 3.375535168195719, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3972530', 'n_tokens_mistral': 2900, 'n_tokens_neox': 2761, 'n_words': 592}