mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
No more flexible array members (not standard C++) (#1307)
* Replace FAMs with `std::vector`s (or one `std::string`) in four `struct`s * Anonymous types declared in an anonymous union are also non-standard Only Clang complains about this (-Wnested-anon-types)
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "asm/lexer.hpp"
|
#include "asm/lexer.hpp"
|
||||||
|
|
||||||
@@ -28,14 +29,12 @@ struct FileStackNode {
|
|||||||
|
|
||||||
struct FileStackReptNode { // NODE_REPT
|
struct FileStackReptNode { // NODE_REPT
|
||||||
struct FileStackNode node;
|
struct FileStackNode node;
|
||||||
uint32_t reptDepth;
|
std::vector<uint32_t> *iters; // REPT iteration counts since last named node, in reverse depth order
|
||||||
// WARNING: if changing this type, change overflow check in `fstk_Init`
|
|
||||||
uint32_t iters[]; // REPT iteration counts since last named node, in reverse depth order
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FileStackNamedNode { // NODE_FILE, NODE_MACRO
|
struct FileStackNamedNode { // NODE_FILE, NODE_MACRO
|
||||||
struct FileStackNode node;
|
struct FileStackNode node;
|
||||||
char name[]; // File name for files, file::macro name for macros
|
std::string *name; // File name for files, file::macro name for macros
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_MAX_DEPTH 64
|
#define DEFAULT_MAX_DEPTH 64
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ struct MacroArgs;
|
|||||||
|
|
||||||
struct MacroArgs *macro_GetCurrentArgs(void);
|
struct MacroArgs *macro_GetCurrentArgs(void);
|
||||||
struct MacroArgs *macro_NewArgs(void);
|
struct MacroArgs *macro_NewArgs(void);
|
||||||
void macro_AppendArg(struct MacroArgs **args, char *s);
|
void macro_AppendArg(struct MacroArgs *args, char *s);
|
||||||
void macro_UseNewArgs(struct MacroArgs *args);
|
void macro_UseNewArgs(struct MacroArgs *args);
|
||||||
void macro_FreeArgs(struct MacroArgs *args);
|
void macro_FreeArgs(struct MacroArgs *args);
|
||||||
char const *macro_GetArg(uint32_t i);
|
char const *macro_GetArg(uint32_t i);
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ enum SymbolType {
|
|||||||
SYM_REF // Forward reference to a label
|
SYM_REF // Forward reference to a label
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Only used in an anonymous union by `struct Symbol`
|
||||||
|
struct strValue {
|
||||||
|
size_t size;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
struct Symbol {
|
struct Symbol {
|
||||||
char name[MAXSYMLEN + 1];
|
char name[MAXSYMLEN + 1];
|
||||||
enum SymbolType type;
|
enum SymbolType type;
|
||||||
@@ -36,18 +42,12 @@ struct Symbol {
|
|||||||
union {
|
union {
|
||||||
// If sym_IsNumeric
|
// If sym_IsNumeric
|
||||||
int32_t value;
|
int32_t value;
|
||||||
int32_t (*numCallback)(void);
|
int32_t (*numCallback)(void); // If hasCallback
|
||||||
// For SYM_MACRO
|
// For SYM_MACRO
|
||||||
struct {
|
struct strValue macro;
|
||||||
size_t size;
|
|
||||||
char *value;
|
|
||||||
} macro;
|
|
||||||
// For SYM_EQUS
|
// For SYM_EQUS
|
||||||
struct {
|
struct strValue equs;
|
||||||
size_t size;
|
char const *(*strCallback)(void); // If hasCallback
|
||||||
char *value;
|
|
||||||
} equs;
|
|
||||||
char const *(*strCallback)(void);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t ID; // ID of the symbol in the object file (-1 if none)
|
uint32_t ID; // ID of the symbol in the object file (-1 if none)
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ extern bool beVerbose;
|
|||||||
extern bool isWRA0Mode;
|
extern bool isWRA0Mode;
|
||||||
extern bool disablePadding;
|
extern bool disablePadding;
|
||||||
|
|
||||||
|
// Only used in an anonymous union by `struct FileStackNode`
|
||||||
|
struct reptNodeData {
|
||||||
|
uint32_t depth;
|
||||||
|
uint32_t *iters;
|
||||||
|
};
|
||||||
|
|
||||||
struct FileStackNode {
|
struct FileStackNode {
|
||||||
struct FileStackNode *parent;
|
struct FileStackNode *parent;
|
||||||
// Line at which the parent context was exited; meaningless for the root level
|
// Line at which the parent context was exited; meaningless for the root level
|
||||||
@@ -36,10 +42,7 @@ struct FileStackNode {
|
|||||||
enum FileStackNodeType type;
|
enum FileStackNodeType type;
|
||||||
union {
|
union {
|
||||||
char *name; // NODE_FILE, NODE_MACRO
|
char *name; // NODE_FILE, NODE_MACRO
|
||||||
struct { // NODE_REPT
|
struct reptNodeData rept; // NODE_REPT
|
||||||
uint32_t depth;
|
|
||||||
uint32_t *iters;
|
|
||||||
} rept;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
/* SPDX-License-Identifier: MIT */
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <new>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "asm/charmap.hpp"
|
#include "asm/charmap.hpp"
|
||||||
#include "asm/main.hpp"
|
#include "asm/main.hpp"
|
||||||
@@ -25,13 +27,9 @@ struct Charnode {
|
|||||||
size_t next[255]; // Indexes of where to go next, 0 = nowhere
|
size_t next[255]; // Indexes of where to go next, 0 = nowhere
|
||||||
};
|
};
|
||||||
|
|
||||||
#define INITIAL_CAPACITY 32
|
|
||||||
|
|
||||||
struct Charmap {
|
struct Charmap {
|
||||||
char *name;
|
char *name;
|
||||||
size_t usedNodes; // How many nodes are being used
|
std::vector<struct Charnode> *nodes; // first node is reserved for the root node
|
||||||
size_t capacity; // How many nodes have been allocated
|
|
||||||
struct Charnode nodes[]; // first node is reserved for the root node
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static HashMap charmaps;
|
static HashMap charmaps;
|
||||||
@@ -52,16 +50,6 @@ static struct Charmap *charmap_Get(char const *name)
|
|||||||
return (struct Charmap *)hash_GetElement(charmaps, name);
|
return (struct Charmap *)hash_GetElement(charmaps, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resizeCharmap(struct Charmap **map, size_t capacity)
|
|
||||||
{
|
|
||||||
*map = (struct Charmap *)realloc(*map, sizeof(**map) + sizeof(*(*map)->nodes) * capacity);
|
|
||||||
|
|
||||||
if (!*map)
|
|
||||||
fatalerror("Failed to %s charmap: %s\n",
|
|
||||||
*map ? "create" : "resize", strerror(errno));
|
|
||||||
(**map).capacity = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void initNode(struct Charnode *node)
|
static void initNode(struct Charnode *node)
|
||||||
{
|
{
|
||||||
node->isTerminal = false;
|
node->isTerminal = false;
|
||||||
@@ -87,15 +75,17 @@ struct Charmap *charmap_New(char const *name, char const *baseName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init the new charmap's fields
|
// Init the new charmap's fields
|
||||||
if (base) {
|
charmap = (struct Charmap *)malloc(sizeof(*charmap));
|
||||||
resizeCharmap(&charmap, base->capacity);
|
if (charmap)
|
||||||
charmap->usedNodes = base->usedNodes;
|
charmap->nodes = new(std::nothrow) std::vector<struct Charnode>();
|
||||||
|
if (!charmap || !charmap->nodes)
|
||||||
|
fatalerror("Failed to create charmap: %s\n", strerror(errno));
|
||||||
|
|
||||||
memcpy(charmap->nodes, base->nodes, sizeof(base->nodes[0]) * charmap->usedNodes);
|
if (base) {
|
||||||
|
*charmap->nodes = *base->nodes; // Copies `base->nodes`
|
||||||
} else {
|
} else {
|
||||||
resizeCharmap(&charmap, INITIAL_CAPACITY);
|
charmap->nodes->emplace_back();
|
||||||
charmap->usedNodes = 1;
|
initNode(&charmap->nodes->back()); // Init the root node
|
||||||
initNode(&charmap->nodes[0]); // Init the root node
|
|
||||||
}
|
}
|
||||||
charmap->name = strdup(name);
|
charmap->name = strdup(name);
|
||||||
|
|
||||||
@@ -109,6 +99,7 @@ static void freeCharmap(void *_charmap, void *)
|
|||||||
struct Charmap *charmap = (struct Charmap *)_charmap;
|
struct Charmap *charmap = (struct Charmap *)_charmap;
|
||||||
|
|
||||||
free(charmap->name);
|
free(charmap->name);
|
||||||
|
delete charmap->nodes;
|
||||||
free(charmap);
|
free(charmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,25 +148,19 @@ void charmap_Pop(void)
|
|||||||
void charmap_Add(char *mapping, uint8_t value)
|
void charmap_Add(char *mapping, uint8_t value)
|
||||||
{
|
{
|
||||||
struct Charmap *charmap = *currentCharmap;
|
struct Charmap *charmap = *currentCharmap;
|
||||||
struct Charnode *node = &charmap->nodes[0];
|
struct Charnode *node = &charmap->nodes->front();
|
||||||
|
|
||||||
for (uint8_t c; *mapping; mapping++) {
|
for (uint8_t c; *mapping; mapping++) {
|
||||||
c = *mapping - 1;
|
c = *mapping - 1;
|
||||||
|
|
||||||
if (node->next[c]) {
|
if (node->next[c]) {
|
||||||
node = &charmap->nodes[node->next[c]];
|
node = &(*charmap->nodes)[node->next[c]];
|
||||||
} else {
|
} else {
|
||||||
// Register next available node
|
// Register next available node
|
||||||
node->next[c] = charmap->usedNodes;
|
node->next[c] = charmap->nodes->size();
|
||||||
// If no more nodes are available, get new ones
|
|
||||||
if (charmap->usedNodes == charmap->capacity) {
|
|
||||||
charmap->capacity *= 2;
|
|
||||||
resizeCharmap(currentCharmap, charmap->capacity);
|
|
||||||
charmap = *currentCharmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch to and init new node
|
// Switch to and init new node
|
||||||
node = &charmap->nodes[charmap->usedNodes++];
|
node = &charmap->nodes->emplace_back();
|
||||||
initNode(node);
|
initNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,14 +175,14 @@ void charmap_Add(char *mapping, uint8_t value)
|
|||||||
bool charmap_HasChar(char const *input)
|
bool charmap_HasChar(char const *input)
|
||||||
{
|
{
|
||||||
struct Charmap const *charmap = *currentCharmap;
|
struct Charmap const *charmap = *currentCharmap;
|
||||||
struct Charnode const *node = &charmap->nodes[0];
|
struct Charnode const *node = &charmap->nodes->front();
|
||||||
|
|
||||||
for (; *input; input++) {
|
for (; *input; input++) {
|
||||||
size_t next = node->next[(uint8_t)*input - 1];
|
size_t next = node->next[(uint8_t)*input - 1];
|
||||||
|
|
||||||
if (!next)
|
if (!next)
|
||||||
return false;
|
return false;
|
||||||
node = &charmap->nodes[next];
|
node = &(*charmap->nodes)[next];
|
||||||
}
|
}
|
||||||
|
|
||||||
return node->isTerminal;
|
return node->isTerminal;
|
||||||
@@ -220,7 +205,7 @@ size_t charmap_ConvertNext(char const **input, uint8_t **output)
|
|||||||
// If that would lead to a dead end, rewind characters until the last match, and output.
|
// If that would lead to a dead end, rewind characters until the last match, and output.
|
||||||
// If no match, read a UTF-8 codepoint and output that.
|
// If no match, read a UTF-8 codepoint and output that.
|
||||||
struct Charmap const *charmap = *currentCharmap;
|
struct Charmap const *charmap = *currentCharmap;
|
||||||
struct Charnode const *node = &charmap->nodes[0];
|
struct Charnode const *node = &charmap->nodes->front();
|
||||||
struct Charnode const *match = NULL;
|
struct Charnode const *match = NULL;
|
||||||
size_t rewindDistance = 0;
|
size_t rewindDistance = 0;
|
||||||
|
|
||||||
@@ -233,7 +218,7 @@ size_t charmap_ConvertNext(char const **input, uint8_t **output)
|
|||||||
rewindDistance++;
|
rewindDistance++;
|
||||||
|
|
||||||
// Advance to next node (index starts at 1)
|
// Advance to next node (index starts at 1)
|
||||||
node = &charmap->nodes[node->next[c]];
|
node = &(*charmap->nodes)[node->next[c]];
|
||||||
if (node->isTerminal) {
|
if (node->isTerminal) {
|
||||||
// This node matches, register it
|
// This node matches, register it
|
||||||
match = node;
|
match = node;
|
||||||
@@ -265,7 +250,7 @@ size_t charmap_ConvertNext(char const **input, uint8_t **output)
|
|||||||
*output += codepointLen;
|
*output += codepointLen;
|
||||||
|
|
||||||
// Warn if this character is not mapped but any others are
|
// Warn if this character is not mapped but any others are
|
||||||
if (charmap->usedNodes > 1)
|
if (charmap->nodes->size() > 1)
|
||||||
warning(WARNING_UNMAPPED_CHAR_1,
|
warning(WARNING_UNMAPPED_CHAR_1,
|
||||||
"Unmapped character %s\n", printChar(firstChar));
|
"Unmapped character %s\n", printChar(firstChar));
|
||||||
else if (strcmp(charmap->name, DEFAULT_CHARMAP_NAME))
|
else if (strcmp(charmap->name, DEFAULT_CHARMAP_NAME))
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: MIT */
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <new>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "asm/fstack.hpp"
|
#include "asm/fstack.hpp"
|
||||||
#include "asm/macro.hpp"
|
#include "asm/macro.hpp"
|
||||||
@@ -51,10 +53,10 @@ static const char *dumpNodeAndParents(struct FileStackNode const *node)
|
|||||||
|
|
||||||
name = dumpNodeAndParents(node->parent);
|
name = dumpNodeAndParents(node->parent);
|
||||||
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
|
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
|
||||||
for (uint32_t i = reptInfo->reptDepth; i--; )
|
for (uint32_t i = reptInfo->iters->size(); i--; )
|
||||||
fprintf(stderr, "::REPT~%" PRIu32, reptInfo->iters[i]);
|
fprintf(stderr, "::REPT~%" PRIu32, (*reptInfo->iters)[i]);
|
||||||
} else {
|
} else {
|
||||||
name = ((struct FileStackNamedNode const *)node)->name;
|
name = ((struct FileStackNamedNode const *)node)->name->c_str();
|
||||||
if (node->parent) {
|
if (node->parent) {
|
||||||
dumpNodeAndParents(node->parent);
|
dumpNodeAndParents(node->parent);
|
||||||
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
|
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
|
||||||
@@ -103,7 +105,7 @@ char const *fstk_GetFileName(void)
|
|||||||
|
|
||||||
while (node->type != NODE_FILE)
|
while (node->type != NODE_FILE)
|
||||||
node = node->parent;
|
node = node->parent;
|
||||||
return ((struct FileStackNamedNode const *)node)->name;
|
return ((struct FileStackNamedNode const *)node)->name->c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fstk_AddIncludePath(char const *path)
|
void fstk_AddIncludePath(char const *path)
|
||||||
@@ -199,13 +201,16 @@ bool yywrap(void)
|
|||||||
|
|
||||||
// If the node is referenced, we can't edit it; duplicate it
|
// If the node is referenced, we can't edit it; duplicate it
|
||||||
if (contextStack->fileInfo->referenced) {
|
if (contextStack->fileInfo->referenced) {
|
||||||
size_t size = sizeof(*fileInfo) + sizeof(fileInfo->iters[0]) * fileInfo->reptDepth;
|
struct FileStackReptNode *copy = (struct FileStackReptNode *)malloc(sizeof(*copy));
|
||||||
struct FileStackReptNode *copy = (struct FileStackReptNode *)malloc(size);
|
|
||||||
|
|
||||||
if (!copy)
|
|
||||||
fatalerror("Failed to duplicate REPT file node: %s\n", strerror(errno));
|
|
||||||
// Copy all info but the referencing
|
// Copy all info but the referencing
|
||||||
memcpy(copy, fileInfo, size);
|
if (copy) {
|
||||||
|
memcpy(copy, fileInfo, sizeof(*copy));
|
||||||
|
copy->iters = new(std::nothrow) std::vector<uint32_t>();
|
||||||
|
}
|
||||||
|
if (!copy || !copy->iters)
|
||||||
|
fatalerror("Failed to duplicate REPT file node: %s\n", strerror(errno));
|
||||||
|
*copy->iters = *fileInfo->iters; // Copies `fileInfo->iters`
|
||||||
copy->node.next = NULL;
|
copy->node.next = NULL;
|
||||||
copy->node.referenced = false;
|
copy->node.referenced = false;
|
||||||
|
|
||||||
@@ -214,7 +219,7 @@ bool yywrap(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this is a FOR, update the symbol value
|
// If this is a FOR, update the symbol value
|
||||||
if (contextStack->forName && fileInfo->iters[0] <= contextStack->nbReptIters) {
|
if (contextStack->forName && fileInfo->iters->front() <= contextStack->nbReptIters) {
|
||||||
// Avoid arithmetic overflow runtime error
|
// Avoid arithmetic overflow runtime error
|
||||||
uint32_t forValue = (uint32_t)contextStack->forValue +
|
uint32_t forValue = (uint32_t)contextStack->forValue +
|
||||||
(uint32_t)contextStack->forStep;
|
(uint32_t)contextStack->forStep;
|
||||||
@@ -228,9 +233,9 @@ bool yywrap(void)
|
|||||||
fatalerror("Failed to update FOR symbol value\n");
|
fatalerror("Failed to update FOR symbol value\n");
|
||||||
}
|
}
|
||||||
// Advance to the next iteration
|
// Advance to the next iteration
|
||||||
fileInfo->iters[0]++;
|
fileInfo->iters->front()++;
|
||||||
// If this wasn't the last iteration, wrap instead of popping
|
// If this wasn't the last iteration, wrap instead of popping
|
||||||
if (fileInfo->iters[0] <= contextStack->nbReptIters) {
|
if (fileInfo->iters->front() <= contextStack->nbReptIters) {
|
||||||
lexer_RestartRept(contextStack->fileInfo->lineNo);
|
lexer_RestartRept(contextStack->fileInfo->lineNo);
|
||||||
contextStack->uniqueID = macro_UseNewUniqueID();
|
contextStack->uniqueID = macro_UseNewUniqueID();
|
||||||
return false;
|
return false;
|
||||||
@@ -252,8 +257,13 @@ bool yywrap(void)
|
|||||||
macro_UseNewArgs(contextStack->macroArgs);
|
macro_UseNewArgs(contextStack->macroArgs);
|
||||||
}
|
}
|
||||||
// Free the file stack node
|
// Free the file stack node
|
||||||
if (!context->fileInfo->referenced)
|
if (!context->fileInfo->referenced) {
|
||||||
|
if (context->fileInfo->type == NODE_REPT)
|
||||||
|
delete ((struct FileStackReptNode *)context->fileInfo)->iters;
|
||||||
|
else
|
||||||
|
delete ((struct FileStackNamedNode *)context->fileInfo)->name;
|
||||||
free(context->fileInfo);
|
free(context->fileInfo);
|
||||||
|
}
|
||||||
// Free the FOR symbol name
|
// Free the FOR symbol name
|
||||||
free(context->forName);
|
free(context->forName);
|
||||||
// Free the entry and make its parent the current entry
|
// Free the entry and make its parent the current entry
|
||||||
@@ -309,19 +319,17 @@ void fstk_RunInclude(char const *path)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileStackNamedNode *fileInfo =
|
struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo));
|
||||||
(struct FileStackNamedNode *)malloc(sizeof(*fileInfo) + fullPath->length() + 1);
|
|
||||||
|
|
||||||
if (!fileInfo) {
|
if (!fileInfo) {
|
||||||
error("Failed to alloc file info for INCLUDE: %s\n", strerror(errno));
|
error("Failed to alloc file info for INCLUDE: %s\n", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fileInfo->node.type = NODE_FILE;
|
fileInfo->node.type = NODE_FILE;
|
||||||
strcpy(fileInfo->name, fullPath->c_str());
|
fileInfo->name = fullPath; // `fullPath` is already `new`-allocated, so just point to it
|
||||||
delete fullPath;
|
|
||||||
|
|
||||||
newContext((struct FileStackNode *)fileInfo);
|
newContext((struct FileStackNode *)fileInfo);
|
||||||
contextStack->lexerState = lexer_OpenFile(fileInfo->name);
|
contextStack->lexerState = lexer_OpenFile(fileInfo->name->c_str());
|
||||||
if (!contextStack->lexerState)
|
if (!contextStack->lexerState)
|
||||||
fatalerror("Failed to set up lexer for file include\n");
|
fatalerror("Failed to set up lexer for file include\n");
|
||||||
lexer_SetStateAtEOL(contextStack->lexerState);
|
lexer_SetStateAtEOL(contextStack->lexerState);
|
||||||
@@ -345,19 +353,17 @@ static void runPreIncludeFile(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileStackNamedNode *fileInfo =
|
struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo));
|
||||||
(struct FileStackNamedNode *)malloc(sizeof(*fileInfo) + fullPath->length() + 1);
|
|
||||||
|
|
||||||
if (!fileInfo) {
|
if (!fileInfo) {
|
||||||
error("Failed to alloc file info for pre-include: %s\n", strerror(errno));
|
error("Failed to alloc file info for pre-include: %s\n", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fileInfo->node.type = NODE_FILE;
|
fileInfo->node.type = NODE_FILE;
|
||||||
strcpy(fileInfo->name, fullPath->c_str());
|
fileInfo->name = fullPath; // `fullPath` is already `new`-allocated, so just point to it
|
||||||
delete fullPath;
|
|
||||||
|
|
||||||
newContext((struct FileStackNode *)fileInfo);
|
newContext((struct FileStackNode *)fileInfo);
|
||||||
contextStack->lexerState = lexer_OpenFile(fileInfo->name);
|
contextStack->lexerState = lexer_OpenFile(fileInfo->name->c_str());
|
||||||
if (!contextStack->lexerState)
|
if (!contextStack->lexerState)
|
||||||
fatalerror("Failed to set up lexer for file include\n");
|
fatalerror("Failed to set up lexer for file include\n");
|
||||||
lexer_SetState(contextStack->lexerState);
|
lexer_SetState(contextStack->lexerState);
|
||||||
@@ -387,43 +393,41 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
|
|||||||
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
|
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
|
||||||
|
|
||||||
// 4294967295 = 2^32 - 1, aka UINT32_MAX
|
// 4294967295 = 2^32 - 1, aka UINT32_MAX
|
||||||
reptNameLen += reptNode->reptDepth * strlen("::REPT~4294967295");
|
reptNameLen += reptNode->iters->size() * strlen("::REPT~4294967295");
|
||||||
// Look for next named node
|
// Look for next named node
|
||||||
do {
|
do {
|
||||||
node = node->parent;
|
node = node->parent;
|
||||||
} while (node->type == NODE_REPT);
|
} while (node->type == NODE_REPT);
|
||||||
}
|
}
|
||||||
struct FileStackNamedNode const *baseNode = (struct FileStackNamedNode const *)node;
|
|
||||||
size_t baseLen = strlen(baseNode->name);
|
|
||||||
size_t macroNameLen = strlen(macro->name);
|
|
||||||
struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo) +
|
|
||||||
baseLen + reptNameLen + 2 + macroNameLen + 1);
|
|
||||||
|
|
||||||
if (!fileInfo) {
|
struct FileStackNamedNode const *baseNode = (struct FileStackNamedNode const *)node;
|
||||||
|
struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo));
|
||||||
|
|
||||||
|
if (fileInfo)
|
||||||
|
fileInfo->name = new(std::nothrow) std::string();
|
||||||
|
if (!fileInfo || !fileInfo->name) {
|
||||||
error("Failed to alloc file info for \"%s\": %s\n", macro->name, strerror(errno));
|
error("Failed to alloc file info for \"%s\": %s\n", macro->name, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fileInfo->node.type = NODE_MACRO;
|
fileInfo->node.type = NODE_MACRO;
|
||||||
// Print the name...
|
|
||||||
char *dest = fileInfo->name;
|
|
||||||
|
|
||||||
memcpy(dest, baseNode->name, baseLen);
|
// Print the name...
|
||||||
dest += baseLen;
|
fileInfo->name->reserve(baseNode->name->length() + reptNameLen + 2 + strlen(macro->name));
|
||||||
|
fileInfo->name->append(*baseNode->name);
|
||||||
if (node->type == NODE_REPT) {
|
if (node->type == NODE_REPT) {
|
||||||
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
|
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
|
||||||
|
|
||||||
for (uint32_t i = reptNode->reptDepth; i--; ) {
|
for (uint32_t i = reptNode->iters->size(); i--; ) {
|
||||||
int nbChars = sprintf(dest, "::REPT~%" PRIu32, reptNode->iters[i]);
|
char buf[sizeof("::REPT~4294967295")]; // UINT32_MAX
|
||||||
|
|
||||||
if (nbChars < 0)
|
if (sprintf(buf, "::REPT~%" PRIu32, (*reptNode->iters)[i]) < 0)
|
||||||
fatalerror("Failed to write macro invocation info: %s\n",
|
fatalerror("Failed to write macro invocation info: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
dest += nbChars;
|
fileInfo->name->append(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*dest++ = ':';
|
fileInfo->name->append("::");
|
||||||
*dest++ = ':';
|
fileInfo->name->append(macro->name);
|
||||||
memcpy(dest, macro->name, macroNameLen + 1);
|
|
||||||
|
|
||||||
newContext((struct FileStackNode *)fileInfo);
|
newContext((struct FileStackNode *)fileInfo);
|
||||||
contextStack->lexerState = lexer_OpenFileView("MACRO", macro->macro.value, macro->macro.size,
|
contextStack->lexerState = lexer_OpenFileView("MACRO", macro->macro.value, macro->macro.size,
|
||||||
@@ -438,23 +442,22 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
|
|||||||
static bool newReptContext(int32_t reptLineNo, char *body, size_t size)
|
static bool newReptContext(int32_t reptLineNo, char *body, size_t size)
|
||||||
{
|
{
|
||||||
uint32_t reptDepth = contextStack->fileInfo->type == NODE_REPT
|
uint32_t reptDepth = contextStack->fileInfo->type == NODE_REPT
|
||||||
? ((struct FileStackReptNode *)contextStack->fileInfo)->reptDepth
|
? ((struct FileStackReptNode *)contextStack->fileInfo)->iters->size()
|
||||||
: 0;
|
: 0;
|
||||||
struct FileStackReptNode *fileInfo = (struct FileStackReptNode *)malloc(sizeof(*fileInfo)
|
struct FileStackReptNode *fileInfo = (struct FileStackReptNode *)malloc(sizeof(*fileInfo));
|
||||||
+ (reptDepth + 1) * sizeof(fileInfo->iters[0]));
|
|
||||||
|
|
||||||
if (!fileInfo) {
|
if (fileInfo)
|
||||||
|
fileInfo->iters = new std::vector<uint32_t>();
|
||||||
|
if (!fileInfo || !fileInfo->iters) {
|
||||||
error("Failed to alloc file info for REPT: %s\n", strerror(errno));
|
error("Failed to alloc file info for REPT: %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fileInfo->node.type = NODE_REPT;
|
fileInfo->node.type = NODE_REPT;
|
||||||
fileInfo->reptDepth = reptDepth + 1;
|
if (reptDepth) {
|
||||||
fileInfo->iters[0] = 1;
|
|
||||||
if (reptDepth)
|
|
||||||
// Copy all parent iter counts
|
// Copy all parent iter counts
|
||||||
memcpy(&fileInfo->iters[1],
|
*fileInfo->iters = *((struct FileStackReptNode *)contextStack->fileInfo)->iters;
|
||||||
((struct FileStackReptNode *)contextStack->fileInfo)->iters,
|
}
|
||||||
reptDepth * sizeof(fileInfo->iters[0]));
|
fileInfo->iters->insert(fileInfo->iters->begin(), 1);
|
||||||
|
|
||||||
newContext((struct FileStackNode *)fileInfo);
|
newContext((struct FileStackNode *)fileInfo);
|
||||||
// Correct our line number, which currently points to the `ENDR` line
|
// Correct our line number, which currently points to the `ENDR` line
|
||||||
@@ -545,23 +548,22 @@ void fstk_Init(char const *mainPath, size_t maxDepth)
|
|||||||
fatalerror("Failed to open main file\n");
|
fatalerror("Failed to open main file\n");
|
||||||
lexer_SetState(state);
|
lexer_SetState(state);
|
||||||
char const *fileName = lexer_GetFileName();
|
char const *fileName = lexer_GetFileName();
|
||||||
size_t len = strlen(fileName);
|
|
||||||
struct Context *context = (struct Context *)malloc(sizeof(*contextStack));
|
struct Context *context = (struct Context *)malloc(sizeof(*contextStack));
|
||||||
struct FileStackNamedNode *fileInfo =
|
struct FileStackNamedNode *fileInfo = (struct FileStackNamedNode *)malloc(sizeof(*fileInfo));
|
||||||
(struct FileStackNamedNode *)malloc(sizeof(*fileInfo) + len + 1);
|
|
||||||
|
|
||||||
if (!context)
|
if (!context)
|
||||||
fatalerror("Failed to allocate memory for main context: %s\n", strerror(errno));
|
fatalerror("Failed to allocate memory for main context: %s\n", strerror(errno));
|
||||||
if (!fileInfo)
|
if (fileInfo)
|
||||||
|
fileInfo->name = new(std::nothrow) std::string(fileName);
|
||||||
|
if (!fileInfo || !fileInfo->name)
|
||||||
fatalerror("Failed to allocate memory for main file info: %s\n", strerror(errno));
|
fatalerror("Failed to allocate memory for main file info: %s\n", strerror(errno));
|
||||||
|
|
||||||
context->fileInfo = (struct FileStackNode *)fileInfo;
|
context->fileInfo = (struct FileStackNode *)fileInfo;
|
||||||
// lineNo and reptIter are unused on the top-level context
|
// lineNo and nbReptIters are unused on the top-level context
|
||||||
context->fileInfo->parent = NULL;
|
context->fileInfo->parent = NULL;
|
||||||
context->fileInfo->lineNo = 0; // This still gets written to the object file, so init it
|
context->fileInfo->lineNo = 0; // This still gets written to the object file, so init it
|
||||||
context->fileInfo->referenced = false;
|
context->fileInfo->referenced = false;
|
||||||
context->fileInfo->type = NODE_FILE;
|
context->fileInfo->type = NODE_FILE;
|
||||||
memcpy(fileInfo->name, fileName, len + 1);
|
|
||||||
|
|
||||||
context->parent = NULL;
|
context->parent = NULL;
|
||||||
context->lexerState = state;
|
context->lexerState = state;
|
||||||
@@ -574,19 +576,7 @@ void fstk_Init(char const *mainPath, size_t maxDepth)
|
|||||||
// Now that it's set up properly, register the context
|
// Now that it's set up properly, register the context
|
||||||
contextStack = context;
|
contextStack = context;
|
||||||
|
|
||||||
// Check that max recursion depth won't allow overflowing node `malloc`s
|
|
||||||
// This assumes that the rept node is larger
|
|
||||||
#define DEPTH_LIMIT ((SIZE_MAX - sizeof(struct FileStackReptNode)) / sizeof(uint32_t))
|
|
||||||
if (maxDepth > DEPTH_LIMIT) {
|
|
||||||
error("Recursion depth may not be higher than %zu, defaulting to "
|
|
||||||
EXPAND_AND_STR(DEFAULT_MAX_DEPTH) "\n", DEPTH_LIMIT);
|
|
||||||
maxRecursionDepth = DEFAULT_MAX_DEPTH;
|
|
||||||
} else {
|
|
||||||
maxRecursionDepth = maxDepth;
|
maxRecursionDepth = maxDepth;
|
||||||
}
|
|
||||||
// Make sure that the default of 64 is OK, though
|
|
||||||
assert(DEPTH_LIMIT >= DEFAULT_MAX_DEPTH);
|
|
||||||
#undef DEPTH_LIMIT
|
|
||||||
|
|
||||||
runPreIncludeFile();
|
runPreIncludeFile();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,24 +308,28 @@ struct IfStack {
|
|||||||
bool reachedElseBlock; // Whether an ELSE block ran already
|
bool reachedElseBlock; // Whether an ELSE block ran already
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MmappedLexerState {
|
||||||
|
char *ptr; // Technically `const` during the lexer's execution
|
||||||
|
size_t size;
|
||||||
|
size_t offset;
|
||||||
|
bool isReferenced; // If a macro in this file requires not unmapping it
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BufferedLexerState {
|
||||||
|
int fd;
|
||||||
|
size_t index; // Read index into the buffer
|
||||||
|
char buf[LEXER_BUF_SIZE]; // Circular buffer
|
||||||
|
size_t nbChars; // Number of "fresh" chars in the buffer
|
||||||
|
};
|
||||||
|
|
||||||
struct LexerState {
|
struct LexerState {
|
||||||
char const *path;
|
char const *path;
|
||||||
|
|
||||||
// mmap()-dependent IO state
|
// mmap()-dependent IO state
|
||||||
bool isMmapped;
|
bool isMmapped;
|
||||||
union {
|
union {
|
||||||
struct { // If mmap()ed
|
struct MmappedLexerState mmap; // If mmap()ed
|
||||||
char *ptr; // Technically `const` during the lexer's execution
|
struct BufferedLexerState cbuf; // Otherwise
|
||||||
size_t size;
|
|
||||||
size_t offset;
|
|
||||||
bool isReferenced; // If a macro in this file requires not unmapping it
|
|
||||||
} mmap;
|
|
||||||
struct { // Otherwise
|
|
||||||
int fd;
|
|
||||||
size_t index; // Read index into the buffer
|
|
||||||
char buf[LEXER_BUF_SIZE]; // Circular buffer
|
|
||||||
size_t nbChars; // Number of "fresh" chars in the buffer
|
|
||||||
} cbuf;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Common state
|
// Common state
|
||||||
|
|||||||
@@ -1,33 +1,24 @@
|
|||||||
/* SPDX-License-Identifier: MIT */
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <new>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "asm/macro.hpp"
|
#include "asm/macro.hpp"
|
||||||
#include "asm/warning.hpp"
|
#include "asm/warning.hpp"
|
||||||
|
|
||||||
#define MAXMACROARGS 99999
|
#define MAXMACROARGS 99999
|
||||||
|
|
||||||
// Your average macro invocation does not go past the tens, but some go further
|
|
||||||
// This ensures that sane and slightly insane invocations suffer no penalties,
|
|
||||||
// and the rest is insane and thus will assume responsibility.
|
|
||||||
// Additionally, ~300 bytes (on x64) of memory per level of nesting has been
|
|
||||||
// deemed reasonable. (Halve that on x86.)
|
|
||||||
#define INITIAL_ARG_SIZE 32
|
|
||||||
struct MacroArgs {
|
struct MacroArgs {
|
||||||
unsigned int nbArgs;
|
|
||||||
unsigned int shift;
|
unsigned int shift;
|
||||||
unsigned int capacity;
|
std::vector<char *> *args;
|
||||||
char *args[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SIZEOF_ARGS(nbArgs) (sizeof(struct MacroArgs) + \
|
|
||||||
sizeof(((struct MacroArgs *)0)->args[0]) * (nbArgs))
|
|
||||||
|
|
||||||
static struct MacroArgs *macroArgs = NULL;
|
static struct MacroArgs *macroArgs = NULL;
|
||||||
static uint32_t uniqueID = 0;
|
static uint32_t uniqueID = 0;
|
||||||
static uint32_t maxUniqueID = 0;
|
static uint32_t maxUniqueID = 0;
|
||||||
@@ -44,35 +35,24 @@ struct MacroArgs *macro_GetCurrentArgs(void)
|
|||||||
|
|
||||||
struct MacroArgs *macro_NewArgs(void)
|
struct MacroArgs *macro_NewArgs(void)
|
||||||
{
|
{
|
||||||
struct MacroArgs *args = (struct MacroArgs *)malloc(SIZEOF_ARGS(INITIAL_ARG_SIZE));
|
struct MacroArgs *args = (struct MacroArgs *)malloc(sizeof(*args));
|
||||||
|
|
||||||
if (!args)
|
if (args)
|
||||||
|
args->args = new(std::nothrow) std::vector<char *>();
|
||||||
|
if (!args || !args->args)
|
||||||
fatalerror("Unable to register macro arguments: %s\n", strerror(errno));
|
fatalerror("Unable to register macro arguments: %s\n", strerror(errno));
|
||||||
|
|
||||||
args->nbArgs = 0;
|
|
||||||
args->shift = 0;
|
args->shift = 0;
|
||||||
args->capacity = INITIAL_ARG_SIZE;
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
void macro_AppendArg(struct MacroArgs **argPtr, char *s)
|
void macro_AppendArg(struct MacroArgs *args, char *s)
|
||||||
{
|
{
|
||||||
#define macArgs (*argPtr)
|
|
||||||
if (s[0] == '\0')
|
if (s[0] == '\0')
|
||||||
warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n");
|
warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n");
|
||||||
if (macArgs->nbArgs == MAXMACROARGS)
|
if (args->args->size() == MAXMACROARGS)
|
||||||
error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n");
|
error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n");
|
||||||
if (macArgs->nbArgs >= macArgs->capacity) {
|
args->args->push_back(s);
|
||||||
macArgs->capacity *= 2;
|
|
||||||
// Check that overflow didn't roll us back
|
|
||||||
if (macArgs->capacity <= macArgs->nbArgs)
|
|
||||||
fatalerror("Failed to add new macro argument: capacity overflow\n");
|
|
||||||
macArgs = (struct MacroArgs *)realloc(macArgs, SIZEOF_ARGS(macArgs->capacity));
|
|
||||||
if (!macArgs)
|
|
||||||
fatalerror("Error adding new macro argument: %s\n", strerror(errno));
|
|
||||||
}
|
|
||||||
macArgs->args[macArgs->nbArgs++] = s;
|
|
||||||
#undef macArgs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void macro_UseNewArgs(struct MacroArgs *args)
|
void macro_UseNewArgs(struct MacroArgs *args)
|
||||||
@@ -82,8 +62,9 @@ void macro_UseNewArgs(struct MacroArgs *args)
|
|||||||
|
|
||||||
void macro_FreeArgs(struct MacroArgs *args)
|
void macro_FreeArgs(struct MacroArgs *args)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < macroArgs->nbArgs; i++)
|
for (char *arg : *macroArgs->args)
|
||||||
free(args->args[i]);
|
free(arg);
|
||||||
|
delete args->args;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *macro_GetArg(uint32_t i)
|
char const *macro_GetArg(uint32_t i)
|
||||||
@@ -93,8 +74,7 @@ char const *macro_GetArg(uint32_t i)
|
|||||||
|
|
||||||
uint32_t realIndex = i + macroArgs->shift - 1;
|
uint32_t realIndex = i + macroArgs->shift - 1;
|
||||||
|
|
||||||
return realIndex >= macroArgs->nbArgs ? NULL
|
return realIndex >= macroArgs->args->size() ? NULL : (*macroArgs->args)[realIndex];
|
||||||
: macroArgs->args[realIndex];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *macro_GetAllArgs(void)
|
char const *macro_GetAllArgs(void)
|
||||||
@@ -102,13 +82,15 @@ char const *macro_GetAllArgs(void)
|
|||||||
if (!macroArgs)
|
if (!macroArgs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (macroArgs->shift >= macroArgs->nbArgs)
|
size_t nbArgs = macroArgs->args->size();
|
||||||
|
|
||||||
|
if (macroArgs->shift >= nbArgs)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
for (uint32_t i = macroArgs->shift; i < macroArgs->nbArgs; i++)
|
for (uint32_t i = macroArgs->shift; i < nbArgs; i++)
|
||||||
len += strlen(macroArgs->args[i]) + 1; // 1 for comma
|
len += strlen((*macroArgs->args)[i]) + 1; // 1 for comma
|
||||||
|
|
||||||
char *str = (char *)malloc(len + 1); // 1 for '\0'
|
char *str = (char *)malloc(len + 1); // 1 for '\0'
|
||||||
char *ptr = str;
|
char *ptr = str;
|
||||||
@@ -116,14 +98,15 @@ char const *macro_GetAllArgs(void)
|
|||||||
if (!str)
|
if (!str)
|
||||||
fatalerror("Failed to allocate memory for expanding '\\#': %s\n", strerror(errno));
|
fatalerror("Failed to allocate memory for expanding '\\#': %s\n", strerror(errno));
|
||||||
|
|
||||||
for (uint32_t i = macroArgs->shift; i < macroArgs->nbArgs; i++) {
|
for (uint32_t i = macroArgs->shift; i < nbArgs; i++) {
|
||||||
size_t n = strlen(macroArgs->args[i]);
|
char *arg = (*macroArgs->args)[i];
|
||||||
|
size_t n = strlen(arg);
|
||||||
|
|
||||||
memcpy(ptr, macroArgs->args[i], n);
|
memcpy(ptr, arg, n);
|
||||||
ptr += n;
|
ptr += n;
|
||||||
|
|
||||||
// Commas go between args and after a last empty arg
|
// Commas go between args and after a last empty arg
|
||||||
if (i < macroArgs->nbArgs - 1 || n == 0)
|
if (i < nbArgs - 1 || n == 0)
|
||||||
*ptr++ = ','; // no space after comma
|
*ptr++ = ','; // no space after comma
|
||||||
}
|
}
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
@@ -176,14 +159,12 @@ void macro_ShiftCurrentArgs(int32_t count)
|
|||||||
{
|
{
|
||||||
if (!macroArgs) {
|
if (!macroArgs) {
|
||||||
error("Cannot shift macro arguments outside of a macro\n");
|
error("Cannot shift macro arguments outside of a macro\n");
|
||||||
} else if (count > 0 && ((uint32_t)count > macroArgs->nbArgs
|
} else if (size_t nbArgs = macroArgs->args->size();
|
||||||
|| macroArgs->shift > macroArgs->nbArgs - count)) {
|
count > 0 && ((uint32_t)count > nbArgs || macroArgs->shift > nbArgs - count)) {
|
||||||
warning(WARNING_MACRO_SHIFT,
|
warning(WARNING_MACRO_SHIFT, "Cannot shift macro arguments past their end\n");
|
||||||
"Cannot shift macro arguments past their end\n");
|
macroArgs->shift = nbArgs;
|
||||||
macroArgs->shift = macroArgs->nbArgs;
|
|
||||||
} else if (count < 0 && macroArgs->shift < (uint32_t)-count) {
|
} else if (count < 0 && macroArgs->shift < (uint32_t)-count) {
|
||||||
warning(WARNING_MACRO_SHIFT,
|
warning(WARNING_MACRO_SHIFT, "Cannot shift macro arguments past their beginning\n");
|
||||||
"Cannot shift macro arguments past their beginning\n");
|
|
||||||
macroArgs->shift = 0;
|
macroArgs->shift = 0;
|
||||||
} else {
|
} else {
|
||||||
macroArgs->shift += count;
|
macroArgs->shift += count;
|
||||||
@@ -192,5 +173,5 @@ void macro_ShiftCurrentArgs(int32_t count)
|
|||||||
|
|
||||||
uint32_t macro_NbArgs(void)
|
uint32_t macro_NbArgs(void)
|
||||||
{
|
{
|
||||||
return macroArgs->nbArgs - macroArgs->shift;
|
return macroArgs->args->size() - macroArgs->shift;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -457,14 +457,14 @@ static void writeFileStackNode(struct FileStackNode const *node, FILE *f)
|
|||||||
putlong(node->lineNo, f);
|
putlong(node->lineNo, f);
|
||||||
putc(node->type, f);
|
putc(node->type, f);
|
||||||
if (node->type != NODE_REPT) {
|
if (node->type != NODE_REPT) {
|
||||||
putstring(((struct FileStackNamedNode const *)node)->name, f);
|
putstring(((struct FileStackNamedNode const *)node)->name->c_str(), f);
|
||||||
} else {
|
} else {
|
||||||
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
|
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
|
||||||
|
|
||||||
putlong(reptNode->reptDepth, f);
|
putlong(reptNode->iters->size(), f);
|
||||||
// Iters are stored by decreasing depth, so reverse the order for output
|
// Iters are stored by decreasing depth, so reverse the order for output
|
||||||
for (uint32_t i = reptNode->reptDepth; i--; )
|
for (uint32_t i = reptNode->iters->size(); i--; )
|
||||||
putlong(reptNode->iters[i], f);
|
putlong((*reptNode->iters)[i], f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -492,6 +492,15 @@ enum {
|
|||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%code requires {
|
||||||
|
// Only used in the %union
|
||||||
|
struct ForArgs {
|
||||||
|
int32_t start;
|
||||||
|
int32_t stop;
|
||||||
|
int32_t step;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
%union
|
%union
|
||||||
{
|
{
|
||||||
char symName[MAXSYMLEN + 1];
|
char symName[MAXSYMLEN + 1];
|
||||||
@@ -506,11 +515,7 @@ enum {
|
|||||||
struct AlignmentSpec alignSpec;
|
struct AlignmentSpec alignSpec;
|
||||||
struct DsArgList dsArgs;
|
struct DsArgList dsArgs;
|
||||||
struct PurgeArgList purgeArgs;
|
struct PurgeArgList purgeArgs;
|
||||||
struct {
|
struct ForArgs forArgs;
|
||||||
int32_t start;
|
|
||||||
int32_t stop;
|
|
||||||
int32_t step;
|
|
||||||
} forArgs;
|
|
||||||
struct StrFmtArgList strfmtArgs;
|
struct StrFmtArgList strfmtArgs;
|
||||||
bool captureTerminated;
|
bool captureTerminated;
|
||||||
}
|
}
|
||||||
@@ -885,7 +890,7 @@ macroargs : %empty {
|
|||||||
$$ = macro_NewArgs();
|
$$ = macro_NewArgs();
|
||||||
}
|
}
|
||||||
| macroargs T_STRING {
|
| macroargs T_STRING {
|
||||||
macro_AppendArg(&($$), strdup($2));
|
macro_AppendArg($$, strdup($2));
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user