Use std::deque for assertions

Also fix a memory leak
This commit is contained in:
Rangi42
2024-02-21 15:57:44 -05:00
committed by Sylvie
parent 2df4fff6c9
commit 26a93a530b
3 changed files with 28 additions and 34 deletions

View File

@@ -4,6 +4,7 @@
#ifndef RGBDS_LINK_PATCH_H
#define RGBDS_LINK_PATCH_H
#include <deque>
#include <stdint.h>
#include "link/section.hpp"
@@ -11,20 +12,17 @@
#include "linkdefs.hpp"
struct Assertion {
struct Patch patch;
// enum AssertionType type; The `patch`'s field is instead re-used
struct Patch patch; // Also used for its `.type`
char *message;
// This would be redundant with `.section->fileSymbols`... but `section` is sometimes NULL!
struct Symbol **fileSymbols;
struct Assertion *next;
};
/*
* Checks all assertions
* @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

View File

@@ -34,7 +34,7 @@ static struct FileStackNodes {
struct FileStackNode *nodes;
uint32_t nbNodes;
} *nodes;
static struct Assertion *assertions;
static std::deque<struct Assertion> assertions;
// 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);
verbosePrint("Reading %" PRIu32 " assertions...\n", nbAsserts);
for (uint32_t i = 0; i < nbAsserts; i++) {
struct Assertion *assertion = (struct Assertion *)malloc(sizeof(*assertion));
struct Assertion &assertion = assertions.emplace_front();
if (!assertion)
err("%s: Failed to create new assertion", fileName);
readAssertion(file, assertion, fileName, i, nodes[fileID].nodes);
linkPatchToPCSect(&assertion->patch, fileSections);
assertion->fileSymbols = fileSymbols;
assertion->next = assertions;
assertions = assertion;
readAssertion(file, &assertion, fileName, i, nodes[fileID].nodes);
linkPatchToPCSect(&assertion.patch, fileSections);
assertion.fileSymbols = fileSymbols;
}
free(fileSections);
@@ -706,4 +702,9 @@ void obj_Cleanup(void)
freeSymbol(list.symbolList[i]);
free(list.symbolList);
}
for (struct Assertion &assert : assertions) {
free(assert.patch.rpnExpression);
free(assert.message);
}
}

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: MIT */
#include <assert.h>
#include <deque>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
@@ -456,45 +457,39 @@ static int32_t computeRPNExpr(struct Patch const *patch,
#undef popRPN
}
void patch_CheckAssertions(struct Assertion *assert)
void patch_CheckAssertions(std::deque<struct Assertion> &assertions)
{
verbosePrint("Checking assertions...\n");
initRPNStack();
while (assert) {
int32_t value = computeRPNExpr(&assert->patch,
(struct Symbol const * const *)assert->fileSymbols);
enum AssertionType type = (enum AssertionType)assert->patch.type;
for (struct Assertion &assert : assertions) {
int32_t value = computeRPNExpr(&assert.patch,
(struct Symbol const * const *)assert.fileSymbols);
enum AssertionType type = (enum AssertionType)assert.patch.type;
if (!isError && !value) {
switch (type) {
case ASSERT_FATAL:
fatal(assert->patch.src, assert->patch.lineNo, "%s",
assert->message[0] ? assert->message
fatal(assert.patch.src, assert.patch.lineNo, "%s",
assert.message[0] ? assert.message
: "assert failure");
case ASSERT_ERROR:
error(assert->patch.src, assert->patch.lineNo, "%s",
assert->message[0] ? assert->message
error(assert.patch.src, assert.patch.lineNo, "%s",
assert.message[0] ? assert.message
: "assert failure");
break;
case ASSERT_WARN:
warning(assert->patch.src, assert->patch.lineNo, "%s",
assert->message[0] ? assert->message
warning(assert.patch.src, assert.patch.lineNo, "%s",
assert.message[0] ? assert.message
: "assert failure");
break;
}
} 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",
assert->message[0] ? ": " : "",
assert->message);
assert.message[0] ? ": " : "",
assert.message);
}
struct Assertion *next = assert->next;
free(assert->patch.rpnExpression);
free(assert->message);
free(assert);
assert = next;
}
freeRPNStack();