111 lines
2.9 KiB
C
111 lines
2.9 KiB
C
// strip.c -- Release build stripping
|
|
//
|
|
// Removes debug information from a compiled module:
|
|
// - Clears debug variable info (names, scopes, types)
|
|
// - Clears debug UDT definitions
|
|
// - Mangles procedure names that aren't needed for runtime dispatch.
|
|
// The form runtime dispatches events by name (Control_Event pattern)
|
|
// and SetEvent looks up handlers by name at runtime, so those proc
|
|
// names must be preserved. Everything else becomes F1, F2, F3...
|
|
//
|
|
// OP_LINE removal is deferred to a future version (requires
|
|
// bytecode compaction and offset rewriting).
|
|
|
|
#include "strip.h"
|
|
#include "../runtime/values.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
// Events fired by name via basFormRtFireEvent* in formrt.c. Any proc
|
|
// ending in "_<EventName>" must keep its name so the dispatcher can
|
|
// find it.
|
|
static const char *sEventSuffixes[] = {
|
|
"Load", "Unload", "QueryUnload", "Resize", "Activate", "Deactivate",
|
|
"Click", "DblClick", "Change", "Timer",
|
|
"GotFocus", "LostFocus",
|
|
"KeyPress", "KeyDown", "KeyUp",
|
|
"MouseDown", "MouseUp", "MouseMove",
|
|
"Scroll", "Reposition", "Validate",
|
|
NULL
|
|
};
|
|
|
|
|
|
static bool nameEndsWithEventSuffix(const char *name) {
|
|
const char *underscore = strrchr(name, '_');
|
|
|
|
if (!underscore) {
|
|
return false;
|
|
}
|
|
|
|
const char *suffix = underscore + 1;
|
|
|
|
for (int32_t i = 0; sEventSuffixes[i]; i++) {
|
|
if (strcasecmp(suffix, sEventSuffixes[i]) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
static bool nameInConstantPool(const BasModuleT *mod, const char *name) {
|
|
for (int32_t i = 0; i < mod->constCount; i++) {
|
|
const BasStringT *s = mod->constants[i];
|
|
|
|
if (s && strcasecmp(s->data, name) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
void basStripModule(BasModuleT *mod) {
|
|
if (!mod) {
|
|
return;
|
|
}
|
|
|
|
// Clear debug variable info
|
|
free(mod->debugVars);
|
|
mod->debugVars = NULL;
|
|
mod->debugVarCount = 0;
|
|
|
|
// Clear debug UDT definitions
|
|
if (mod->debugUdtDefs) {
|
|
for (int32_t i = 0; i < mod->debugUdtDefCount; i++) {
|
|
free(mod->debugUdtDefs[i].fields);
|
|
}
|
|
|
|
free(mod->debugUdtDefs);
|
|
mod->debugUdtDefs = NULL;
|
|
mod->debugUdtDefCount = 0;
|
|
}
|
|
|
|
// Mangle proc names. Keep names that are needed for runtime name
|
|
// lookup: event handlers (Control_Event pattern) and any name
|
|
// referenced as a string constant (e.g. SetEvent's target name).
|
|
int32_t nextMangled = 1;
|
|
|
|
for (int32_t i = 0; i < mod->procCount; i++) {
|
|
BasProcEntryT *proc = &mod->procs[i];
|
|
|
|
if (proc->name[0] == '\0') {
|
|
continue;
|
|
}
|
|
|
|
if (nameEndsWithEventSuffix(proc->name)) {
|
|
continue;
|
|
}
|
|
|
|
if (nameInConstantPool(mod, proc->name)) {
|
|
continue;
|
|
}
|
|
|
|
snprintf(proc->name, sizeof(proc->name), "F%ld", (long)nextMangled++);
|
|
}
|
|
}
|