mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Use std::deque for assertions
Also fix a memory leak
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#ifndef RGBDS_LINK_PATCH_H
|
#ifndef RGBDS_LINK_PATCH_H
|
||||||
#define RGBDS_LINK_PATCH_H
|
#define RGBDS_LINK_PATCH_H
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "link/section.hpp"
|
#include "link/section.hpp"
|
||||||
@@ -11,20 +12,17 @@
|
|||||||
#include "linkdefs.hpp"
|
#include "linkdefs.hpp"
|
||||||
|
|
||||||
struct Assertion {
|
struct Assertion {
|
||||||
struct Patch patch;
|
struct Patch patch; // Also used for its `.type`
|
||||||
// enum AssertionType type; The `patch`'s field is instead re-used
|
|
||||||
char *message;
|
char *message;
|
||||||
// This would be redundant with `.section->fileSymbols`... but `section` is sometimes NULL!
|
// This would be redundant with `.section->fileSymbols`... but `section` is sometimes NULL!
|
||||||
struct Symbol **fileSymbols;
|
struct Symbol **fileSymbols;
|
||||||
|
|
||||||
struct Assertion *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks all assertions
|
* Checks all assertions
|
||||||
* @return true if assertion failed
|
* @return true if assertion failed
|
||||||
*/
|
*/
|
||||||
void patch_CheckAssertions(struct Assertion *assertion);
|
void patch_CheckAssertions(std::deque<struct Assertion> &assertions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Applies all SECTIONs' patches to them
|
* Applies all SECTIONs' patches to them
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ static struct FileStackNodes {
|
|||||||
struct FileStackNode *nodes;
|
struct FileStackNode *nodes;
|
||||||
uint32_t nbNodes;
|
uint32_t nbNodes;
|
||||||
} *nodes;
|
} *nodes;
|
||||||
static struct Assertion *assertions;
|
static std::deque<struct Assertion> assertions;
|
||||||
|
|
||||||
// Helper functions for reading object files
|
// Helper functions for reading object files
|
||||||
|
|
||||||
@@ -617,15 +617,11 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
|
|||||||
tryReadlong(nbAsserts, file, "%s: Cannot read number of assertions: %s", fileName);
|
tryReadlong(nbAsserts, file, "%s: Cannot read number of assertions: %s", fileName);
|
||||||
verbosePrint("Reading %" PRIu32 " assertions...\n", nbAsserts);
|
verbosePrint("Reading %" PRIu32 " assertions...\n", nbAsserts);
|
||||||
for (uint32_t i = 0; i < nbAsserts; i++) {
|
for (uint32_t i = 0; i < nbAsserts; i++) {
|
||||||
struct Assertion *assertion = (struct Assertion *)malloc(sizeof(*assertion));
|
struct Assertion &assertion = assertions.emplace_front();
|
||||||
|
|
||||||
if (!assertion)
|
readAssertion(file, &assertion, fileName, i, nodes[fileID].nodes);
|
||||||
err("%s: Failed to create new assertion", fileName);
|
linkPatchToPCSect(&assertion.patch, fileSections);
|
||||||
readAssertion(file, assertion, fileName, i, nodes[fileID].nodes);
|
assertion.fileSymbols = fileSymbols;
|
||||||
linkPatchToPCSect(&assertion->patch, fileSections);
|
|
||||||
assertion->fileSymbols = fileSymbols;
|
|
||||||
assertion->next = assertions;
|
|
||||||
assertions = assertion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fileSections);
|
free(fileSections);
|
||||||
@@ -706,4 +702,9 @@ void obj_Cleanup(void)
|
|||||||
freeSymbol(list.symbolList[i]);
|
freeSymbol(list.symbolList[i]);
|
||||||
free(list.symbolList);
|
free(list.symbolList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (struct Assertion &assert : assertions) {
|
||||||
|
free(assert.patch.rpnExpression);
|
||||||
|
free(assert.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: MIT */
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <deque>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -456,45 +457,39 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
#undef popRPN
|
#undef popRPN
|
||||||
}
|
}
|
||||||
|
|
||||||
void patch_CheckAssertions(struct Assertion *assert)
|
void patch_CheckAssertions(std::deque<struct Assertion> &assertions)
|
||||||
{
|
{
|
||||||
verbosePrint("Checking assertions...\n");
|
verbosePrint("Checking assertions...\n");
|
||||||
initRPNStack();
|
initRPNStack();
|
||||||
|
|
||||||
while (assert) {
|
for (struct Assertion &assert : assertions) {
|
||||||
int32_t value = computeRPNExpr(&assert->patch,
|
int32_t value = computeRPNExpr(&assert.patch,
|
||||||
(struct Symbol const * const *)assert->fileSymbols);
|
(struct Symbol const * const *)assert.fileSymbols);
|
||||||
enum AssertionType type = (enum AssertionType)assert->patch.type;
|
enum AssertionType type = (enum AssertionType)assert.patch.type;
|
||||||
|
|
||||||
if (!isError && !value) {
|
if (!isError && !value) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ASSERT_FATAL:
|
case ASSERT_FATAL:
|
||||||
fatal(assert->patch.src, assert->patch.lineNo, "%s",
|
fatal(assert.patch.src, assert.patch.lineNo, "%s",
|
||||||
assert->message[0] ? assert->message
|
assert.message[0] ? assert.message
|
||||||
: "assert failure");
|
: "assert failure");
|
||||||
case ASSERT_ERROR:
|
case ASSERT_ERROR:
|
||||||
error(assert->patch.src, assert->patch.lineNo, "%s",
|
error(assert.patch.src, assert.patch.lineNo, "%s",
|
||||||
assert->message[0] ? assert->message
|
assert.message[0] ? assert.message
|
||||||
: "assert failure");
|
: "assert failure");
|
||||||
break;
|
break;
|
||||||
case ASSERT_WARN:
|
case ASSERT_WARN:
|
||||||
warning(assert->patch.src, assert->patch.lineNo, "%s",
|
warning(assert.patch.src, assert.patch.lineNo, "%s",
|
||||||
assert->message[0] ? assert->message
|
assert.message[0] ? assert.message
|
||||||
: "assert failure");
|
: "assert failure");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (isError && type == ASSERT_FATAL) {
|
} else if (isError && type == ASSERT_FATAL) {
|
||||||
fatal(assert->patch.src, assert->patch.lineNo,
|
fatal(assert.patch.src, assert.patch.lineNo,
|
||||||
"Failed to evaluate assertion%s%s",
|
"Failed to evaluate assertion%s%s",
|
||||||
assert->message[0] ? ": " : "",
|
assert.message[0] ? ": " : "",
|
||||||
assert->message);
|
assert.message);
|
||||||
}
|
}
|
||||||
struct Assertion *next = assert->next;
|
|
||||||
|
|
||||||
free(assert->patch.rpnExpression);
|
|
||||||
free(assert->message);
|
|
||||||
free(assert);
|
|
||||||
assert = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
freeRPNStack();
|
freeRPNStack();
|
||||||
|
|||||||
Reference in New Issue
Block a user