Skip to content

GLuaScript#1

Open
bilenkonito wants to merge 3 commits into
bilenkonito:masterfrom
Metastruct:master
Open

GLuaScript#1
bilenkonito wants to merge 3 commits into
bilenkonito:masterfrom
Metastruct:master

Conversation

@bilenkonito

Copy link
Copy Markdown
Owner

No description provided.

@bilenkonito bilenkonito self-assigned this Jan 27, 2026
Copilot AI review requested due to automatic review settings January 27, 2026 19:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR appears to retarget the embedded Lua runtime and libraries toward a Lua 5.1-era implementation (for GLua compatibility) while adding a Lua 5.3 compatibility shim and updating the Notepad++ plugin build/initialization.

Changes:

  • Swaps/rewrites large portions of bundled Lua core + standard libraries to older (5.1-style) APIs and data structures.
  • Adds a Lua 5.3 compatibility layer (compat-5.3.*) to backfill newer APIs on older Lua.
  • Updates Visual Studio solution/projects and plugin init code to build/link against an external Lua 5.1 (lua_shared.lib) and to open libraries via new *_base2/openlibs2 entrypoints.

Reviewed changes

Copilot reviewed 41 out of 66 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/lua/src/loslib.c Alters os.* implementations (execute/date/time/exit) to older semantics and custom error handling.
src/lua/src/lopcodes.h Reverts opcode definitions/macros toward Lua 5.1 layouts (removes Ax, EXTRAARG, etc.).
src/lua/src/lopcodes.c Updates opcode name/mode tables to match the altered opcode set.
src/lua/src/lobject.h Large refactor of TValue/GCObject/tagging/layouts toward an older Lua object model.
src/lua/src/lobject.c Reworks object helpers (nil object, number conversion, pushfstring, chunk id formatting, etc.).
src/lua/src/lmem.h Changes memory macros/types and grow helpers for the older runtime assumptions.
src/lua/src/lmem.c Reworks allocator, growth errors, and accounting (totalbytes vs GC debt).
src/lua/src/lmathlib.c Changes math library contents/registration and random behavior.
src/lua/src/llimits.h Reverts core limits/types/macros (Instruction type, MAX_* definitions, stack limits).
src/lua/src/llex.h Alters lexer token set and lexer state fields toward older parser expectations.
src/lua/src/linit.c Replaces luaL_openlibs with luaL_openlibs2 and changes opened library set/call pattern.
src/lua/src/lgc.h Reworks GC state model and barriers/macros for older runtime behavior.
src/lua/src/lfunc.h Changes closure/upvalue APIs and introduces free helpers for closures/upvalues.
src/lua/src/lfunc.c Reimplements closure/upvalue allocation/linking and proto lifecycle.
src/lua/src/ldump.c Reworks bytecode dump writer to match revised data structures/dump format.
src/lua/src/ldo.h Changes stack checking macros and function prototypes to older VM calling conventions.
src/lua/src/ldebug.h Updates debug API prototypes and line mapping macro names/semantics.
src/lua/src/ldblib.c Reverts debug library APIs (fenv, hook storage, traceback) and registration style.
src/lua/src/lcode.h Reverts codegen operator enums and code access macros/prototypes.
src/lua/src/lbaselib.c Replaces base library with a reduced “base2” API surface and loader functions.
src/lua/src/lauxlib.h Reverts auxlib API (register/openlib, buffer API) and introduces compat macros.
src/lua/src/lapi.h Removes inline API stack macros and adds luaA_pushobject prototype.
src/lua/src/compat-5.3.h Adds Lua 5.3 compatibility header for Lua 5.1/5.2 builds.
src/lua/src/compat-5.3.c Adds implementation for the Lua 5.3 compatibility layer.
src/lua/src/Makefile Updates object lists/targets for the altered Lua source set.
src/SciTE/LuaExtension.cpp Updates plugin init to open libs via both Lua’s luaL_openlibs and new *2 open functions.
src/LuaScript.vcxproj.filters Adds Lua sources + compat file to the Visual Studio filters.
src/LuaScript.vcxproj Updates toolset/SDK, links against external lua_shared.lib, and includes Lua sources.
src/Lua.vcxproj Updates toolset/SDK (but the solution removes this project).
README.md Adds GLuaScript-specific readme header and keeps original README sections.
LuaScript.sln Moves solution to VS 15 and removes the separate Lua static library project.
.gitattributes Adds a standard .gitattributes for line-ending normalization and merge guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/lua/src/loslib.c
const char *se = s + slen; /* 's' end */
struct tm tmr, *stm;
const char *s = luaL_optstring(L, 1, "%c");
time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

luaL_opt expects a function pointer (f(lua_State*, int)), but (time_t)luaL_checknumber casts the function symbol to an integer type, which will not compile (or will compile incorrectly) and cannot be called. Use luaL_optnumber/luaL_optinteger and cast the returned value to time_t, or provide a small wrapper function matching luaL_opt’s expected signature that returns time_t.

Suggested change
time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
time_t t = (time_t)luaL_optnumber(L, 2, (lua_Number)time(NULL));

Copilot uses AI. Check for mistakes.
Comment thread src/lua/src/lobject.c
Comment on lines +183 to +211
if (*source == '=') {
strncpy(out, source+1, bufflen); /* remove first char */
out[bufflen-1] = '\0'; /* ensures null termination */
}
else { /* out = "source", or "...source" */
if (*source == '@') {
size_t l;
source++; /* skip the `@' */
bufflen -= sizeof(" '...' ");
l = strlen(source);
strcpy(out, "");
if (l > bufflen) {
source += (l-bufflen); /* get last part of file name */
strcat(out, "...");
}
strcat(out, source);
}
else {
if (nl != NULL) l = nl - source; /* stop at first newline */
if (l > bufflen) l = bufflen;
addstr(out, source, l);
addstr(out, RETS, LL(RETS));
else { /* out = [string "string"] */
size_t len = strcspn(source, "\n\r"); /* stop at first newline */
bufflen -= sizeof(" [string \"...\"] ");
if (len > bufflen) len = bufflen;
strcpy(out, "[string \"");
if (source[len] != '\0') { /* must truncate? */
strncat(out, source, len);
strcat(out, "...");
}
else
strcat(out, source);
strcat(out, "\"]");

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bufflen is a size_t; subtracting sizeof(" '...' ") without checking can underflow when bufflen is small, turning it into a huge number and making the subsequent strcat/strcpy calls potential buffer overflows. Please clamp/guard bufflen before subtracting and use size-bounded writes (e.g., track remaining space and use bounded concatenation) so out is never overrun.

Suggested change
if (*source == '=') {
strncpy(out, source+1, bufflen); /* remove first char */
out[bufflen-1] = '\0'; /* ensures null termination */
}
else { /* out = "source", or "...source" */
if (*source == '@') {
size_t l;
source++; /* skip the `@' */
bufflen -= sizeof(" '...' ");
l = strlen(source);
strcpy(out, "");
if (l > bufflen) {
source += (l-bufflen); /* get last part of file name */
strcat(out, "...");
}
strcat(out, source);
}
else {
if (nl != NULL) l = nl - source; /* stop at first newline */
if (l > bufflen) l = bufflen;
addstr(out, source, l);
addstr(out, RETS, LL(RETS));
else { /* out = [string "string"] */
size_t len = strcspn(source, "\n\r"); /* stop at first newline */
bufflen -= sizeof(" [string \"...\"] ");
if (len > bufflen) len = bufflen;
strcpy(out, "[string \"");
if (source[len] != '\0') { /* must truncate? */
strncat(out, source, len);
strcat(out, "...");
}
else
strcat(out, source);
strcat(out, "\"]");
size_t outsize = bufflen;
/* handle trivial case: no space to write anything */
if (outsize == 0)
return;
if (*source == '=') {
/* remove first char, ensuring null termination and no overflow */
if (outsize > 0) {
/* leave room for terminator */
strncpy(out, source + 1, outsize - 1);
out[outsize - 1] = '\0';
}
}
else { /* out = "source", or "...source" */
if (*source == '@') {
size_t l;
size_t available;
source++; /* skip the `@' */
l = strlen(source);
/*
** Compute how many characters from the end of the file name are
** available for display after reserving space for possible
** decorations (e.g., " '...' " around the name). Guard against
** underflow when outsize is small.
*/
if (outsize > sizeof(" '...' "))
available = outsize - sizeof(" '...' ");
else
available = 0;
if (available == 0) {
/* Not enough room to do anything useful; return empty string. */
out[0] = '\0';
return;
}
if (l > available) {
/* get last part of file name */
source += (l - available);
/* prefix with "..." and then append the tail, all bounded */
int n = snprintf(out, outsize, "...");
if (n < 0 || (size_t)n >= outsize) {
/* ensure null termination in case of truncation */
out[outsize - 1] = '\0';
return;
}
{
size_t used = (size_t)n;
size_t remaining = outsize - used;
if (remaining > 0) {
n = snprintf(out + used, remaining, "%s", source);
if (n < 0 || (size_t)n >= remaining)
out[outsize - 1] = '\0';
}
}
}
else {
/* whole file name fits */
int n = snprintf(out, outsize, "%s", source);
if (n < 0 || (size_t)n >= outsize)
out[outsize - 1] = '\0';
}
}
else { /* out = [string "string"] */
size_t len = strcspn(source, "\n\r"); /* stop at first newline */
size_t available;
char *p = out;
size_t remaining = outsize;
int n;
/*
** Compute how many characters from the chunk string we can include
** while still leaving space for the surrounding [string "...\"].
** Guard against underflow when outsize is small.
*/
if (outsize > sizeof(" [string \"...\"] "))
available = outsize - sizeof(" [string \"...\"] ");
else
available = 0;
if (len > available)
len = available;
if (remaining == 0) {
return;
}
/* start with the prefix */
n = snprintf(p, remaining, "[string \"");
if (n < 0 || (size_t)n >= remaining) {
out[outsize - 1] = '\0';
return;
}
p += n;
remaining -= (size_t)n;
if (len > 0) {
if (source[len] != '\0') { /* must truncate? */
n = snprintf(p, remaining, "%.*s...", (int)len, source);
}
else {
n = snprintf(p, remaining, "%.*s", (int)len, source);
}
if (n < 0 || (size_t)n >= remaining) {
out[outsize - 1] = '\0';
return;
}
p += n;
remaining -= (size_t)n;
}
/* append the closing "\"]" */
if (remaining > 0) {
n = snprintf(p, remaining, "\"]");
if (n < 0 || (size_t)n >= remaining)
out[outsize - 1] = '\0';
}
else {
/* no room for closing marker; ensure termination */
out[outsize - 1] = '\0';
}

Copilot uses AI. Check for mistakes.
Comment thread src/lua/src/lmathlib.c
Comment on lines +182 to 186
/* the `%' avoids the (rare) case of r==1, and is needed also because on
some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
switch (lua_gettop(L)) { /* check number of arguments */
case 0: { /* no arguments */

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rand() % RAND_MAX makes r==0 significantly more likely (because rand()==RAND_MAX maps to 0), which biases math.random. Also, modulo here doesn’t address the “rand larger than RAND_MAX” concern (that would be a broken libc contract). Prefer generating r via dividing by (RAND_MAX + 1) (or similar) to keep r in [0,1) without introducing extra bias.

Suggested change
/* the `%' avoids the (rare) case of r==1, and is needed also because on
some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
switch (lua_gettop(L)) { /* check number of arguments */
case 0: { /* no arguments */
/* compute r in [0,1) without introducing bias */
lua_Number r = (lua_Number)rand() / ((lua_Number)RAND_MAX + 1.0);
switch (lua_gettop(L)) { /* check number of arguments */
case 0: { /* no arguments */
case 0: { /* no arguments */

Copilot uses AI. Check for mistakes.

// ...register standard libraries
luaL_openlibs(luaState);
luaopen_base2(luaState);

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

luaopen_base2 returns 1 value (the library table) and this call path doesn’t pop it, which can leave unexpected stack junk during initialization. Also, calling both luaL_openlibs and luaL_openlibs2 risks registering overlapping libraries twice; consider using a single library-open path (or explicitly documenting/controlling the intended override order) and ensure the Lua stack is balanced after each call.

Suggested change
luaopen_base2(luaState);
luaopen_base2(luaState);
// luaopen_base2 pushes its library table; pop it to keep the stack balanced
lua_pop(luaState, 1);

Copilot uses AI. Check for mistakes.
Comment thread src/LuaScript.vcxproj
</ClCompile>
<Link>
<AdditionalDependencies>Lua.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>x:\do\GMod\gbins\lua51\lua_shared.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These absolute x:\... paths make the project non-portable and will break builds on other machines/CI. Use a repo-relative path, an MSBuild property (e.g., $(SolutionDir), $(ProjectDir)), or an environment variable with a reasonable default so contributors can build without editing the project file.

Copilot uses AI. Check for mistakes.
Comment thread src/LuaScript.vcxproj
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Debug configuration, using MultiThreaded (release CRT) instead of MultiThreadedDebug can cause CRT/heap mismatches and makes debugging harder (especially if any linked objects/libs use the debug CRT). If this is intentional, it should be clearly documented; otherwise, switch Debug back to the debug runtime or align the rest of the configuration accordingly.

Suggested change
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

Copilot uses AI. Check for mistakes.
Comment thread src/lua/src/lgc.h
** phase may break the invariant, as objects turned white may point to
** still-black objects. The invariant is restored when sweep ends and
** all objects are white again.
** some userful bit tricks

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'userful' to 'useful'.

Suggested change
** some userful bit tricks
** some useful bit tricks

Copilot uses AI. Check for mistakes.
Comment thread src/lua/src/lobject.c
}
while (x >= (8 << 1)) { /* fine steps */
x = (x + 1) >> 1; /* x = ceil(x / 2) */
int e = 0; /* expoent */

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'expoent' to 'exponent'.

Suggested change
int e = 0; /* expoent */
int e = 0; /* exponent */

Copilot uses AI. Check for mistakes.
Comment thread src/lua/src/ldblib.c
Comment on lines +245 to +255
static void gethooktable (lua_State *L) {
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
lua_createtable(L, 0, 1);
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
}
}

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hook table stored in the registry is not configured as weak and uses lua_State* (lightuserdata) keys; if hook entries aren’t explicitly cleared, this can grow unbounded over time as threads come/go. Consider using a weak-key table keyed by the thread object (lua_pushthread) or setting a metatable with __mode = "k" so entries don’t pin/accumulate unnecessarily.

Copilot uses AI. Check for mistakes.
Comment thread src/lua/src/lobject.c
Comment on lines 153 to 160
default: {
luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'",
*(e + 1));
char buff[3];
buff[0] = '%';
buff[1] = *(e+1);
buff[2] = '\0';
pushstr(L, buff);
break;
}

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

luaO_pushvfstring previously errored on invalid format options; this new behavior silently emits the unknown specifier text instead. That can mask format-string bugs and diverges from typical lua_pushfstring expectations. Consider restoring a hard error (or at least a debug assertion) when an unsupported format specifier is encountered.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants