Remove now-unnecessary struct keyword (#1320)

C++ acts like structs are `typedef`ed by default

We do have to keep `struct stat`, since there's ambiguity
with the function also called `stat`.
This commit is contained in:
Sylvie
2024-02-29 14:41:58 -05:00
committed by GitHub
parent 1210a7441f
commit eff8c324c8
40 changed files with 537 additions and 553 deletions

View File

@@ -35,13 +35,13 @@ struct StrFmtArgList {
std::vector<std::variant<uint32_t, char *>> *args; std::vector<std::variant<uint32_t, char *>> *args;
}; };
struct FormatSpec fmt_NewSpec(void); FormatSpec fmt_NewSpec(void);
bool fmt_IsEmpty(struct FormatSpec const *fmt); bool fmt_IsEmpty(FormatSpec const *fmt);
bool fmt_IsValid(struct FormatSpec const *fmt); bool fmt_IsValid(FormatSpec const *fmt);
bool fmt_IsFinished(struct FormatSpec const *fmt); bool fmt_IsFinished(FormatSpec const *fmt);
void fmt_UseCharacter(struct FormatSpec *fmt, int c); void fmt_UseCharacter(FormatSpec *fmt, int c);
void fmt_FinishCharacters(struct FormatSpec *fmt); void fmt_FinishCharacters(FormatSpec *fmt);
void fmt_PrintString(char *buf, size_t bufLen, struct FormatSpec const *fmt, char const *value); void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const *value);
void fmt_PrintNumber(char *buf, size_t bufLen, struct FormatSpec const *fmt, uint32_t value); void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t value);
#endif // RGBDS_FORMAT_SPEC_H #endif // RGBDS_FORMAT_SPEC_H

View File

@@ -16,7 +16,7 @@
#include "linkdefs.hpp" #include "linkdefs.hpp"
struct FileStackNode { struct FileStackNode {
struct FileStackNode *parent; // Pointer to parent node, for error reporting FileStackNode *parent; // Pointer to parent node, for error reporting
// 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
uint32_t lineNo; uint32_t lineNo;
@@ -43,9 +43,9 @@ extern size_t maxRecursionDepth;
struct MacroArgs; struct MacroArgs;
void fstk_Dump(struct FileStackNode const *node, uint32_t lineNo); void fstk_Dump(FileStackNode const *node, uint32_t lineNo);
void fstk_DumpCurrent(void); void fstk_DumpCurrent(void);
struct FileStackNode *fstk_GetFileStack(void); FileStackNode *fstk_GetFileStack(void);
// The lifetime of the returned chars is until reaching the end of that file // The lifetime of the returned chars is until reaching the end of that file
char const *fstk_GetFileName(void); char const *fstk_GetFileName(void);
@@ -59,7 +59,7 @@ std::string *fstk_FindFile(char const *path);
bool yywrap(void); bool yywrap(void);
void fstk_RunInclude(char const *path); void fstk_RunInclude(char const *path);
void fstk_RunMacro(char const *macroName, struct MacroArgs *args); void fstk_RunMacro(char const *macroName, MacroArgs *args);
void fstk_RunRept(uint32_t count, int32_t reptLineNo, char *body, size_t size); void fstk_RunRept(uint32_t count, int32_t reptLineNo, char *body, size_t size);
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step, void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char *body, size_t size); int32_t reptLineNo, char *body, size_t size);

View File

@@ -60,8 +60,8 @@ struct LexerState {
// mmap()-dependent IO state // mmap()-dependent IO state
bool isMmapped; bool isMmapped;
union { union {
struct MmappedLexerState mmap; // If mmap()ed MmappedLexerState mmap; // If mmap()ed
struct BufferedLexerState cbuf; // Otherwise BufferedLexerState cbuf; // Otherwise
}; };
// Common state // Common state
@@ -73,7 +73,7 @@ struct LexerState {
uint32_t colNo; uint32_t colNo;
int lastToken; int lastToken;
std::deque<struct IfStackEntry> ifStack; std::deque<IfStackEntry> ifStack;
bool capturing; // Whether the text being lexed should be captured bool capturing; // Whether the text being lexed should be captured
size_t captureSize; // Amount of text captured size_t captureSize; // Amount of text captured
@@ -84,18 +84,18 @@ struct LexerState {
bool disableInterpolation; bool disableInterpolation;
size_t macroArgScanDistance; // Max distance already scanned for macro args size_t macroArgScanDistance; // Max distance already scanned for macro args
bool expandStrings; bool expandStrings;
std::deque<struct Expansion> expansions; // Front is the innermost current expansion std::deque<Expansion> expansions; // Front is the innermost current expansion
}; };
extern struct LexerState *lexerState; extern LexerState *lexerState;
extern struct LexerState *lexerStateEOL; extern LexerState *lexerStateEOL;
static inline void lexer_SetState(struct LexerState *state) static inline void lexer_SetState(LexerState *state)
{ {
lexerState = state; lexerState = state;
} }
static inline void lexer_SetStateAtEOL(struct LexerState *state) static inline void lexer_SetStateAtEOL(LexerState *state)
{ {
lexerStateEOL = state; lexerStateEOL = state;
} }
@@ -118,11 +118,10 @@ static inline void lexer_SetGfxDigits(char const digits[4])
} }
// `path` is referenced, but not held onto..! // `path` is referenced, but not held onto..!
bool lexer_OpenFile(struct LexerState &state, char const *path); bool lexer_OpenFile(LexerState &state, char const *path);
void lexer_OpenFileView(struct LexerState &state, char const *path, char *buf, size_t size, void lexer_OpenFileView(LexerState &state, char const *path, char *buf, size_t size, uint32_t lineNo);
uint32_t lineNo);
void lexer_RestartRept(uint32_t lineNo); void lexer_RestartRept(uint32_t lineNo);
void lexer_CleanupState(struct LexerState &state); void lexer_CleanupState(LexerState &state);
void lexer_Init(void); void lexer_Init(void);
void lexer_SetMode(enum LexerMode mode); void lexer_SetMode(enum LexerMode mode);
void lexer_ToggleStringExpansion(bool enable); void lexer_ToggleStringExpansion(bool enable);
@@ -147,8 +146,8 @@ uint32_t lexer_GetLineNo(void);
uint32_t lexer_GetColNo(void); uint32_t lexer_GetColNo(void);
void lexer_DumpStringExpansions(void); void lexer_DumpStringExpansions(void);
int yylex(void); int yylex(void);
bool lexer_CaptureRept(struct CaptureBody *capture); bool lexer_CaptureRept(CaptureBody *capture);
bool lexer_CaptureMacroBody(struct CaptureBody *capture); bool lexer_CaptureMacroBody(CaptureBody *capture);
struct AlignmentSpec { struct AlignmentSpec {
uint8_t alignment; uint8_t alignment;

View File

@@ -12,11 +12,11 @@
struct MacroArgs; struct MacroArgs;
struct MacroArgs *macro_GetCurrentArgs(void); MacroArgs *macro_GetCurrentArgs(void);
struct MacroArgs *macro_NewArgs(void); MacroArgs *macro_NewArgs(void);
void macro_AppendArg(struct MacroArgs *args, char *s); void macro_AppendArg(MacroArgs *args, char *s);
void macro_UseNewArgs(struct MacroArgs *args); void macro_UseNewArgs(MacroArgs *args);
void macro_FreeArgs(struct MacroArgs *args); void macro_FreeArgs(MacroArgs *args);
char const *macro_GetArg(uint32_t i); char const *macro_GetArg(uint32_t i);
char const *macro_GetAllArgs(void); char const *macro_GetAllArgs(void);

View File

@@ -12,12 +12,11 @@ struct FileStackNode;
extern const char *objectName; extern const char *objectName;
void out_RegisterNode(struct FileStackNode *node); void out_RegisterNode(FileStackNode *node);
void out_ReplaceNode(struct FileStackNode *node); void out_ReplaceNode(FileStackNode *node);
void out_SetFileName(char *s); void out_SetFileName(char *s);
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, uint32_t pcShift); void out_CreatePatch(uint32_t type, Expression const *expr, uint32_t ofs, uint32_t pcShift);
void out_CreateAssert(enum AssertionType type, struct Expression const *expr, void out_CreateAssert(enum AssertionType type, Expression const *expr, char const *message, uint32_t ofs);
char const *message, uint32_t ofs);
void out_WriteObject(void); void out_WriteObject(void);
#endif // RGBDS_ASM_OUTPUT_H #endif // RGBDS_ASM_OUTPUT_H

View File

@@ -8,6 +8,8 @@
#include "linkdefs.hpp" #include "linkdefs.hpp"
struct Symbol;
struct Expression { struct Expression {
int32_t val; // If the expression's value is known, it's here int32_t val; // If the expression's value is known, it's here
std::string *reason; // Why the expression is not known, if it isn't std::string *reason; // Why the expression is not known, if it isn't
@@ -18,41 +20,39 @@ struct Expression {
}; };
// Determines if an expression is known at assembly time // Determines if an expression is known at assembly time
static inline bool rpn_isKnown(struct Expression const *expr) static inline bool rpn_isKnown(Expression const *expr)
{ {
return expr->isKnown; return expr->isKnown;
} }
// Determines if an expression is a symbol suitable for const diffing // Determines if an expression is a symbol suitable for const diffing
static inline bool rpn_isSymbol(const struct Expression *expr) static inline bool rpn_isSymbol(const Expression *expr)
{ {
return expr->isSymbol; return expr->isSymbol;
} }
void rpn_Symbol(struct Expression *expr, char const *symName); void rpn_Symbol(Expression *expr, char const *symName);
void rpn_Number(struct Expression *expr, uint32_t i); void rpn_Number(Expression *expr, uint32_t i);
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src); void rpn_LOGNOT(Expression *expr, const Expression *src);
struct Symbol const *rpn_SymbolOf(struct Expression const *expr); Symbol const *rpn_SymbolOf(Expression const *expr);
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *symName); bool rpn_IsDiffConstant(Expression const *src, Symbol const *symName);
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr, void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2);
const struct Expression *src1, void rpn_HIGH(Expression *expr, const Expression *src);
const struct Expression *src2); void rpn_LOW(Expression *expr, const Expression *src);
void rpn_HIGH(struct Expression *expr, const struct Expression *src); void rpn_ISCONST(Expression *expr, const Expression *src);
void rpn_LOW(struct Expression *expr, const struct Expression *src); void rpn_NEG(Expression *expr, const Expression *src);
void rpn_ISCONST(struct Expression *expr, const struct Expression *src); void rpn_NOT(Expression *expr, const Expression *src);
void rpn_NEG(struct Expression *expr, const struct Expression *src); void rpn_BankSymbol(Expression *expr, char const *symName);
void rpn_NOT(struct Expression *expr, const struct Expression *src); void rpn_BankSection(Expression *expr, char const *sectionName);
void rpn_BankSymbol(struct Expression *expr, char const *symName); void rpn_BankSelf(Expression *expr);
void rpn_BankSection(struct Expression *expr, char const *sectionName); void rpn_SizeOfSection(Expression *expr, char const *sectionName);
void rpn_BankSelf(struct Expression *expr); void rpn_StartOfSection(Expression *expr, char const *sectionName);
void rpn_SizeOfSection(struct Expression *expr, char const *sectionName); void rpn_SizeOfSectionType(Expression *expr, enum SectionType type);
void rpn_StartOfSection(struct Expression *expr, char const *sectionName); void rpn_StartOfSectionType(Expression *expr, enum SectionType type);
void rpn_SizeOfSectionType(struct Expression *expr, enum SectionType type); void rpn_Free(Expression *expr);
void rpn_StartOfSectionType(struct Expression *expr, enum SectionType type); void rpn_CheckHRAM(Expression *expr, const Expression *src);
void rpn_Free(struct Expression *expr); void rpn_CheckRST(Expression *expr, const Expression *src);
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src); void rpn_CheckNBit(Expression const *expr, uint8_t n);
void rpn_CheckRST(struct Expression *expr, const struct Expression *src); int32_t rpn_GetConstVal(Expression const *expr);
void rpn_CheckNBit(struct Expression const *expr, uint8_t n);
int32_t rpn_GetConstVal(struct Expression const *expr);
#endif // RGBDS_ASM_RPN_H #endif // RGBDS_ASM_RPN_H

View File

@@ -17,10 +17,10 @@ struct FileStackNode;
struct Section; struct Section;
struct Patch { struct Patch {
struct FileStackNode const *src; FileStackNode const *src;
uint32_t lineNo; uint32_t lineNo;
uint32_t offset; uint32_t offset;
struct Section *pcSection; Section *pcSection;
uint32_t pcOffset; uint32_t pcOffset;
uint8_t type; uint8_t type;
std::vector<uint8_t> rpn; std::vector<uint8_t> rpn;
@@ -30,14 +30,14 @@ struct Section {
char *name; char *name;
enum SectionType type; enum SectionType type;
enum SectionModifier modifier; enum SectionModifier modifier;
struct FileStackNode const *src; // Where the section was defined FileStackNode const *src; // Where the section was defined
uint32_t fileLine; // Line where the section was defined uint32_t fileLine; // Line where the section was defined
uint32_t size; uint32_t size;
uint32_t org; uint32_t org;
uint32_t bank; uint32_t bank;
uint8_t align; // Exactly as specified in `ALIGN[]` uint8_t align; // Exactly as specified in `ALIGN[]`
uint16_t alignOfs; uint16_t alignOfs;
std::deque<struct Patch> patches; std::deque<Patch> patches;
std::vector<uint8_t> data; std::vector<uint8_t> data;
}; };
@@ -47,17 +47,17 @@ struct SectionSpec {
uint16_t alignOfs; uint16_t alignOfs;
}; };
extern std::deque<struct Section> sectionList; extern std::deque<Section> sectionList;
extern struct Section *currentSection; extern Section *currentSection;
struct Section *sect_FindSectionByName(char const *name); Section *sect_FindSectionByName(char const *name);
void sect_NewSection(char const *name, enum SectionType type, uint32_t org, void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
struct SectionSpec const *attributes, enum SectionModifier mod); SectionSpec const *attributes, enum SectionModifier mod);
void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org, void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
struct SectionSpec const *attributes, enum SectionModifier mod); SectionSpec const *attributes, enum SectionModifier mod);
void sect_EndLoadSection(void); void sect_EndLoadSection(void);
struct Section *sect_GetSymbolSection(void); Section *sect_GetSymbolSection(void);
uint32_t sect_GetSymbolOffset(void); uint32_t sect_GetSymbolOffset(void);
uint32_t sect_GetOutputOffset(void); uint32_t sect_GetOutputOffset(void);
uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset); uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset);
@@ -73,11 +73,11 @@ void sect_AbsByteGroup(uint8_t const *s, size_t length);
void sect_AbsWordGroup(uint8_t const *s, size_t length); void sect_AbsWordGroup(uint8_t const *s, size_t length);
void sect_AbsLongGroup(uint8_t const *s, size_t length); void sect_AbsLongGroup(uint8_t const *s, size_t length);
void sect_Skip(uint32_t skip, bool ds); void sect_Skip(uint32_t skip, bool ds);
void sect_RelByte(struct Expression *expr, uint32_t pcShift); void sect_RelByte(Expression *expr, uint32_t pcShift);
void sect_RelBytes(uint32_t n, std::vector<struct Expression> &exprs); void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs);
void sect_RelWord(struct Expression *expr, uint32_t pcShift); void sect_RelWord(Expression *expr, uint32_t pcShift);
void sect_RelLong(struct Expression *expr, uint32_t pcShift); void sect_RelLong(Expression *expr, uint32_t pcShift);
void sect_PCRelByte(struct Expression *expr, uint32_t pcShift); void sect_PCRelByte(Expression *expr, uint32_t pcShift);
void sect_BinaryFile(char const *s, int32_t startPos); void sect_BinaryFile(char const *s, int32_t startPos);
void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length); void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
@@ -85,6 +85,6 @@ void sect_EndSection(void);
void sect_PushSection(void); void sect_PushSection(void);
void sect_PopSection(void); void sect_PopSection(void);
bool sect_IsSizeKnown(struct Section const NONNULL(name)); bool sect_IsSizeKnown(Section const NONNULL(name));
#endif // RGBDS_SECTION_H #endif // RGBDS_SECTION_H

View File

@@ -23,7 +23,7 @@ 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` // Only used in an anonymous union by `Symbol`
struct strValue { struct strValue {
size_t size; size_t size;
char *value; char *value;
@@ -34,8 +34,8 @@ struct Symbol {
enum SymbolType type; enum SymbolType type;
bool isExported; // Whether the symbol is to be exported bool isExported; // Whether the symbol is to be exported
bool isBuiltin; // Whether the symbol is a built-in bool isBuiltin; // Whether the symbol is a built-in
struct Section *section; Section *section;
struct FileStackNode *src; // Where the symbol was defined FileStackNode *src; // Where the symbol was defined
uint32_t fileLine; // Line where the symbol was defined uint32_t fileLine; // Line where the symbol was defined
bool hasCallback; bool hasCallback;
@@ -44,91 +44,91 @@ struct Symbol {
int32_t value; int32_t value;
int32_t (*numCallback)(void); // If hasCallback int32_t (*numCallback)(void); // If hasCallback
// For SYM_MACRO // For SYM_MACRO
struct strValue macro; strValue macro;
// For SYM_EQUS // For SYM_EQUS
struct strValue equs; strValue equs;
char const *(*strCallback)(void); // If hasCallback char const *(*strCallback)(void); // If hasCallback
}; };
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)
}; };
bool sym_IsPC(struct Symbol const *sym); bool sym_IsPC(Symbol const *sym);
static inline bool sym_IsDefined(struct Symbol const *sym) static inline bool sym_IsDefined(Symbol const *sym)
{ {
return sym->type != SYM_REF; return sym->type != SYM_REF;
} }
static inline struct Section *sym_GetSection(struct Symbol const *sym) static inline Section *sym_GetSection(Symbol const *sym)
{ {
return sym_IsPC(sym) ? sect_GetSymbolSection() : sym->section; return sym_IsPC(sym) ? sect_GetSymbolSection() : sym->section;
} }
static inline bool sym_IsConstant(struct Symbol const *sym) static inline bool sym_IsConstant(Symbol const *sym)
{ {
if (sym->type == SYM_LABEL) { if (sym->type == SYM_LABEL) {
struct Section const *sect = sym_GetSection(sym); Section const *sect = sym_GetSection(sym);
return sect && sect->org != (uint32_t)-1; return sect && sect->org != (uint32_t)-1;
} }
return sym->type == SYM_EQU || sym->type == SYM_VAR; return sym->type == SYM_EQU || sym->type == SYM_VAR;
} }
static inline bool sym_IsNumeric(struct Symbol const *sym) static inline bool sym_IsNumeric(Symbol const *sym)
{ {
return sym->type == SYM_LABEL || sym->type == SYM_EQU || sym->type == SYM_VAR; return sym->type == SYM_LABEL || sym->type == SYM_EQU || sym->type == SYM_VAR;
} }
static inline bool sym_IsLabel(struct Symbol const *sym) static inline bool sym_IsLabel(Symbol const *sym)
{ {
return sym->type == SYM_LABEL || sym->type == SYM_REF; return sym->type == SYM_LABEL || sym->type == SYM_REF;
} }
static inline bool sym_IsLocal(struct Symbol const *sym) static inline bool sym_IsLocal(Symbol const *sym)
{ {
return sym_IsLabel(sym) && strchr(sym->name, '.'); return sym_IsLabel(sym) && strchr(sym->name, '.');
} }
static inline bool sym_IsExported(struct Symbol const *sym) static inline bool sym_IsExported(Symbol const *sym)
{ {
return sym->isExported; return sym->isExported;
} }
// Get a string equate's value // Get a string equate's value
static inline char const *sym_GetStringValue(struct Symbol const *sym) static inline char const *sym_GetStringValue(Symbol const *sym)
{ {
if (sym->hasCallback) if (sym->hasCallback)
return sym->strCallback(); return sym->strCallback();
return sym->equs.value; return sym->equs.value;
} }
void sym_ForEach(void (*func)(struct Symbol *)); void sym_ForEach(void (*func)(Symbol *));
int32_t sym_GetValue(struct Symbol const *sym); int32_t sym_GetValue(Symbol const *sym);
void sym_SetExportAll(bool set); void sym_SetExportAll(bool set);
struct Symbol *sym_AddLocalLabel(char const *symName); Symbol *sym_AddLocalLabel(char const *symName);
struct Symbol *sym_AddLabel(char const *symName); Symbol *sym_AddLabel(char const *symName);
struct Symbol *sym_AddAnonLabel(void); Symbol *sym_AddAnonLabel(void);
void sym_WriteAnonLabelName(char buf[MIN_NB_ELMS(MAXSYMLEN + 1)], uint32_t ofs, bool neg); void sym_WriteAnonLabelName(char buf[MIN_NB_ELMS(MAXSYMLEN + 1)], uint32_t ofs, bool neg);
void sym_Export(char const *symName); void sym_Export(char const *symName);
struct Symbol *sym_AddEqu(char const *symName, int32_t value); Symbol *sym_AddEqu(char const *symName, int32_t value);
struct Symbol *sym_RedefEqu(char const *symName, int32_t value); Symbol *sym_RedefEqu(char const *symName, int32_t value);
struct Symbol *sym_AddVar(char const *symName, int32_t value); Symbol *sym_AddVar(char const *symName, int32_t value);
uint32_t sym_GetPCValue(void); uint32_t sym_GetPCValue(void);
uint32_t sym_GetConstantSymValue(struct Symbol const *sym); uint32_t sym_GetConstantSymValue(Symbol const *sym);
uint32_t sym_GetConstantValue(char const *symName); uint32_t sym_GetConstantValue(char const *symName);
// Find a symbol by exact name, bypassing expansion checks // Find a symbol by exact name, bypassing expansion checks
struct Symbol *sym_FindExactSymbol(char const *symName); Symbol *sym_FindExactSymbol(char const *symName);
// Find a symbol, possibly scoped, by name // Find a symbol, possibly scoped, by name
struct Symbol *sym_FindScopedSymbol(char const *symName); Symbol *sym_FindScopedSymbol(char const *symName);
// Find a scoped symbol by name; do not return `@` or `_NARG` when they have no value // Find a scoped symbol by name; do not return `@` or `_NARG` when they have no value
struct Symbol *sym_FindScopedValidSymbol(char const *symName); Symbol *sym_FindScopedValidSymbol(char const *symName);
struct Symbol const *sym_GetPC(void); Symbol const *sym_GetPC(void);
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size); Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
struct Symbol *sym_Ref(char const *symName); Symbol *sym_Ref(char const *symName);
struct Symbol *sym_AddString(char const *symName, char const *value); Symbol *sym_AddString(char const *symName, char const *value);
struct Symbol *sym_RedefString(char const *symName, char const *value); Symbol *sym_RedefString(char const *symName, char const *value);
void sym_Purge(std::string const &symName); void sym_Purge(std::string const &symName);
void sym_Init(time_t now); void sym_Init(time_t now);

View File

@@ -18,7 +18,7 @@ struct option {
}; };
int musl_getopt_long_only(int argc, char **argv, char const *optstring, int musl_getopt_long_only(int argc, char **argv, char const *optstring,
const struct option *longopts, int *idx); const option *longopts, int *idx);
#define no_argument 0 #define no_argument 0
#define required_argument 1 #define required_argument 1

View File

@@ -31,7 +31,7 @@ extern bool isWRAM0Mode;
extern bool disablePadding; extern bool disablePadding;
struct FileStackNode { struct FileStackNode {
struct FileStackNode *parent; 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
uint32_t lineNo; uint32_t lineNo;
@@ -60,15 +60,12 @@ struct FileStackNode {
* Dump a file stack to stderr * Dump a file stack to stderr
* @param node The leaf node to dump the context of * @param node The leaf node to dump the context of
*/ */
std::string const *dumpFileStack(struct FileStackNode const *node); std::string const *dumpFileStack(FileStackNode const *node);
void warning(struct FileStackNode const *where, uint32_t lineNo, void warning(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4);
char const *fmt, ...) format_(printf, 3, 4);
void error(struct FileStackNode const *where, uint32_t lineNo, void error(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4);
char const *fmt, ...) format_(printf, 3, 4);
[[noreturn]] void fatal(struct FileStackNode const *where, uint32_t lineNo, [[noreturn]] void fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4);
char const *fmt, ...) format_(printf, 3, 4);
#endif // RGBDS_LINK_MAIN_H #endif // RGBDS_LINK_MAIN_H

View File

@@ -12,14 +12,14 @@
* Registers a section for output. * Registers a section for output.
* @param section The section to add * @param section The section to add
*/ */
void out_AddSection(struct Section const *section); void out_AddSection(Section const *section);
/* /*
* Finds an assigned section overlapping another one. * Finds an assigned section overlapping another one.
* @param section The section that is being overlapped * @param section The section that is being overlapped
* @return A section overlapping it * @return A section overlapping it
*/ */
struct Section const *out_OverlappingSection(struct Section const *section); Section const *out_OverlappingSection(Section const *section);
/* /*
* Writes all output (bin, sym, map) files. * Writes all output (bin, sym, map) files.

View File

@@ -13,17 +13,17 @@
#include "linkdefs.hpp" #include "linkdefs.hpp"
struct Assertion { struct Assertion {
struct Patch patch; // Also used for its `.type` Patch patch; // Also used for its `.type`
std::string message; std::string 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!
std::vector<struct Symbol> *fileSymbols; std::vector<Symbol> *fileSymbols;
}; };
/* /*
* Checks all assertions * Checks all assertions
* @return true if assertion failed * @return true if assertion failed
*/ */
void patch_CheckAssertions(std::deque<struct Assertion> &assertions); void patch_CheckAssertions(std::deque<Assertion> &assertions);
/* /*
* Applies all SECTIONs' patches to them * Applies all SECTIONs' patches to them

View File

@@ -10,6 +10,6 @@
struct FileStackNode; struct FileStackNode;
struct Symbol; struct Symbol;
void sdobj_ReadFile(struct FileStackNode const *fileName, FILE *file, std::vector<struct Symbol> &fileSymbols); void sdobj_ReadFile(FileStackNode const *fileName, FILE *file, std::vector<Symbol> &fileSymbols);
#endif // RGBDS_LINK_SDAS_OBJ_H #endif // RGBDS_LINK_SDAS_OBJ_H

View File

@@ -16,12 +16,13 @@
struct FileStackNode; struct FileStackNode;
struct Section; struct Section;
struct Symbol;
struct Patch { struct Patch {
struct FileStackNode const *src; FileStackNode const *src;
uint32_t lineNo; uint32_t lineNo;
uint32_t offset; uint32_t offset;
struct Section const *pcSection; Section const *pcSection;
uint32_t pcSectionID; uint32_t pcSectionID;
uint32_t pcOffset; uint32_t pcOffset;
enum PatchType type; enum PatchType type;
@@ -45,11 +46,11 @@ struct Section {
uint16_t alignMask; uint16_t alignMask;
uint16_t alignOfs; uint16_t alignOfs;
std::vector<uint8_t> data; // Array of size `size`, or 0 if `type` does not have data std::vector<uint8_t> data; // Array of size `size`, or 0 if `type` does not have data
std::vector<struct Patch> patches; std::vector<Patch> patches;
// Extra info computed during linking // Extra info computed during linking
std::vector<struct Symbol> *fileSymbols; std::vector<Symbol> *fileSymbols;
std::vector<struct Symbol *> symbols; std::vector<Symbol *> symbols;
struct Section *nextu; // The next "component" of this unionized sect Section *nextu; // The next "component" of this unionized sect
}; };
/* /*
@@ -57,20 +58,20 @@ struct Section {
* This is to avoid exposing the data structure in which sections are stored. * This is to avoid exposing the data structure in which sections are stored.
* @param callback The function to call for each structure. * @param callback The function to call for each structure.
*/ */
void sect_ForEach(void (*callback)(struct Section *)); void sect_ForEach(void (*callback)(Section *));
/* /*
* Registers a section to be processed. * Registers a section to be processed.
* @param section The section to register. * @param section The section to register.
*/ */
void sect_AddSection(struct Section *section); void sect_AddSection(Section *section);
/* /*
* Finds a section by its name. * Finds a section by its name.
* @param name The name of the section to look for * @param name The name of the section to look for
* @return A pointer to the section, or NULL if it wasn't found * @return A pointer to the section, or NULL if it wasn't found
*/ */
struct Section *sect_GetSection(std::string const &name); Section *sect_GetSection(std::string const &name);
/* /*
* Checks if all sections meet reasonable criteria, such as max size * Checks if all sections meet reasonable criteria, such as max size

View File

@@ -12,13 +12,14 @@
#include "linkdefs.hpp" #include "linkdefs.hpp"
struct FileStackNode; struct FileStackNode;
struct Section;
struct Symbol { struct Symbol {
// Info contained in the object files // Info contained in the object files
std::string name; std::string name;
enum ExportLevel type; enum ExportLevel type;
char const *objFileName; char const *objFileName;
struct FileStackNode const *src; FileStackNode const *src;
int32_t lineNo; int32_t lineNo;
int32_t sectionID; int32_t sectionID;
union { union {
@@ -27,16 +28,16 @@ struct Symbol {
int32_t value; int32_t value;
}; };
// Extra info computed during linking // Extra info computed during linking
struct Section *section; Section *section;
}; };
void sym_AddSymbol(struct Symbol *symbol); void sym_AddSymbol(Symbol *symbol);
/* /*
* Finds a symbol in all the defined symbols. * Finds a symbol in all the defined symbols.
* @param name The name of the symbol to look for * @param name The name of the symbol to look for
* @return A pointer to the symbol, or NULL if not found. * @return A pointer to the symbol, or NULL if not found.
*/ */
struct Symbol *sym_GetSymbol(std::string const &name); Symbol *sym_GetSymbol(std::string const &name);
#endif // RGBDS_LINK_SYMBOL_H #endif // RGBDS_LINK_SYMBOL_H

View File

@@ -30,17 +30,17 @@ struct CharmapNode {
struct Charmap { struct Charmap {
std::string name; std::string name;
std::vector<struct CharmapNode> nodes; // first node is reserved for the root node std::vector<CharmapNode> nodes; // first node is reserved for the root node
}; };
static std::map<std::string, struct Charmap> charmaps; static std::map<std::string, Charmap> charmaps;
static struct Charmap *currentCharmap; static Charmap *currentCharmap;
std::stack<struct Charmap *> charmapStack; std::stack<Charmap *> charmapStack;
void charmap_New(char const *name, char const *baseName) void charmap_New(char const *name, char const *baseName)
{ {
struct Charmap *base = NULL; Charmap *base = NULL;
if (baseName != NULL) { if (baseName != NULL) {
auto search = charmaps.find(baseName); auto search = charmaps.find(baseName);
@@ -57,7 +57,7 @@ void charmap_New(char const *name, char const *baseName)
} }
// Init the new charmap's fields // Init the new charmap's fields
struct Charmap &charmap = charmaps[name]; Charmap &charmap = charmaps[name];
if (base) if (base)
charmap.nodes = base->nodes; // Copies `base->nodes` charmap.nodes = base->nodes; // Copies `base->nodes`
@@ -96,7 +96,7 @@ void charmap_Pop(void)
void charmap_Add(char *mapping, uint8_t value) void charmap_Add(char *mapping, uint8_t value)
{ {
struct Charmap &charmap = *currentCharmap; Charmap &charmap = *currentCharmap;
size_t nodeIdx = 0; size_t nodeIdx = 0;
for (; *mapping; mapping++) { for (; *mapping; mapping++) {
@@ -115,7 +115,7 @@ void charmap_Add(char *mapping, uint8_t value)
nodeIdx = nextIdx; nodeIdx = nextIdx;
} }
struct CharmapNode &node = charmap.nodes[nodeIdx]; CharmapNode &node = charmap.nodes[nodeIdx];
if (node.isTerminal) if (node.isTerminal)
warning(WARNING_CHARMAP_REDEF, "Overriding charmap mapping\n"); warning(WARNING_CHARMAP_REDEF, "Overriding charmap mapping\n");
@@ -126,7 +126,7 @@ 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; Charmap const &charmap = *currentCharmap;
size_t nodeIdx = 0; size_t nodeIdx = 0;
for (; *input; input++) { for (; *input; input++) {
@@ -151,7 +151,7 @@ size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
// For that, advance through the trie with each character read. // For that, advance through the trie with each character read.
// 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; Charmap const &charmap = *currentCharmap;
size_t matchIdx = 0; size_t matchIdx = 0;
size_t rewindDistance = 0; size_t rewindDistance = 0;

View File

@@ -12,29 +12,29 @@
#include "asm/format.hpp" #include "asm/format.hpp"
#include "asm/warning.hpp" #include "asm/warning.hpp"
struct FormatSpec fmt_NewSpec(void) FormatSpec fmt_NewSpec(void)
{ {
struct FormatSpec fmt = {}; FormatSpec fmt = {};
return fmt; return fmt;
} }
bool fmt_IsEmpty(struct FormatSpec const *fmt) bool fmt_IsEmpty(FormatSpec const *fmt)
{ {
return !fmt->state; return !fmt->state;
} }
bool fmt_IsValid(struct FormatSpec const *fmt) bool fmt_IsValid(FormatSpec const *fmt)
{ {
return fmt->valid || fmt->state == FORMAT_DONE; return fmt->valid || fmt->state == FORMAT_DONE;
} }
bool fmt_IsFinished(struct FormatSpec const *fmt) bool fmt_IsFinished(FormatSpec const *fmt)
{ {
return fmt->state >= FORMAT_DONE; return fmt->state >= FORMAT_DONE;
} }
void fmt_UseCharacter(struct FormatSpec *fmt, int c) void fmt_UseCharacter(FormatSpec *fmt, int c)
{ {
if (fmt->state == FORMAT_INVALID) if (fmt->state == FORMAT_INVALID)
return; return;
@@ -121,13 +121,13 @@ invalid:
} }
} }
void fmt_FinishCharacters(struct FormatSpec *fmt) void fmt_FinishCharacters(FormatSpec *fmt)
{ {
if (!fmt_IsValid(fmt)) if (!fmt_IsValid(fmt))
fmt->state = FORMAT_INVALID; fmt->state = FORMAT_INVALID;
} }
void fmt_PrintString(char *buf, size_t bufLen, struct FormatSpec const *fmt, char const *value) void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const *value)
{ {
if (fmt->sign) if (fmt->sign)
error("Formatting string with sign flag '%c'\n", fmt->sign); error("Formatting string with sign flag '%c'\n", fmt->sign);
@@ -166,7 +166,7 @@ void fmt_PrintString(char *buf, size_t bufLen, struct FormatSpec const *fmt, cha
buf[totalLen] = '\0'; buf[totalLen] = '\0';
} }
void fmt_PrintNumber(char *buf, size_t bufLen, struct FormatSpec const *fmt, uint32_t value) void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t value)
{ {
if (fmt->type != 'X' && fmt->type != 'x' && fmt->type != 'b' && fmt->type != 'o' if (fmt->type != 'X' && fmt->type != 'x' && fmt->type != 'b' && fmt->type != 'o'
&& fmt->prefix) && fmt->prefix)

View File

@@ -23,10 +23,10 @@
#include "platform.hpp" // S_ISDIR (stat macro) #include "platform.hpp" // S_ISDIR (stat macro)
struct Context { struct Context {
struct FileStackNode *fileInfo; FileStackNode *fileInfo;
struct LexerState lexerState; LexerState lexerState;
uint32_t uniqueID; uint32_t uniqueID;
struct MacroArgs *macroArgs; // Macro args are *saved* here MacroArgs *macroArgs; // Macro args are *saved* here
uint32_t nbReptIters; uint32_t nbReptIters;
bool isForLoop; bool isForLoop;
int32_t forValue; int32_t forValue;
@@ -34,7 +34,7 @@ struct Context {
std::string forName; std::string forName;
}; };
static std::stack<struct Context> contextStack; static std::stack<Context> contextStack;
size_t maxRecursionDepth; size_t maxRecursionDepth;
// The first include path for `fstk_FindFile` to try is none at all // The first include path for `fstk_FindFile` to try is none at all
@@ -42,7 +42,7 @@ static std::vector<std::string> includePaths = { "" };
static const char *preIncludeName; static const char *preIncludeName;
static const char *dumpNodeAndParents(struct FileStackNode const *node) static const char *dumpNodeAndParents(FileStackNode const *node)
{ {
char const *name; char const *name;
@@ -86,7 +86,7 @@ std::string const &FileStackNode::name() const {
return std::get<std::string>(data); return std::get<std::string>(data);
} }
void fstk_Dump(struct FileStackNode const *node, uint32_t lineNo) void fstk_Dump(FileStackNode const *node, uint32_t lineNo)
{ {
dumpNodeAndParents(node); dumpNodeAndParents(node);
fprintf(stderr, "(%" PRIu32 ")", lineNo); fprintf(stderr, "(%" PRIu32 ")", lineNo);
@@ -101,15 +101,15 @@ void fstk_DumpCurrent(void)
fstk_Dump(contextStack.top().fileInfo, lexer_GetLineNo()); fstk_Dump(contextStack.top().fileInfo, lexer_GetLineNo());
} }
struct FileStackNode *fstk_GetFileStack(void) FileStackNode *fstk_GetFileStack(void)
{ {
if (contextStack.empty()) if (contextStack.empty())
return NULL; return NULL;
struct FileStackNode *topNode = contextStack.top().fileInfo; FileStackNode *topNode = contextStack.top().fileInfo;
// Mark node and all of its parents as referenced if not already so they don't get freed // Mark node and all of its parents as referenced if not already so they don't get freed
for (struct FileStackNode *node = topNode; node && !node->referenced; node = node->parent) { for (FileStackNode *node = topNode; node && !node->referenced; node = node->parent) {
node->ID = -1; node->ID = -1;
node->referenced = true; node->referenced = true;
} }
@@ -119,7 +119,7 @@ struct FileStackNode *fstk_GetFileStack(void)
char const *fstk_GetFileName(void) char const *fstk_GetFileName(void)
{ {
// Iterating via the nodes themselves skips nested REPTs // Iterating via the nodes themselves skips nested REPTs
struct FileStackNode const *node = contextStack.top().fileInfo; FileStackNode const *node = contextStack.top().fileInfo;
while (node->type != NODE_FILE) while (node->type != NODE_FILE)
node = node->parent; node = node->parent;
@@ -196,12 +196,12 @@ bool yywrap(void)
fatalerror("Ended block with %" PRIu32 " unterminated IF construct%s\n", fatalerror("Ended block with %" PRIu32 " unterminated IF construct%s\n",
ifDepth, ifDepth == 1 ? "" : "s"); ifDepth, ifDepth == 1 ? "" : "s");
if (struct Context &context = contextStack.top(); context.fileInfo->type == NODE_REPT) { if (Context &context = contextStack.top(); context.fileInfo->type == NODE_REPT) {
// The context is a REPT or FOR block, which may loop // The context is a REPT or FOR block, which may loop
// 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 (context.fileInfo->referenced) { if (context.fileInfo->referenced) {
context.fileInfo = new(std::nothrow) struct FileStackNode(*context.fileInfo); context.fileInfo = new(std::nothrow) FileStackNode(*context.fileInfo);
if (!context.fileInfo) if (!context.fileInfo)
fatalerror("Failed to duplicate REPT file node: %s\n", strerror(errno)); fatalerror("Failed to duplicate REPT file node: %s\n", strerror(errno));
// Copy all info but the referencing // Copy all info but the referencing
@@ -215,7 +215,7 @@ bool yywrap(void)
// Avoid arithmetic overflow runtime error // Avoid arithmetic overflow runtime error
uint32_t forValue = (uint32_t)context.forValue + (uint32_t)context.forStep; uint32_t forValue = (uint32_t)context.forValue + (uint32_t)context.forStep;
context.forValue = forValue <= INT32_MAX ? forValue : -(int32_t)~forValue - 1; context.forValue = forValue <= INT32_MAX ? forValue : -(int32_t)~forValue - 1;
struct Symbol *sym = sym_AddVar(context.forName.c_str(), context.forValue); Symbol *sym = sym_AddVar(context.forName.c_str(), context.forValue);
// This error message will refer to the current iteration // This error message will refer to the current iteration
if (sym->type != SYM_VAR) if (sym->type != SYM_VAR)
@@ -233,7 +233,7 @@ bool yywrap(void)
return true; return true;
} }
struct Context oldContext = contextStack.top(); Context oldContext = contextStack.top();
contextStack.pop(); contextStack.pop();
@@ -256,7 +256,7 @@ bool yywrap(void)
// Make sure not to switch the lexer state before calling this, so the saved line no is correct. // Make sure not to switch the lexer state before calling this, so the saved line no is correct.
// BE CAREFUL! This modifies the file stack directly, you should have set up the file info first. // BE CAREFUL! This modifies the file stack directly, you should have set up the file info first.
// Callers should set `contextStack.top().lexerState` after this so it is not NULL. // Callers should set `contextStack.top().lexerState` after this so it is not NULL.
static struct Context &newContext(struct FileStackNode *fileInfo) static Context &newContext(FileStackNode *fileInfo)
{ {
if (contextStack.size() > maxRecursionDepth) if (contextStack.size() > maxRecursionDepth)
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth); fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
@@ -264,13 +264,13 @@ static struct Context &newContext(struct FileStackNode *fileInfo)
// Save the current `\@` value, to be restored when this context ends // Save the current `\@` value, to be restored when this context ends
contextStack.top().uniqueID = macro_GetUniqueID(); contextStack.top().uniqueID = macro_GetUniqueID();
struct FileStackNode *parent = contextStack.top().fileInfo; FileStackNode *parent = contextStack.top().fileInfo;
fileInfo->parent = parent; fileInfo->parent = parent;
fileInfo->lineNo = lexer_GetLineNo(); fileInfo->lineNo = lexer_GetLineNo();
fileInfo->referenced = false; fileInfo->referenced = false;
struct Context &context = contextStack.emplace(); Context &context = contextStack.emplace();
context.fileInfo = fileInfo; context.fileInfo = fileInfo;
context.isForLoop = false; context.isForLoop = false;
@@ -294,7 +294,7 @@ void fstk_RunInclude(char const *path)
return; return;
} }
struct FileStackNode *fileInfo = new(std::nothrow) struct FileStackNode(); FileStackNode *fileInfo = new(std::nothrow) FileStackNode();
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));
@@ -305,7 +305,7 @@ void fstk_RunInclude(char const *path)
delete fullPath; delete fullPath;
uint32_t uniqueID = contextStack.top().uniqueID; uint32_t uniqueID = contextStack.top().uniqueID;
struct Context &context = newContext(fileInfo); Context &context = newContext(fileInfo);
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str())) if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
fatalerror("Failed to set up lexer for file include\n"); fatalerror("Failed to set up lexer for file include\n");
@@ -330,7 +330,7 @@ static void runPreIncludeFile(void)
return; return;
} }
struct FileStackNode *fileInfo = new(std::nothrow) struct FileStackNode(); FileStackNode *fileInfo = new(std::nothrow) FileStackNode();
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));
@@ -340,7 +340,7 @@ static void runPreIncludeFile(void)
fileInfo->data = *fullPath; fileInfo->data = *fullPath;
delete fullPath; delete fullPath;
struct Context &context = newContext(fileInfo); Context &context = newContext(fileInfo);
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str())) if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
fatalerror("Failed to set up lexer for file include\n"); fatalerror("Failed to set up lexer for file include\n");
@@ -349,9 +349,9 @@ static void runPreIncludeFile(void)
context.uniqueID = macro_UndefUniqueID(); context.uniqueID = macro_UndefUniqueID();
} }
void fstk_RunMacro(char const *macroName, struct MacroArgs *args) void fstk_RunMacro(char const *macroName, MacroArgs *args)
{ {
struct Symbol *macro = sym_FindExactSymbol(macroName); Symbol *macro = sym_FindExactSymbol(macroName);
if (!macro) { if (!macro) {
error("Macro \"%s\" not defined\n", macroName); error("Macro \"%s\" not defined\n", macroName);
@@ -363,7 +363,7 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
} }
contextStack.top().macroArgs = macro_GetCurrentArgs(); contextStack.top().macroArgs = macro_GetCurrentArgs();
struct FileStackNode *fileInfo = new(std::nothrow) struct FileStackNode(); FileStackNode *fileInfo = new(std::nothrow) FileStackNode();
if (!fileInfo) { if (!fileInfo) {
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));
@@ -375,7 +375,7 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
// Print the name... // Print the name...
std::string &fileInfoName = fileInfo->name(); std::string &fileInfoName = fileInfo->name();
for (struct FileStackNode const *node = macro->src; node; node = node->parent) { for (FileStackNode const *node = macro->src; node; node = node->parent) {
if (node->type != NODE_REPT) { if (node->type != NODE_REPT) {
fileInfoName.append(node->name()); fileInfoName.append(node->name());
break; break;
@@ -396,7 +396,7 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
fileInfoName.append("::"); fileInfoName.append("::");
fileInfoName.append(macro->name); fileInfoName.append(macro->name);
struct Context &context = newContext(fileInfo); Context &context = newContext(fileInfo);
lexer_OpenFileView(context.lexerState, "MACRO", macro->macro.value, macro->macro.size, lexer_OpenFileView(context.lexerState, "MACRO", macro->macro.value, macro->macro.size,
macro->fileLine); macro->fileLine);
@@ -410,7 +410,7 @@ static bool newReptContext(int32_t reptLineNo, char *body, size_t size)
uint32_t reptDepth = contextStack.top().fileInfo->type == NODE_REPT uint32_t reptDepth = contextStack.top().fileInfo->type == NODE_REPT
? contextStack.top().fileInfo->iters().size() ? contextStack.top().fileInfo->iters().size()
: 0; : 0;
struct FileStackNode *fileInfo = new(std::nothrow) struct FileStackNode(); FileStackNode *fileInfo = new(std::nothrow) FileStackNode();
if (!fileInfo) { if (!fileInfo) {
error("Failed to alloc file info for REPT: %s\n", strerror(errno)); error("Failed to alloc file info for REPT: %s\n", strerror(errno));
@@ -423,7 +423,7 @@ static bool newReptContext(int32_t reptLineNo, char *body, size_t size)
fileInfo->iters().insert(fileInfo->iters().end(), RANGE(contextStack.top().fileInfo->iters())); fileInfo->iters().insert(fileInfo->iters().end(), RANGE(contextStack.top().fileInfo->iters()));
} }
struct Context &context = newContext(fileInfo); Context &context = newContext(fileInfo);
// Correct our line number, which currently points to the `ENDR` line // Correct our line number, which currently points to the `ENDR` line
context.fileInfo->lineNo = reptLineNo; context.fileInfo->lineNo = reptLineNo;
@@ -447,7 +447,7 @@ void fstk_RunRept(uint32_t count, int32_t reptLineNo, char *body, size_t size)
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step, void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char *body, size_t size) int32_t reptLineNo, char *body, size_t size)
{ {
struct Symbol *sym = sym_AddVar(symName, start); Symbol *sym = sym_AddVar(symName, start);
if (sym->type != SYM_VAR) if (sym->type != SYM_VAR)
return; return;
@@ -470,7 +470,7 @@ void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
if (!newReptContext(reptLineNo, body, size)) if (!newReptContext(reptLineNo, body, size))
return; return;
struct Context &context = contextStack.top(); Context &context = contextStack.top();
context.nbReptIters = count; context.nbReptIters = count;
context.isForLoop = true; context.isForLoop = true;
@@ -505,13 +505,13 @@ void fstk_NewRecursionDepth(size_t newDepth)
void fstk_Init(char const *mainPath, size_t maxDepth) void fstk_Init(char const *mainPath, size_t maxDepth)
{ {
struct Context &context = contextStack.emplace(); Context &context = contextStack.emplace();
if (!lexer_OpenFile(context.lexerState, mainPath)) if (!lexer_OpenFile(context.lexerState, mainPath))
fatalerror("Failed to open main file\n"); fatalerror("Failed to open main file\n");
lexer_SetState(&context.lexerState); lexer_SetState(&context.lexerState);
struct FileStackNode *fileInfo = new(std::nothrow) struct FileStackNode(); FileStackNode *fileInfo = new(std::nothrow) FileStackNode();
if (!fileInfo) if (!fileInfo)
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));

View File

@@ -298,10 +298,10 @@ static bool isWhitespace(int c)
return c == ' ' || c == '\t'; return c == ' ' || c == '\t';
} }
struct LexerState *lexerState = NULL; LexerState *lexerState = NULL;
struct LexerState *lexerStateEOL = NULL; LexerState *lexerStateEOL = NULL;
static void initState(struct LexerState &state) static void initState(LexerState &state)
{ {
state.mode = LEXER_NORMAL; state.mode = LEXER_NORMAL;
state.atLineStart = true; // yylex() will init colNo due to this state.atLineStart = true; // yylex() will init colNo due to this
@@ -364,7 +364,7 @@ void lexer_ReachELSEBlock(void)
lexerState->ifStack.front().reachedElseBlock = true; lexerState->ifStack.front().reachedElseBlock = true;
} }
bool lexer_OpenFile(struct LexerState &state, char const *path) bool lexer_OpenFile(LexerState &state, char const *path)
{ {
bool isStdin = !strcmp(path, "-"); bool isStdin = !strcmp(path, "-");
struct stat fileInfo; struct stat fileInfo;
@@ -431,7 +431,7 @@ bool lexer_OpenFile(struct LexerState &state, char const *path)
return true; return true;
} }
void lexer_OpenFileView(struct LexerState &state, char const *path, char *buf, size_t size, uint32_t lineNo) void lexer_OpenFileView(LexerState &state, char const *path, char *buf, size_t size, uint32_t lineNo)
{ {
state.path = path; // Used to report read errors in `peekInternal` state.path = path; // Used to report read errors in `peekInternal`
state.isFile = false; state.isFile = false;
@@ -451,7 +451,7 @@ void lexer_RestartRept(uint32_t lineNo)
lexerState->lineNo = lineNo; lexerState->lineNo = lineNo;
} }
void lexer_CleanupState(struct LexerState &state) void lexer_CleanupState(LexerState &state)
{ {
// A big chunk of the lexer state soundness is the file stack ("fstack"). // A big chunk of the lexer state soundness is the file stack ("fstack").
// Each context in the fstack has its own *unique* lexer state; thus, we always guarantee // Each context in the fstack has its own *unique* lexer state; thus, we always guarantee
@@ -523,7 +523,7 @@ void lexer_CheckRecursionDepth(void)
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth); fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
} }
static void freeExpansion(struct Expansion &expansion) static void freeExpansion(Expansion &expansion)
{ {
free(expansion.name); free(expansion.name);
if (expansion.owned) if (expansion.owned)
@@ -573,7 +573,7 @@ static uint32_t readBracketedMacroArgNum(void)
} }
symName[i] = '\0'; symName[i] = '\0';
struct Symbol const *sym = sym_FindScopedValidSymbol(symName); Symbol const *sym = sym_FindScopedValidSymbol(symName);
if (!sym) { if (!sym) {
error("Bracketed symbol \"%s\" does not exist\n", symName); error("Bracketed symbol \"%s\" does not exist\n", symName);
@@ -654,7 +654,7 @@ static size_t readInternal(size_t bufIndex, size_t nbChars)
// We only need one character of lookahead, for macro arguments // We only need one character of lookahead, for macro arguments
static int peekInternal(uint8_t distance) static int peekInternal(uint8_t distance)
{ {
for (struct Expansion &exp : lexerState->expansions) { for (Expansion &exp : lexerState->expansions) {
// An expansion that has reached its end will have `exp->offset` == `exp->size`, // An expansion that has reached its end will have `exp->offset` == `exp->size`,
// and `peekInternal` will continue with its parent // and `peekInternal` will continue with its parent
assert(exp.offset <= exp.size); assert(exp.offset <= exp.size);
@@ -775,7 +775,7 @@ static void shiftChar(void)
restart: restart:
if (!lexerState->expansions.empty()) { if (!lexerState->expansions.empty()) {
// Advance within the current expansion // Advance within the current expansion
struct Expansion &expansion = lexerState->expansions.front(); Expansion &expansion = lexerState->expansions.front();
assert(expansion.offset <= expansion.size); assert(expansion.offset <= expansion.size);
expansion.offset++; expansion.offset++;
@@ -840,7 +840,7 @@ void lexer_DumpStringExpansions(void)
if (!lexerState) if (!lexerState)
return; return;
for (struct Expansion &exp : lexerState->expansions) { for (Expansion &exp : lexerState->expansions) {
// Only register EQUS expansions, not string args // Only register EQUS expansions, not string args
if (exp.name) if (exp.name)
fprintf(stderr, "while expanding symbol \"%s\"\n", exp.name); fprintf(stderr, "while expanding symbol \"%s\"\n", exp.name);
@@ -1184,7 +1184,7 @@ static char const *readInterpolation(size_t depth)
char symName[MAXSYMLEN + 1]; char symName[MAXSYMLEN + 1];
size_t i = 0; size_t i = 0;
struct FormatSpec fmt = fmt_NewSpec(); FormatSpec fmt = fmt_NewSpec();
bool disableInterpolation = lexerState->disableInterpolation; bool disableInterpolation = lexerState->disableInterpolation;
// In a context where `lexerState->disableInterpolation` is true, `peek` will expand // In a context where `lexerState->disableInterpolation` is true, `peek` will expand
@@ -1239,7 +1239,7 @@ static char const *readInterpolation(size_t depth)
static char buf[MAXSTRLEN + 1]; static char buf[MAXSTRLEN + 1];
struct Symbol const *sym = sym_FindScopedValidSymbol(symName); Symbol const *sym = sym_FindScopedValidSymbol(symName);
if (!sym) { if (!sym) {
error("Interpolated symbol \"%s\" does not exist\n", symName); error("Interpolated symbol \"%s\" does not exist\n", symName);
@@ -1881,7 +1881,7 @@ static int yylex_NORMAL(void)
// Local symbols cannot be string expansions // Local symbols cannot be string expansions
if (tokenType == T_ID && lexerState->expandStrings) { if (tokenType == T_ID && lexerState->expandStrings) {
// Attempt string expansion // Attempt string expansion
struct Symbol const *sym = sym_FindExactSymbol(yylval.symName); Symbol const *sym = sym_FindExactSymbol(yylval.symName);
if (sym && sym->type == SYM_EQUS) { if (sym && sym->type == SYM_EQUS) {
char const *s = sym_GetStringValue(sym); char const *s = sym_GetStringValue(sym);
@@ -2286,7 +2286,7 @@ int yylex(void)
return token; return token;
} }
static void startCapture(struct CaptureBody *capture) static void startCapture(CaptureBody *capture)
{ {
assert(!lexerState->capturing); assert(!lexerState->capturing);
lexerState->capturing = true; lexerState->capturing = true;
@@ -2306,7 +2306,7 @@ static void startCapture(struct CaptureBody *capture)
} }
} }
static void endCapture(struct CaptureBody *capture) static void endCapture(CaptureBody *capture)
{ {
// This being NULL means we're capturing from the capture buf, which is `realloc`'d during // This being NULL means we're capturing from the capture buf, which is `realloc`'d during
// the whole capture process, and so MUST be retrieved at the end // the whole capture process, and so MUST be retrieved at the end
@@ -2320,7 +2320,7 @@ static void endCapture(struct CaptureBody *capture)
lexerState->disableInterpolation = false; lexerState->disableInterpolation = false;
} }
bool lexer_CaptureRept(struct CaptureBody *capture) bool lexer_CaptureRept(CaptureBody *capture)
{ {
startCapture(capture); startCapture(capture);
@@ -2378,7 +2378,7 @@ finish:
return c != EOF; return c != EOF;
} }
bool lexer_CaptureMacroBody(struct CaptureBody *capture) bool lexer_CaptureMacroBody(CaptureBody *capture)
{ {
startCapture(capture); startCapture(capture);

View File

@@ -18,7 +18,7 @@ struct MacroArgs {
std::vector<char *> args; std::vector<char *> args;
}; };
static struct MacroArgs *macroArgs = NULL; static MacroArgs *macroArgs = NULL;
static uint32_t uniqueID = 0; static uint32_t uniqueID = 0;
static uint32_t maxUniqueID = 0; static uint32_t maxUniqueID = 0;
// The initialization is somewhat harmful, since it is never used, but it // The initialization is somewhat harmful, since it is never used, but it
@@ -27,14 +27,14 @@ static uint32_t maxUniqueID = 0;
static char uniqueIDBuf[] = "_u4294967295"; // UINT32_MAX static char uniqueIDBuf[] = "_u4294967295"; // UINT32_MAX
static char *uniqueIDPtr = NULL; static char *uniqueIDPtr = NULL;
struct MacroArgs *macro_GetCurrentArgs(void) MacroArgs *macro_GetCurrentArgs(void)
{ {
return macroArgs; return macroArgs;
} }
struct MacroArgs *macro_NewArgs(void) MacroArgs *macro_NewArgs(void)
{ {
struct MacroArgs *args = new(std::nothrow) struct MacroArgs(); MacroArgs *args = new(std::nothrow) MacroArgs();
if (!args) if (!args)
fatalerror("Unable to register macro arguments: %s\n", strerror(errno)); fatalerror("Unable to register macro arguments: %s\n", strerror(errno));
@@ -43,7 +43,7 @@ struct MacroArgs *macro_NewArgs(void)
return args; return args;
} }
void macro_AppendArg(struct MacroArgs *args, char *s) void macro_AppendArg(MacroArgs *args, char *s)
{ {
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");
@@ -52,12 +52,12 @@ void macro_AppendArg(struct MacroArgs *args, char *s)
args->args.push_back(s); args->args.push_back(s);
} }
void macro_UseNewArgs(struct MacroArgs *args) void macro_UseNewArgs(MacroArgs *args)
{ {
macroArgs = args; macroArgs = args;
} }
void macro_FreeArgs(struct MacroArgs *args) void macro_FreeArgs(MacroArgs *args)
{ {
for (char *arg : args->args) for (char *arg : args->args)
free(arg); free(arg);

View File

@@ -97,7 +97,7 @@ static int depType; // Variants of `-M`
// except if it doesn't create any ambiguity (`verbose` versus `version`). // except if it doesn't create any ambiguity (`verbose` versus `version`).
// This is because long opt matching, even to a single char, is prioritized // This is because long opt matching, even to a single char, is prioritized
// over short opt matching // over short opt matching
static struct option const longopts[] = { static option const longopts[] = {
{ "binary-digits", required_argument, NULL, 'b' }, { "binary-digits", required_argument, NULL, 'b' },
{ "define", required_argument, NULL, 'D' }, { "define", required_argument, NULL, 'D' },
{ "export-all", no_argument, NULL, 'E' }, { "export-all", no_argument, NULL, 'E' },

View File

@@ -31,7 +31,7 @@ struct OptStackEntry {
enum WarningState warningStates[numWarningStates]; enum WarningState warningStates[numWarningStates];
}; };
static std::stack<struct OptStackEntry> stack; static std::stack<OptStackEntry> stack;
void opt_B(char const chars[2]) void opt_B(char const chars[2])
{ {
@@ -241,7 +241,7 @@ void opt_Parse(char *s)
void opt_Push(void) void opt_Push(void)
{ {
struct OptStackEntry entry; OptStackEntry entry;
// Both of these are pulled from lexer.hpp // Both of these are pulled from lexer.hpp
entry.binary[0] = binDigits[0]; entry.binary[0] = binDigits[0];
@@ -280,7 +280,7 @@ void opt_Pop(void)
return; return;
} }
struct OptStackEntry entry = stack.top(); OptStackEntry entry = stack.top();
stack.pop(); stack.pop();
opt_B(entry.binary); opt_B(entry.binary);

View File

@@ -28,19 +28,19 @@
#include "platform.hpp" // strdup #include "platform.hpp" // strdup
struct Assertion { struct Assertion {
struct Patch patch; Patch patch;
struct Section *section; Section *section;
std::string message; std::string message;
}; };
const char *objectName; const char *objectName;
// List of symbols to put in the object file // List of symbols to put in the object file
static std::vector<struct Symbol *> objectSymbols; static std::vector<Symbol *> objectSymbols;
static std::deque<struct Assertion> assertions; static std::deque<Assertion> assertions;
static std::deque<struct FileStackNode *> fileStackNodes; static std::deque<FileStackNode *> fileStackNodes;
// Write a long to a file (little-endian) // Write a long to a file (little-endian)
static void putlong(uint32_t i, FILE *f) static void putlong(uint32_t i, FILE *f)
@@ -59,7 +59,7 @@ static void putstring(char const *s, FILE *f)
putc(0, f); putc(0, f);
} }
void out_RegisterNode(struct FileStackNode *node) void out_RegisterNode(FileStackNode *node)
{ {
// If node is not already registered, register it (and parents), and give it a unique ID // If node is not already registered, register it (and parents), and give it a unique ID
for (; node && node->ID == (uint32_t)-1; node = node->parent) { for (; node && node->ID == (uint32_t)-1; node = node->parent) {
@@ -68,7 +68,7 @@ void out_RegisterNode(struct FileStackNode *node)
} }
} }
void out_ReplaceNode(struct FileStackNode * /* node */) void out_ReplaceNode(FileStackNode * /* node */)
{ {
#if 0 #if 0
This is code intended to replace a node, which is pretty useless until ref counting is added... This is code intended to replace a node, which is pretty useless until ref counting is added...
@@ -85,7 +85,7 @@ This is code intended to replace a node, which is pretty useless until ref count
} }
// Return a section's ID, or -1 if the section is not in the list // Return a section's ID, or -1 if the section is not in the list
static uint32_t getSectIDIfAny(struct Section *sect) static uint32_t getSectIDIfAny(Section *sect)
{ {
if (!sect) if (!sect)
return (uint32_t)-1; return (uint32_t)-1;
@@ -99,7 +99,7 @@ static uint32_t getSectIDIfAny(struct Section *sect)
} }
// Write a patch to a file // Write a patch to a file
static void writepatch(struct Patch const &patch, FILE *f) static void writepatch(Patch const &patch, FILE *f)
{ {
assert(patch.src->ID != (uint32_t)-1); assert(patch.src->ID != (uint32_t)-1);
putlong(patch.src->ID, f); putlong(patch.src->ID, f);
@@ -113,7 +113,7 @@ static void writepatch(struct Patch const &patch, FILE *f)
} }
// Write a section to a file // Write a section to a file
static void writesection(struct Section const &sect, FILE *f) static void writesection(Section const &sect, FILE *f)
{ {
putstring(sect.name, f); putstring(sect.name, f);
@@ -133,13 +133,13 @@ static void writesection(struct Section const &sect, FILE *f)
fwrite(sect.data.data(), 1, sect.size, f); fwrite(sect.data.data(), 1, sect.size, f);
putlong(sect.patches.size(), f); putlong(sect.patches.size(), f);
for (struct Patch const &patch : sect.patches) for (Patch const &patch : sect.patches)
writepatch(patch, f); writepatch(patch, f);
} }
} }
// Write a symbol to a file // Write a symbol to a file
static void writesymbol(struct Symbol const *sym, FILE *f) static void writesymbol(Symbol const *sym, FILE *f)
{ {
putstring(sym->name, f); putstring(sym->name, f);
if (!sym_IsDefined(sym)) { if (!sym_IsDefined(sym)) {
@@ -155,7 +155,7 @@ static void writesymbol(struct Symbol const *sym, FILE *f)
} }
} }
static void registerSymbol(struct Symbol *sym) static void registerSymbol(Symbol *sym)
{ {
sym->ID = objectSymbols.size(); sym->ID = objectSymbols.size();
objectSymbols.push_back(sym); objectSymbols.push_back(sym);
@@ -164,7 +164,7 @@ static void registerSymbol(struct Symbol *sym)
// Returns a symbol's ID within the object file // Returns a symbol's ID within the object file
// If the symbol does not have one, one is assigned by registering the symbol // If the symbol does not have one, one is assigned by registering the symbol
static uint32_t getSymbolID(struct Symbol *sym) static uint32_t getSymbolID(Symbol *sym)
{ {
if (sym->ID == (uint32_t)-1 && !sym_IsPC(sym)) if (sym->ID == (uint32_t)-1 && !sym_IsPC(sym))
registerSymbol(sym); registerSymbol(sym);
@@ -182,7 +182,7 @@ static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &
uint8_t rpndata = popbyte(); uint8_t rpndata = popbyte();
switch (rpndata) { switch (rpndata) {
struct Symbol *sym; Symbol *sym;
uint32_t value; uint32_t value;
uint8_t b; uint8_t b;
size_t i; size_t i;
@@ -267,9 +267,9 @@ static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &
} }
} }
static void initpatch(struct Patch &patch, uint32_t type, struct Expression const *expr, uint32_t ofs) static void initpatch(Patch &patch, uint32_t type, Expression const *expr, uint32_t ofs)
{ {
struct FileStackNode *node = fstk_GetFileStack(); FileStackNode *node = fstk_GetFileStack();
patch.type = type; patch.type = type;
patch.src = node; patch.src = node;
@@ -295,10 +295,10 @@ static void initpatch(struct Patch &patch, uint32_t type, struct Expression cons
} }
// Create a new patch (includes the rpn expr) // Create a new patch (includes the rpn expr)
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, uint32_t pcShift) void out_CreatePatch(uint32_t type, Expression const *expr, uint32_t ofs, uint32_t pcShift)
{ {
// Add the patch to the list // Add the patch to the list
struct Patch &patch = currentSection->patches.emplace_front(); Patch &patch = currentSection->patches.emplace_front();
initpatch(patch, type, expr, ofs); initpatch(patch, type, expr, ofs);
@@ -309,22 +309,21 @@ void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs,
} }
// Creates an assert that will be written to the object file // Creates an assert that will be written to the object file
void out_CreateAssert(enum AssertionType type, struct Expression const *expr, void out_CreateAssert(enum AssertionType type, Expression const *expr, char const *message, uint32_t ofs)
char const *message, uint32_t ofs)
{ {
struct Assertion &assertion = assertions.emplace_front(); Assertion &assertion = assertions.emplace_front();
initpatch(assertion.patch, type, expr, ofs); initpatch(assertion.patch, type, expr, ofs);
assertion.message = message; assertion.message = message;
} }
static void writeassert(struct Assertion &assert, FILE *f) static void writeassert(Assertion &assert, FILE *f)
{ {
writepatch(assert.patch, f); writepatch(assert.patch, f);
putstring(assert.message.c_str(), f); putstring(assert.message.c_str(), f);
} }
static void writeFileStackNode(struct FileStackNode const *node, FILE *f) static void writeFileStackNode(FileStackNode const *node, FILE *f)
{ {
putlong(node->parent ? node->parent->ID : (uint32_t)-1, f); putlong(node->parent ? node->parent->ID : (uint32_t)-1, f);
putlong(node->lineNo, f); putlong(node->lineNo, f);
@@ -341,7 +340,7 @@ static void writeFileStackNode(struct FileStackNode const *node, FILE *f)
} }
} }
static void registerUnregisteredSymbol(struct Symbol *symbol) static void registerUnregisteredSymbol(Symbol *symbol)
{ {
// Check for symbol->src, to skip any built-in symbol from rgbasm // Check for symbol->src, to skip any built-in symbol from rgbasm
if (symbol->src && symbol->ID == (uint32_t)-1) { if (symbol->src && symbol->ID == (uint32_t)-1) {
@@ -374,7 +373,7 @@ void out_WriteObject(void)
putlong(fileStackNodes.size(), f); putlong(fileStackNodes.size(), f);
for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) { for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) {
struct FileStackNode const *node = *it; FileStackNode const *node = *it;
writeFileStackNode(node, f); writeFileStackNode(node, f);
@@ -385,15 +384,15 @@ void out_WriteObject(void)
it[1]->ID, node->ID); it[1]->ID, node->ID);
} }
for (struct Symbol const *sym : objectSymbols) for (Symbol const *sym : objectSymbols)
writesymbol(sym, f); writesymbol(sym, f);
for (struct Section &sect : sectionList) for (Section &sect : sectionList)
writesection(sect, f); writesection(sect, f);
putlong(assertions.size(), f); putlong(assertions.size(), f);
for (struct Assertion &assert : assertions) for (Assertion &assert : assertions)
writeassert(assert, f); writeassert(assert, f);
fclose(f); fclose(f);

View File

@@ -31,7 +31,7 @@
#include "linkdefs.hpp" #include "linkdefs.hpp"
#include "platform.hpp" // strncasecmp, strdup #include "platform.hpp" // strncasecmp, strdup
static struct CaptureBody captureBody; // Captures a REPT/FOR or MACRO static CaptureBody captureBody; // Captures a REPT/FOR or MACRO
static void upperstring(char *dest, char const *src) static void upperstring(char *dest, char const *src)
{ {
@@ -256,7 +256,7 @@ static void strrpl(char *dest, size_t destLen, char const *src, char const *old,
dest[i] = '\0'; dest[i] = '\0';
} }
static void initStrFmtArgList(struct StrFmtArgList *args) static void initStrFmtArgList(StrFmtArgList *args)
{ {
args->args = new(std::nothrow) std::vector<std::variant<uint32_t, char *>>(); args->args = new(std::nothrow) std::vector<std::variant<uint32_t, char *>>();
if (!args->args) if (!args->args)
@@ -264,7 +264,7 @@ static void initStrFmtArgList(struct StrFmtArgList *args)
strerror(errno)); strerror(errno));
} }
static void freeStrFmtArgList(struct StrFmtArgList *args) static void freeStrFmtArgList(StrFmtArgList *args)
{ {
free(args->format); free(args->format);
for (std::variant<uint32_t, char *> &arg : *args->args) { for (std::variant<uint32_t, char *> &arg : *args->args) {
@@ -297,7 +297,7 @@ static void strfmt(char *dest, size_t destLen, char const *fmt,
continue; continue;
} }
struct FormatSpec spec = fmt_NewSpec(); FormatSpec spec = fmt_NewSpec();
while (c != '\0') { while (c != '\0') {
fmt_UseCharacter(&spec, c); fmt_UseCharacter(&spec, c);
@@ -347,7 +347,7 @@ static void strfmt(char *dest, size_t destLen, char const *fmt,
} }
static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue) { static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue) {
struct Expression oldExpr, constExpr, newExpr; Expression oldExpr, constExpr, newExpr;
int32_t newValue; int32_t newValue;
rpn_Symbol(&oldExpr, symName); rpn_Symbol(&oldExpr, symName);
@@ -357,9 +357,9 @@ static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t
sym_AddVar(symName, newValue); sym_AddVar(symName, newValue);
} }
static void initDsArgList(std::vector<struct Expression> *&args) static void initDsArgList(std::vector<Expression> *&args)
{ {
args = new(std::nothrow) std::vector<struct Expression>(); args = new(std::nothrow) std::vector<Expression>();
if (!args) if (!args)
fatalerror("Failed to allocate memory for ds arg list: %s\n", strerror(errno)); fatalerror("Failed to allocate memory for ds arg list: %s\n", strerror(errno));
} }
@@ -455,18 +455,18 @@ enum {
{ {
char symName[MAXSYMLEN + 1]; char symName[MAXSYMLEN + 1];
char string[MAXSTRLEN + 1]; char string[MAXSTRLEN + 1];
struct Expression expr; Expression expr;
int32_t constValue; int32_t constValue;
enum RPNCommand compoundEqual; enum RPNCommand compoundEqual;
enum SectionModifier sectMod; enum SectionModifier sectMod;
struct SectionSpec sectSpec; SectionSpec sectSpec;
struct MacroArgs *macroArg; MacroArgs *macroArg;
enum AssertionType assertType; enum AssertionType assertType;
struct AlignmentSpec alignSpec; AlignmentSpec alignSpec;
std::vector<struct Expression> *dsArgs; std::vector<Expression> *dsArgs;
std::vector<std::string> *purgeArgs; std::vector<std::string> *purgeArgs;
struct ForArgs forArgs; ForArgs forArgs;
struct StrFmtArgList strfmtArgs; StrFmtArgList strfmtArgs;
bool captureTerminated; bool captureTerminated;
} }
@@ -704,7 +704,7 @@ line : plain_directive endofline
lexer_SetMode(LEXER_NORMAL); lexer_SetMode(LEXER_NORMAL);
lexer_ToggleStringExpansion(true); lexer_ToggleStringExpansion(true);
} endofline { } endofline {
struct Symbol *macro = sym_FindExactSymbol($1); Symbol *macro = sym_FindExactSymbol($1);
if (macro && macro->type == SYM_MACRO) if (macro && macro->type == SYM_MACRO)
fprintf(stderr, fprintf(stderr,
@@ -1649,11 +1649,11 @@ string : T_STRING
freeStrFmtArgList(&$3); freeStrFmtArgList(&$3);
} }
| T_POP_SECTION T_LPAREN scoped_anon_id T_RPAREN { | T_POP_SECTION T_LPAREN scoped_anon_id T_RPAREN {
struct Symbol *sym = sym_FindScopedValidSymbol($3); Symbol *sym = sym_FindScopedValidSymbol($3);
if (!sym) if (!sym)
fatalerror("Unknown symbol \"%s\"\n", $3); fatalerror("Unknown symbol \"%s\"\n", $3);
struct Section const *section = sym_GetSection(sym); Section const *section = sym_GetSection(sym);
if (!section) if (!section)
fatalerror("\"%s\" does not belong to any section\n", sym->name); fatalerror("\"%s\" does not belong to any section\n", sym->name);

View File

@@ -23,7 +23,7 @@
// Makes an expression "not known", also setting its error message // Makes an expression "not known", also setting its error message
template<typename... Ts> template<typename... Ts>
static void makeUnknown(struct Expression *expr, Ts ...parts) static void makeUnknown(Expression *expr, Ts ...parts)
{ {
expr->isKnown = false; expr->isKnown = false;
expr->reason = new std::string(); expr->reason = new std::string();
@@ -32,7 +32,7 @@ static void makeUnknown(struct Expression *expr, Ts ...parts)
(expr->reason->append(parts), ...); (expr->reason->append(parts), ...);
} }
static uint8_t *reserveSpace(struct Expression *expr, uint32_t size) static uint8_t *reserveSpace(Expression *expr, uint32_t size)
{ {
if (!expr->rpn) { if (!expr->rpn) {
expr->rpn = new(std::nothrow) std::vector<uint8_t>(); expr->rpn = new(std::nothrow) std::vector<uint8_t>();
@@ -47,7 +47,7 @@ static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
} }
// Init a RPN expression // Init a RPN expression
static void rpn_Init(struct Expression *expr) static void rpn_Init(Expression *expr)
{ {
expr->reason = NULL; expr->reason = NULL;
expr->isKnown = true; expr->isKnown = true;
@@ -57,7 +57,7 @@ static void rpn_Init(struct Expression *expr)
} }
// Free the RPN expression // Free the RPN expression
void rpn_Free(struct Expression *expr) void rpn_Free(Expression *expr)
{ {
delete expr->rpn; delete expr->rpn;
delete expr->reason; delete expr->reason;
@@ -65,15 +65,15 @@ void rpn_Free(struct Expression *expr)
} }
// Add symbols, constants and operators to expression // Add symbols, constants and operators to expression
void rpn_Number(struct Expression *expr, uint32_t i) void rpn_Number(Expression *expr, uint32_t i)
{ {
rpn_Init(expr); rpn_Init(expr);
expr->val = i; expr->val = i;
} }
void rpn_Symbol(struct Expression *expr, char const *symName) void rpn_Symbol(Expression *expr, char const *symName)
{ {
struct Symbol *sym = sym_FindScopedSymbol(symName); Symbol *sym = sym_FindScopedSymbol(symName);
if (sym_IsPC(sym) && !sect_GetSymbolSection()) { if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
error("PC has no value outside a section\n"); error("PC has no value outside a section\n");
@@ -98,7 +98,7 @@ void rpn_Symbol(struct Expression *expr, char const *symName)
} }
} }
void rpn_BankSelf(struct Expression *expr) void rpn_BankSelf(Expression *expr)
{ {
rpn_Init(expr); rpn_Init(expr);
@@ -114,9 +114,9 @@ void rpn_BankSelf(struct Expression *expr)
} }
} }
void rpn_BankSymbol(struct Expression *expr, char const *symName) void rpn_BankSymbol(Expression *expr, char const *symName)
{ {
struct Symbol const *sym = sym_FindScopedSymbol(symName); Symbol const *sym = sym_FindScopedSymbol(symName);
// The @ symbol is treated differently. // The @ symbol is treated differently.
if (sym_IsPC(sym)) { if (sym_IsPC(sym)) {
@@ -146,11 +146,11 @@ void rpn_BankSymbol(struct Expression *expr, char const *symName)
} }
} }
void rpn_BankSection(struct Expression *expr, char const *sectionName) void rpn_BankSection(Expression *expr, char const *sectionName)
{ {
rpn_Init(expr); rpn_Init(expr);
struct Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
if (section && section->bank != (uint32_t)-1) { if (section && section->bank != (uint32_t)-1) {
expr->val = section->bank; expr->val = section->bank;
@@ -166,11 +166,11 @@ void rpn_BankSection(struct Expression *expr, char const *sectionName)
} }
} }
void rpn_SizeOfSection(struct Expression *expr, char const *sectionName) void rpn_SizeOfSection(Expression *expr, char const *sectionName)
{ {
rpn_Init(expr); rpn_Init(expr);
struct Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
if (section && sect_IsSizeKnown(section)) { if (section && sect_IsSizeKnown(section)) {
expr->val = section->size; expr->val = section->size;
@@ -186,11 +186,11 @@ void rpn_SizeOfSection(struct Expression *expr, char const *sectionName)
} }
} }
void rpn_StartOfSection(struct Expression *expr, char const *sectionName) void rpn_StartOfSection(Expression *expr, char const *sectionName)
{ {
rpn_Init(expr); rpn_Init(expr);
struct Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
if (section && section->org != (uint32_t)-1) { if (section && section->org != (uint32_t)-1) {
expr->val = section->org; expr->val = section->org;
@@ -206,7 +206,7 @@ void rpn_StartOfSection(struct Expression *expr, char const *sectionName)
} }
} }
void rpn_SizeOfSectionType(struct Expression *expr, enum SectionType type) void rpn_SizeOfSectionType(Expression *expr, enum SectionType type)
{ {
rpn_Init(expr); rpn_Init(expr);
makeUnknown(expr, "Section type's size is not known"); makeUnknown(expr, "Section type's size is not known");
@@ -218,7 +218,7 @@ void rpn_SizeOfSectionType(struct Expression *expr, enum SectionType type)
*ptr++ = type; *ptr++ = type;
} }
void rpn_StartOfSectionType(struct Expression *expr, enum SectionType type) void rpn_StartOfSectionType(Expression *expr, enum SectionType type)
{ {
rpn_Init(expr); rpn_Init(expr);
makeUnknown(expr, "Section type's start is not known"); makeUnknown(expr, "Section type's start is not known");
@@ -230,7 +230,7 @@ void rpn_StartOfSectionType(struct Expression *expr, enum SectionType type)
*ptr++ = type; *ptr++ = type;
} }
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src) void rpn_CheckHRAM(Expression *expr, const Expression *src)
{ {
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
@@ -246,7 +246,7 @@ void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
} }
} }
void rpn_CheckRST(struct Expression *expr, const struct Expression *src) void rpn_CheckRST(Expression *expr, const Expression *src)
{ {
*expr = *src; *expr = *src;
@@ -263,7 +263,7 @@ void rpn_CheckRST(struct Expression *expr, const struct Expression *src)
} }
// Checks that an RPN expression's value fits within N bits (signed or unsigned) // Checks that an RPN expression's value fits within N bits (signed or unsigned)
void rpn_CheckNBit(struct Expression const *expr, uint8_t n) void rpn_CheckNBit(Expression const *expr, uint8_t n)
{ {
assert(n != 0); // That doesn't make sense assert(n != 0); // That doesn't make sense
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
@@ -278,7 +278,7 @@ void rpn_CheckNBit(struct Expression const *expr, uint8_t n)
} }
} }
int32_t rpn_GetConstVal(struct Expression const *expr) int32_t rpn_GetConstVal(Expression const *expr)
{ {
if (!rpn_isKnown(expr)) { if (!rpn_isKnown(expr)) {
error("Expected constant expression: %s\n", expr->reason->c_str()); error("Expected constant expression: %s\n", expr->reason->c_str());
@@ -287,7 +287,7 @@ int32_t rpn_GetConstVal(struct Expression const *expr)
return expr->val; return expr->val;
} }
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src) void rpn_LOGNOT(Expression *expr, const Expression *src)
{ {
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
@@ -300,28 +300,27 @@ void rpn_LOGNOT(struct Expression *expr, const struct Expression *src)
} }
} }
struct Symbol const *rpn_SymbolOf(struct Expression const *expr) Symbol const *rpn_SymbolOf(Expression const *expr)
{ {
if (!rpn_isSymbol(expr)) if (!rpn_isSymbol(expr))
return NULL; return NULL;
return sym_FindScopedSymbol((char const *)&(*expr->rpn)[1]); return sym_FindScopedSymbol((char const *)&(*expr->rpn)[1]);
} }
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym) bool rpn_IsDiffConstant(Expression const *src, Symbol const *sym)
{ {
// Check if both expressions only refer to a single symbol // Check if both expressions only refer to a single symbol
struct Symbol const *sym1 = rpn_SymbolOf(src); Symbol const *sym1 = rpn_SymbolOf(src);
if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL) if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
return false; return false;
struct Section const *section1 = sym_GetSection(sym1); Section const *section1 = sym_GetSection(sym1);
struct Section const *section2 = sym_GetSection(sym); Section const *section2 = sym_GetSection(sym);
return section1 && (section1 == section2); return section1 && (section1 == section2);
} }
static bool isDiffConstant(struct Expression const *src1, static bool isDiffConstant(Expression const *src1, Expression const *src2)
struct Expression const *src2)
{ {
return rpn_IsDiffConstant(src1, rpn_SymbolOf(src2)); return rpn_IsDiffConstant(src1, rpn_SymbolOf(src2));
} }
@@ -333,10 +332,10 @@ static bool isDiffConstant(struct Expression const *src1,
* *
* @return The constant result if it can be computed, or -1 otherwise. * @return The constant result if it can be computed, or -1 otherwise.
*/ */
static int32_t tryConstMask(struct Expression const *lhs, struct Expression const *rhs) static int32_t tryConstMask(Expression const *lhs, Expression const *rhs)
{ {
struct Symbol const *sym = rpn_SymbolOf(lhs); Symbol const *sym = rpn_SymbolOf(lhs);
struct Expression const *expr = rhs; Expression const *expr = rhs;
if (!sym || !sym_GetSection(sym)) { if (!sym || !sym_GetSection(sym)) {
// If the lhs isn't a symbol, try again the other way around // If the lhs isn't a symbol, try again the other way around
@@ -351,7 +350,7 @@ static int32_t tryConstMask(struct Expression const *lhs, struct Expression cons
if (!rpn_isKnown(expr)) if (!rpn_isKnown(expr))
return -1; return -1;
// We can now safely use `expr->val` // We can now safely use `expr->val`
struct Section const *sect = sym_GetSection(sym); Section const *sect = sym_GetSection(sym);
int32_t unknownBits = (1 << 16) - (1 << sect->align); // The max alignment is 16 int32_t unknownBits = (1 << 16) - (1 << sect->align); // The max alignment is 16
// The mask must ignore all unknown bits // The mask must ignore all unknown bits
@@ -366,8 +365,7 @@ static int32_t tryConstMask(struct Expression const *lhs, struct Expression cons
return (symbolOfs + sect->alignOfs) & ~unknownBits; return (symbolOfs + sect->alignOfs) & ~unknownBits;
} }
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr, void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2)
const struct Expression *src1, const struct Expression *src2)
{ {
expr->isSymbol = false; expr->isSymbol = false;
int32_t constMaskVal; int32_t constMaskVal;
@@ -512,8 +510,8 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
} }
} else if (op == RPN_SUB && isDiffConstant(src1, src2)) { } else if (op == RPN_SUB && isDiffConstant(src1, src2)) {
struct Symbol const *symbol1 = rpn_SymbolOf(src1); Symbol const *symbol1 = rpn_SymbolOf(src1);
struct Symbol const *symbol2 = rpn_SymbolOf(src2); Symbol const *symbol2 = rpn_SymbolOf(src2);
expr->val = sym_GetValue(symbol1) - sym_GetValue(symbol2); expr->val = sym_GetValue(symbol1) - sym_GetValue(symbol2);
expr->isKnown = true; expr->isKnown = true;
@@ -574,7 +572,7 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
} }
} }
void rpn_HIGH(struct Expression *expr, const struct Expression *src) void rpn_HIGH(Expression *expr, const Expression *src)
{ {
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
@@ -589,7 +587,7 @@ void rpn_HIGH(struct Expression *expr, const struct Expression *src)
} }
} }
void rpn_LOW(struct Expression *expr, const struct Expression *src) void rpn_LOW(Expression *expr, const Expression *src)
{ {
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
@@ -604,7 +602,7 @@ void rpn_LOW(struct Expression *expr, const struct Expression *src)
} }
} }
void rpn_ISCONST(struct Expression *expr, const struct Expression *src) void rpn_ISCONST(Expression *expr, const Expression *src)
{ {
rpn_Init(expr); rpn_Init(expr);
expr->val = rpn_isKnown(src); expr->val = rpn_isKnown(src);
@@ -612,7 +610,7 @@ void rpn_ISCONST(struct Expression *expr, const struct Expression *src)
expr->isSymbol = false; expr->isSymbol = false;
} }
void rpn_NEG(struct Expression *expr, const struct Expression *src) void rpn_NEG(Expression *expr, const Expression *src)
{ {
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
@@ -625,7 +623,7 @@ void rpn_NEG(struct Expression *expr, const struct Expression *src)
} }
} }
void rpn_NOT(struct Expression *expr, const struct Expression *src) void rpn_NOT(Expression *expr, const Expression *src)
{ {
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;

View File

@@ -33,20 +33,20 @@ struct UnionStackEntry {
}; };
struct SectionStackEntry { struct SectionStackEntry {
struct Section *section; Section *section;
struct Section *loadSection; Section *loadSection;
char const *scope; // Section's symbol scope char const *scope; // Section's symbol scope
uint32_t offset; uint32_t offset;
int32_t loadOffset; int32_t loadOffset;
std::stack<struct UnionStackEntry> unionStack; std::stack<UnionStackEntry> unionStack;
}; };
std::stack<struct UnionStackEntry> currentUnionStack; std::stack<UnionStackEntry> currentUnionStack;
std::deque<struct SectionStackEntry> sectionStack; std::deque<SectionStackEntry> sectionStack;
std::deque<struct Section> sectionList; std::deque<Section> sectionList;
uint32_t curOffset; // Offset into the current section (see sect_GetSymbolOffset) uint32_t curOffset; // Offset into the current section (see sect_GetSymbolOffset)
struct Section *currentSection = NULL; Section *currentSection = NULL;
static struct Section *currentLoadSection = NULL; static Section *currentLoadSection = NULL;
char const *currentLoadScope = NULL; char const *currentLoadScope = NULL;
int32_t loadOffset; // Offset into the LOAD section's parent (see sect_GetOutputOffset) int32_t loadOffset; // Offset into the LOAD section's parent (see sect_GetOutputOffset)
@@ -75,7 +75,7 @@ attr_(warn_unused_result) static bool checkcodesection(void)
return false; return false;
} }
attr_(warn_unused_result) static bool checkSectionSize(struct Section const *sect, uint32_t size) attr_(warn_unused_result) static bool checkSectionSize(Section const *sect, uint32_t size)
{ {
uint32_t maxSize = sectionTypeInfo[sect->type].size; uint32_t maxSize = sectionTypeInfo[sect->type].size;
@@ -110,9 +110,9 @@ attr_(warn_unused_result) static bool reserveSpace(uint32_t delta_size)
&& (!currentLoadSection || currentLoadSection->size != UINT32_MAX); && (!currentLoadSection || currentLoadSection->size != UINT32_MAX);
} }
struct Section *sect_FindSectionByName(char const *name) Section *sect_FindSectionByName(char const *name)
{ {
for (struct Section &sect : sectionList) { for (Section &sect : sectionList) {
if (strcmp(name, sect.name) == 0) if (strcmp(name, sect.name) == 0)
return &sect; return &sect;
} }
@@ -126,7 +126,7 @@ do { \
nbSectErrors++; \ nbSectErrors++; \
} while (0) } while (0)
static unsigned int mergeSectUnion(struct Section *sect, enum SectionType type, uint32_t org, static unsigned int mergeSectUnion(Section *sect, enum SectionType type, uint32_t org,
uint8_t alignment, uint16_t alignOffset) uint8_t alignment, uint16_t alignOffset)
{ {
assert(alignment < 16); // Should be ensured by the caller assert(alignment < 16); // Should be ensured by the caller
@@ -171,8 +171,7 @@ static unsigned int mergeSectUnion(struct Section *sect, enum SectionType type,
return nbSectErrors; return nbSectErrors;
} }
static unsigned int mergeFragments(struct Section *sect, uint32_t org, uint8_t alignment, static unsigned int mergeFragments(Section *sect, uint32_t org, uint8_t alignment, uint16_t alignOffset)
uint16_t alignOffset)
{ {
assert(alignment < 16); // Should be ensured by the caller assert(alignment < 16); // Should be ensured by the caller
unsigned int nbSectErrors = 0; unsigned int nbSectErrors = 0;
@@ -220,7 +219,7 @@ static unsigned int mergeFragments(struct Section *sect, uint32_t org, uint8_t a
return nbSectErrors; return nbSectErrors;
} }
static void mergeSections(struct Section *sect, enum SectionType type, uint32_t org, uint32_t bank, static void mergeSections(Section *sect, enum SectionType type, uint32_t org, uint32_t bank,
uint8_t alignment, uint16_t alignOffset, enum SectionModifier mod) uint8_t alignment, uint16_t alignOffset, enum SectionModifier mod)
{ {
unsigned int nbSectErrors = 0; unsigned int nbSectErrors = 0;
@@ -265,12 +264,11 @@ static void mergeSections(struct Section *sect, enum SectionType type, uint32_t
#undef fail #undef fail
// Create a new section, not yet in the list. // Create a new section, not yet in the list.
static struct Section *createSection(char const *name, enum SectionType type, static Section *createSection(char const *name, enum SectionType type, uint32_t org, uint32_t bank,
uint32_t org, uint32_t bank, uint8_t alignment, uint8_t alignment, uint16_t alignOffset, enum SectionModifier mod)
uint16_t alignOffset, enum SectionModifier mod)
{ {
// Add the new section to the list (order doesn't matter) // Add the new section to the list (order doesn't matter)
struct Section &sect = sectionList.emplace_front(); Section &sect = sectionList.emplace_front();
sect.name = strdup(name); sect.name = strdup(name);
if (sect.name == NULL) if (sect.name == NULL)
@@ -294,8 +292,8 @@ static struct Section *createSection(char const *name, enum SectionType type,
} }
// Find a section by name and type. If it doesn't exist, create it. // Find a section by name and type. If it doesn't exist, create it.
static struct Section *getSection(char const *name, enum SectionType type, uint32_t org, static Section *getSection(char const *name, enum SectionType type, uint32_t org,
struct SectionSpec const *attrs, enum SectionModifier mod) SectionSpec const *attrs, enum SectionModifier mod)
{ {
uint32_t bank = attrs->bank; uint32_t bank = attrs->bank;
uint8_t alignment = attrs->alignment; uint8_t alignment = attrs->alignment;
@@ -357,7 +355,7 @@ static struct Section *getSection(char const *name, enum SectionType type, uint3
// Check if another section exists with the same name; merge if yes, otherwise create one // Check if another section exists with the same name; merge if yes, otherwise create one
struct Section *sect = sect_FindSectionByName(name); Section *sect = sect_FindSectionByName(name);
if (sect) { if (sect) {
mergeSections(sect, type, org, bank, alignment, alignOffset, mod); mergeSections(sect, type, org, bank, alignment, alignOffset, mod);
@@ -379,17 +377,17 @@ static void changeSection(void)
// Set the current section by name and type // Set the current section by name and type
void sect_NewSection(char const *name, enum SectionType type, uint32_t org, void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
struct SectionSpec const *attribs, enum SectionModifier mod) SectionSpec const *attribs, enum SectionModifier mod)
{ {
if (currentLoadSection) if (currentLoadSection)
fatalerror("Cannot change the section within a `LOAD` block\n"); fatalerror("Cannot change the section within a `LOAD` block\n");
for (struct SectionStackEntry &entry : sectionStack) { for (SectionStackEntry &entry : sectionStack) {
if (entry.section && !strcmp(name, entry.section->name)) if (entry.section && !strcmp(name, entry.section->name))
fatalerror("Section '%s' is already on the stack\n", name); fatalerror("Section '%s' is already on the stack\n", name);
} }
struct Section *sect = getSection(name, type, org, attribs, mod); Section *sect = getSection(name, type, org, attribs, mod);
changeSection(); changeSection();
curOffset = mod == SECTION_UNION ? 0 : sect->size; curOffset = mod == SECTION_UNION ? 0 : sect->size;
@@ -399,7 +397,7 @@ void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
// Set the current section by name and type // Set the current section by name and type
void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org, void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
struct SectionSpec const *attribs, enum SectionModifier mod) SectionSpec const *attribs, enum SectionModifier mod)
{ {
// Important info: currently, UNION and LOAD cannot interact, since UNION is prohibited in // Important info: currently, UNION and LOAD cannot interact, since UNION is prohibited in
// "code" sections, whereas LOAD is restricted to them. // "code" sections, whereas LOAD is restricted to them.
@@ -424,7 +422,7 @@ void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
return; return;
} }
struct Section *sect = getSection(name, type, org, attribs, mod); Section *sect = getSection(name, type, org, attribs, mod);
currentLoadScope = sym_GetCurrentSymbolScope(); currentLoadScope = sym_GetCurrentSymbolScope();
changeSection(); changeSection();
@@ -447,7 +445,7 @@ void sect_EndLoadSection(void)
sym_SetCurrentSymbolScope(currentLoadScope); sym_SetCurrentSymbolScope(currentLoadScope);
} }
struct Section *sect_GetSymbolSection(void) Section *sect_GetSymbolSection(void)
{ {
return currentLoadSection ? currentLoadSection : currentSection; return currentLoadSection ? currentLoadSection : currentSection;
} }
@@ -466,7 +464,7 @@ uint32_t sect_GetOutputOffset(void)
// Returns how many bytes need outputting for the specified alignment and offset to succeed // Returns how many bytes need outputting for the specified alignment and offset to succeed
uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset) uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset)
{ {
struct Section *sect = sect_GetSymbolSection(); Section *sect = sect_GetSymbolSection();
if (!sect) if (!sect)
return 0; return 0;
@@ -489,7 +487,7 @@ void sect_AlignPC(uint8_t alignment, uint16_t offset)
if (!checksection()) if (!checksection())
return; return;
struct Section *sect = sect_GetSymbolSection(); Section *sect = sect_GetSymbolSection();
uint32_t alignSize = 1 << alignment; // Size of an aligned "block" uint32_t alignSize = 1 << alignment; // Size of an aligned "block"
if (sect->org != (uint32_t)-1) { if (sect->org != (uint32_t)-1) {
@@ -544,7 +542,7 @@ static void writelong(uint32_t b)
writebyte(b >> 24); writebyte(b >> 24);
} }
static void createPatch(enum PatchType type, struct Expression const *expr, uint32_t pcShift) static void createPatch(enum PatchType type, Expression const *expr, uint32_t pcShift)
{ {
out_CreatePatch(type, expr, sect_GetOutputOffset(), pcShift); out_CreatePatch(type, expr, sect_GetOutputOffset(), pcShift);
} }
@@ -570,7 +568,7 @@ void sect_StartUnion(void)
static void endUnionMember(void) static void endUnionMember(void)
{ {
struct UnionStackEntry &member = currentUnionStack.top(); UnionStackEntry &member = currentUnionStack.top();
uint32_t memberSize = curOffset - member.start; uint32_t memberSize = curOffset - member.start;
if (memberSize > member.size) if (memberSize > member.size)
@@ -670,7 +668,7 @@ void sect_Skip(uint32_t skip, bool ds)
// Output a relocatable byte. Checking will be done to see if it // Output a relocatable byte. Checking will be done to see if it
// is an absolute value in disguise. // is an absolute value in disguise.
void sect_RelByte(struct Expression *expr, uint32_t pcShift) void sect_RelByte(Expression *expr, uint32_t pcShift)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
@@ -688,7 +686,7 @@ void sect_RelByte(struct Expression *expr, uint32_t pcShift)
// Output several copies of a relocatable byte. Checking will be done to see if // Output several copies of a relocatable byte. Checking will be done to see if
// it is an absolute value in disguise. // it is an absolute value in disguise.
void sect_RelBytes(uint32_t n, std::vector<struct Expression> &exprs) void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
@@ -696,7 +694,7 @@ void sect_RelBytes(uint32_t n, std::vector<struct Expression> &exprs)
return; return;
for (uint32_t i = 0; i < n; i++) { for (uint32_t i = 0; i < n; i++) {
struct Expression &expr = exprs[i % exprs.size()]; Expression &expr = exprs[i % exprs.size()];
if (!rpn_isKnown(&expr)) { if (!rpn_isKnown(&expr)) {
createPatch(PATCHTYPE_BYTE, &expr, i); createPatch(PATCHTYPE_BYTE, &expr, i);
@@ -706,13 +704,13 @@ void sect_RelBytes(uint32_t n, std::vector<struct Expression> &exprs)
} }
} }
for (struct Expression &expr : exprs) for (Expression &expr : exprs)
rpn_Free(&expr); rpn_Free(&expr);
} }
// Output a relocatable word. Checking will be done to see if // Output a relocatable word. Checking will be done to see if
// it's an absolute value in disguise. // it's an absolute value in disguise.
void sect_RelWord(struct Expression *expr, uint32_t pcShift) void sect_RelWord(Expression *expr, uint32_t pcShift)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
@@ -730,7 +728,7 @@ void sect_RelWord(struct Expression *expr, uint32_t pcShift)
// Output a relocatable longword. Checking will be done to see if // Output a relocatable longword. Checking will be done to see if
// is an absolute value in disguise. // is an absolute value in disguise.
void sect_RelLong(struct Expression *expr, uint32_t pcShift) void sect_RelLong(Expression *expr, uint32_t pcShift)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
@@ -748,19 +746,19 @@ void sect_RelLong(struct Expression *expr, uint32_t pcShift)
// Output a PC-relative relocatable byte. Checking will be done to see if it // Output a PC-relative relocatable byte. Checking will be done to see if it
// is an absolute value in disguise. // is an absolute value in disguise.
void sect_PCRelByte(struct Expression *expr, uint32_t pcShift) void sect_PCRelByte(Expression *expr, uint32_t pcShift)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
if (!reserveSpace(1)) if (!reserveSpace(1))
return; return;
struct Symbol const *pc = sym_GetPC(); Symbol const *pc = sym_GetPC();
if (!rpn_IsDiffConstant(expr, pc)) { if (!rpn_IsDiffConstant(expr, pc)) {
createPatch(PATCHTYPE_JR, expr, pcShift); createPatch(PATCHTYPE_JR, expr, pcShift);
writebyte(0); writebyte(0);
} else { } else {
struct Symbol const *sym = rpn_SymbolOf(expr); Symbol const *sym = rpn_SymbolOf(expr);
// The offset wraps (jump from ROM to HRAM, for example) // The offset wraps (jump from ROM to HRAM, for example)
int16_t offset; int16_t offset;
@@ -948,7 +946,7 @@ void sect_PopSection(void)
if (currentLoadSection) if (currentLoadSection)
fatalerror("Cannot change the section within a `LOAD` block\n"); fatalerror("Cannot change the section within a `LOAD` block\n");
struct SectionStackEntry entry = sectionStack.front(); SectionStackEntry entry = sectionStack.front();
sectionStack.pop_front(); sectionStack.pop_front();
changeSection(); changeSection();
@@ -976,7 +974,7 @@ void sect_EndSection(void)
sym_SetCurrentSymbolScope(NULL); sym_SetCurrentSymbolScope(NULL);
} }
bool sect_IsSizeKnown(struct Section const NONNULL(sect)) bool sect_IsSizeKnown(Section const NONNULL(sect))
{ {
// SECTION UNION and SECTION FRAGMENT can still grow // SECTION UNION and SECTION FRAGMENT can still grow
if (sect->modifier != SECTION_NORMAL) if (sect->modifier != SECTION_NORMAL)
@@ -987,7 +985,7 @@ bool sect_IsSizeKnown(struct Section const NONNULL(sect))
return false; return false;
// Any section on the stack is still growing // Any section on the stack is still growing
for (struct SectionStackEntry &entry : sectionStack) { for (SectionStackEntry &entry : sectionStack) {
if (entry.section && !strcmp(sect->name, entry.section->name)) if (entry.section && !strcmp(sect->name, entry.section->name))
return false; return false;
} }

View File

@@ -27,23 +27,23 @@
#include "helpers.hpp" #include "helpers.hpp"
#include "version.hpp" #include "version.hpp"
std::map<std::string, struct Symbol> symbols; std::map<std::string, Symbol> symbols;
static const char *labelScope; // Current section's label scope static const char *labelScope; // Current section's label scope
static struct Symbol *PCSymbol; static Symbol *PCSymbol;
static struct Symbol *_NARGSymbol; static Symbol *_NARGSymbol;
static char savedTIME[256]; static char savedTIME[256];
static char savedDATE[256]; static char savedDATE[256];
static char savedTIMESTAMP_ISO8601_LOCAL[256]; static char savedTIMESTAMP_ISO8601_LOCAL[256];
static char savedTIMESTAMP_ISO8601_UTC[256]; static char savedTIMESTAMP_ISO8601_UTC[256];
static bool exportAll; static bool exportAll;
bool sym_IsPC(struct Symbol const *sym) bool sym_IsPC(Symbol const *sym)
{ {
return sym == PCSymbol; return sym == PCSymbol;
} }
void sym_ForEach(void (*callback)(struct Symbol *)) void sym_ForEach(void (*callback)(Symbol *))
{ {
for (auto &it : symbols) for (auto &it : symbols)
callback(&it.second); callback(&it.second);
@@ -60,13 +60,13 @@ static int32_t Callback_NARG(void)
static int32_t CallbackPC(void) static int32_t CallbackPC(void)
{ {
struct Section const *section = sect_GetSymbolSection(); Section const *section = sect_GetSymbolSection();
return section ? section->org + sect_GetSymbolOffset() : 0; return section ? section->org + sect_GetSymbolOffset() : 0;
} }
// Get the value field of a symbol // Get the value field of a symbol
int32_t sym_GetValue(struct Symbol const *sym) int32_t sym_GetValue(Symbol const *sym)
{ {
if (sym_IsNumeric(sym) && sym->hasCallback) if (sym_IsNumeric(sym) && sym->hasCallback)
return sym->numCallback(); return sym->numCallback();
@@ -78,7 +78,7 @@ int32_t sym_GetValue(struct Symbol const *sym)
return sym->value; return sym->value;
} }
static void dumpFilename(struct Symbol const *sym) static void dumpFilename(Symbol const *sym)
{ {
if (sym->src) if (sym->src)
fstk_Dump(sym->src, sym->fileLine); fstk_Dump(sym->src, sym->fileLine);
@@ -89,16 +89,16 @@ static void dumpFilename(struct Symbol const *sym)
} }
// Set a symbol's definition filename and line // Set a symbol's definition filename and line
static void setSymbolFilename(struct Symbol *sym) static void setSymbolFilename(Symbol *sym)
{ {
sym->src = fstk_GetFileStack(); sym->src = fstk_GetFileStack();
sym->fileLine = sym->src ? lexer_GetLineNo() : 0; // This is (NULL, 1) for built-ins sym->fileLine = sym->src ? lexer_GetLineNo() : 0; // This is (NULL, 1) for built-ins
} }
// Update a symbol's definition filename and line // Update a symbol's definition filename and line
static void updateSymbolFilename(struct Symbol *sym) static void updateSymbolFilename(Symbol *sym)
{ {
struct FileStackNode *oldSrc = sym->src; FileStackNode *oldSrc = sym->src;
setSymbolFilename(sym); setSymbolFilename(sym);
// If the old node was referenced, ensure the new one is // If the old node was referenced, ensure the new one is
@@ -108,9 +108,9 @@ static void updateSymbolFilename(struct Symbol *sym)
} }
// Create a new symbol by name // Create a new symbol by name
static struct Symbol *createsymbol(char const *symName) static Symbol *createsymbol(char const *symName)
{ {
struct Symbol &sym = symbols[symName]; Symbol &sym = symbols[symName];
if (snprintf(sym.name, MAXSYMLEN + 1, "%s", symName) > MAXSYMLEN) if (snprintf(sym.name, MAXSYMLEN + 1, "%s", symName) > MAXSYMLEN)
warning(WARNING_LONG_STR, "Symbol name is too long: '%s'\n", symName); warning(WARNING_LONG_STR, "Symbol name is too long: '%s'\n", symName);
@@ -138,7 +138,7 @@ static void fullSymbolName(char *output, size_t outputSize,
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName); fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
} }
static void assignStringSymbol(struct Symbol *sym, char const *value) static void assignStringSymbol(Symbol *sym, char const *value)
{ {
char *string = strdup(value); char *string = strdup(value);
@@ -150,13 +150,13 @@ static void assignStringSymbol(struct Symbol *sym, char const *value)
sym->equs.size = strlen(string); sym->equs.size = strlen(string);
} }
struct Symbol *sym_FindExactSymbol(char const *symName) Symbol *sym_FindExactSymbol(char const *symName)
{ {
auto search = symbols.find(symName); auto search = symbols.find(symName);
return search != symbols.end() ? &search->second : NULL; return search != symbols.end() ? &search->second : NULL;
} }
struct Symbol *sym_FindScopedSymbol(char const *symName) Symbol *sym_FindScopedSymbol(char const *symName)
{ {
if (char const *localName = strchr(symName, '.'); localName) { if (char const *localName = strchr(symName, '.'); localName) {
if (strchr(localName + 1, '.')) if (strchr(localName + 1, '.'))
@@ -173,9 +173,9 @@ struct Symbol *sym_FindScopedSymbol(char const *symName)
return sym_FindExactSymbol(symName); return sym_FindExactSymbol(symName);
} }
struct Symbol *sym_FindScopedValidSymbol(char const *symName) Symbol *sym_FindScopedValidSymbol(char const *symName)
{ {
struct Symbol *sym = sym_FindScopedSymbol(symName); Symbol *sym = sym_FindScopedSymbol(symName);
// `@` has no value outside a section // `@` has no value outside a section
if (sym == PCSymbol && !sect_GetSymbolSection()) { if (sym == PCSymbol && !sect_GetSymbolSection()) {
@@ -188,12 +188,12 @@ struct Symbol *sym_FindScopedValidSymbol(char const *symName)
return sym; return sym;
} }
struct Symbol const *sym_GetPC(void) Symbol const *sym_GetPC(void)
{ {
return PCSymbol; return PCSymbol;
} }
static bool isReferenced(struct Symbol const *sym) static bool isReferenced(Symbol const *sym)
{ {
return sym->ID != (uint32_t)-1; return sym->ID != (uint32_t)-1;
} }
@@ -201,7 +201,7 @@ static bool isReferenced(struct Symbol const *sym)
// Purge a symbol // Purge a symbol
void sym_Purge(std::string const &symName) void sym_Purge(std::string const &symName)
{ {
struct Symbol *sym = sym_FindScopedValidSymbol(symName.c_str()); Symbol *sym = sym_FindScopedValidSymbol(symName.c_str());
if (!sym) { if (!sym) {
error("'%s' not defined\n", symName.c_str()); error("'%s' not defined\n", symName.c_str());
@@ -223,7 +223,7 @@ void sym_Purge(std::string const &symName)
uint32_t sym_GetPCValue(void) uint32_t sym_GetPCValue(void)
{ {
struct Section const *sect = sect_GetSymbolSection(); Section const *sect = sect_GetSymbolSection();
if (!sect) if (!sect)
error("PC has no value outside a section\n"); error("PC has no value outside a section\n");
@@ -235,7 +235,7 @@ uint32_t sym_GetPCValue(void)
} }
// Return a constant symbol's value, assuming it's defined // Return a constant symbol's value, assuming it's defined
uint32_t sym_GetConstantSymValue(struct Symbol const *sym) uint32_t sym_GetConstantSymValue(Symbol const *sym)
{ {
if (sym == PCSymbol) if (sym == PCSymbol)
return sym_GetPCValue(); return sym_GetPCValue();
@@ -250,7 +250,7 @@ uint32_t sym_GetConstantSymValue(struct Symbol const *sym)
// Return a constant symbol's value // Return a constant symbol's value
uint32_t sym_GetConstantValue(char const *symName) uint32_t sym_GetConstantValue(char const *symName)
{ {
struct Symbol const *sym = sym_FindScopedSymbol(symName); Symbol const *sym = sym_FindScopedSymbol(symName);
if (!sym) if (!sym)
error("'%s' not defined\n", symName); error("'%s' not defined\n", symName);
@@ -277,9 +277,9 @@ void sym_SetCurrentSymbolScope(char const *newScope)
* @param symName The name of the symbol to create * @param symName The name of the symbol to create
* @param numeric If false, the symbol may not have been referenced earlier * @param numeric If false, the symbol may not have been referenced earlier
*/ */
static struct Symbol *createNonrelocSymbol(char const *symName, bool numeric) static Symbol *createNonrelocSymbol(char const *symName, bool numeric)
{ {
struct Symbol *sym = sym_FindExactSymbol(symName); Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = createsymbol(symName);
@@ -300,9 +300,9 @@ static struct Symbol *createNonrelocSymbol(char const *symName, bool numeric)
} }
// Add an equated symbol // Add an equated symbol
struct Symbol *sym_AddEqu(char const *symName, int32_t value) Symbol *sym_AddEqu(char const *symName, int32_t value)
{ {
struct Symbol *sym = createNonrelocSymbol(symName, true); Symbol *sym = createNonrelocSymbol(symName, true);
if (!sym) if (!sym)
return NULL; return NULL;
@@ -313,9 +313,9 @@ struct Symbol *sym_AddEqu(char const *symName, int32_t value)
return sym; return sym;
} }
struct Symbol *sym_RedefEqu(char const *symName, int32_t value) Symbol *sym_RedefEqu(char const *symName, int32_t value)
{ {
struct Symbol *sym = sym_FindExactSymbol(symName); Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) if (!sym)
return sym_AddEqu(symName, value); return sym_AddEqu(symName, value);
@@ -349,9 +349,9 @@ struct Symbol *sym_RedefEqu(char const *symName, int32_t value)
* of the string are enough: sym_AddString("M_PI", "3.1415"). This is the same * of the string are enough: sym_AddString("M_PI", "3.1415"). This is the same
* as ``` M_PI EQUS "3.1415" ``` * as ``` M_PI EQUS "3.1415" ```
*/ */
struct Symbol *sym_AddString(char const *symName, char const *value) Symbol *sym_AddString(char const *symName, char const *value)
{ {
struct Symbol *sym = createNonrelocSymbol(symName, false); Symbol *sym = createNonrelocSymbol(symName, false);
if (!sym) if (!sym)
return NULL; return NULL;
@@ -360,9 +360,9 @@ struct Symbol *sym_AddString(char const *symName, char const *value)
return sym; return sym;
} }
struct Symbol *sym_RedefString(char const *symName, char const *value) Symbol *sym_RedefString(char const *symName, char const *value)
{ {
struct Symbol *sym = sym_FindExactSymbol(symName); Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) if (!sym)
return sym_AddString(symName, value); return sym_AddString(symName, value);
@@ -389,9 +389,9 @@ struct Symbol *sym_RedefString(char const *symName, char const *value)
} }
// Alter a mutable symbol's value // Alter a mutable symbol's value
struct Symbol *sym_AddVar(char const *symName, int32_t value) Symbol *sym_AddVar(char const *symName, int32_t value)
{ {
struct Symbol *sym = sym_FindExactSymbol(symName); Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = createsymbol(symName);
@@ -416,10 +416,10 @@ struct Symbol *sym_AddVar(char const *symName, int32_t value)
* @param symName The label's full name (so `.name` is invalid) * @param symName The label's full name (so `.name` is invalid)
* @return The created symbol * @return The created symbol
*/ */
static struct Symbol *addLabel(char const *symName) static Symbol *addLabel(char const *symName)
{ {
assert(symName[0] != '.'); // The symbol name must have been expanded prior assert(symName[0] != '.'); // The symbol name must have been expanded prior
struct Symbol *sym = sym_FindExactSymbol(symName); Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = createsymbol(symName);
@@ -445,7 +445,7 @@ static struct Symbol *addLabel(char const *symName)
} }
// Add a local (`.name` or `Parent.name`) relocatable symbol // Add a local (`.name` or `Parent.name`) relocatable symbol
struct Symbol *sym_AddLocalLabel(char const *symName) Symbol *sym_AddLocalLabel(char const *symName)
{ {
// Assuming no dots in `labelScope` if defined // Assuming no dots in `labelScope` if defined
assert(!labelScope || !strchr(labelScope, '.')); assert(!labelScope || !strchr(labelScope, '.'));
@@ -479,9 +479,9 @@ struct Symbol *sym_AddLocalLabel(char const *symName)
} }
// Add a relocatable symbol // Add a relocatable symbol
struct Symbol *sym_AddLabel(char const *symName) Symbol *sym_AddLabel(char const *symName)
{ {
struct Symbol *sym = addLabel(symName); Symbol *sym = addLabel(symName);
// Set the symbol as the new scope // Set the symbol as the new scope
if (sym) if (sym)
@@ -492,7 +492,7 @@ struct Symbol *sym_AddLabel(char const *symName)
static uint32_t anonLabelID; static uint32_t anonLabelID;
// Add an anonymous label // Add an anonymous label
struct Symbol *sym_AddAnonLabel(void) Symbol *sym_AddAnonLabel(void)
{ {
if (anonLabelID == UINT32_MAX) { if (anonLabelID == UINT32_MAX) {
error("Only %" PRIu32 " anonymous labels can be created!", anonLabelID); error("Only %" PRIu32 " anonymous labels can be created!", anonLabelID);
@@ -537,7 +537,7 @@ void sym_Export(char const *symName)
return; return;
} }
struct Symbol *sym = sym_FindScopedSymbol(symName); Symbol *sym = sym_FindScopedSymbol(symName);
// If the symbol doesn't exist, create a ref that can be purged // If the symbol doesn't exist, create a ref that can be purged
if (!sym) if (!sym)
@@ -546,9 +546,9 @@ void sym_Export(char const *symName)
} }
// Add a macro definition // Add a macro definition
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size) Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size)
{ {
struct Symbol *sym = createNonrelocSymbol(symName, false); Symbol *sym = createNonrelocSymbol(symName, false);
if (!sym) if (!sym)
return NULL; return NULL;
@@ -566,9 +566,9 @@ struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body,
// Flag that a symbol is referenced in an RPN expression // Flag that a symbol is referenced in an RPN expression
// and create it if it doesn't exist yet // and create it if it doesn't exist yet
struct Symbol *sym_Ref(char const *symName) Symbol *sym_Ref(char const *symName)
{ {
struct Symbol *sym = sym_FindScopedSymbol(symName); Symbol *sym = sym_FindScopedSymbol(symName);
if (!sym) { if (!sym) {
char fullname[MAXSYMLEN + 1]; char fullname[MAXSYMLEN + 1];
@@ -593,9 +593,9 @@ void sym_SetExportAll(bool set)
exportAll = set; exportAll = set;
} }
static struct Symbol *createBuiltinSymbol(char const *symName) static Symbol *createBuiltinSymbol(char const *symName)
{ {
struct Symbol *sym = createsymbol(symName); Symbol *sym = createsymbol(symName);
sym->isBuiltin = true; sym->isBuiltin = true;
sym->hasCallback = true; sym->hasCallback = true;
@@ -620,7 +620,7 @@ void sym_Init(time_t now)
sym_AddVar("_RS", 0)->isBuiltin = true; sym_AddVar("_RS", 0)->isBuiltin = true;
#define addSym(fn, name, val) do { \ #define addSym(fn, name, val) do { \
struct Symbol *sym = fn(name, val); \ Symbol *sym = fn(name, val); \
assert(sym); \ assert(sym); \
sym->isBuiltin = true; \ sym->isBuiltin = true; \
} while (0) } while (0)
@@ -641,7 +641,7 @@ void sym_Init(time_t now)
now = 0; now = 0;
} }
const struct tm *time_local = localtime(&now); const tm *time_local = localtime(&now);
strftime(savedTIME, sizeof(savedTIME), "\"%H:%M:%S\"", time_local); strftime(savedTIME, sizeof(savedTIME), "\"%H:%M:%S\"", time_local);
strftime(savedDATE, sizeof(savedDATE), "\"%d %B %Y\"", time_local); strftime(savedDATE, sizeof(savedDATE), "\"%d %B %Y\"", time_local);
@@ -649,7 +649,7 @@ void sym_Init(time_t now)
sizeof(savedTIMESTAMP_ISO8601_LOCAL), "\"%Y-%m-%dT%H:%M:%S%z\"", sizeof(savedTIMESTAMP_ISO8601_LOCAL), "\"%Y-%m-%dT%H:%M:%S%z\"",
time_local); time_local);
const struct tm *time_utc = gmtime(&now); const tm *time_utc = gmtime(&now);
strftime(savedTIMESTAMP_ISO8601_UTC, strftime(savedTIMESTAMP_ISO8601_UTC,
sizeof(savedTIMESTAMP_ISO8601_UTC), "\"%Y-%m-%dT%H:%M:%SZ\"", sizeof(savedTIMESTAMP_ISO8601_UTC), "\"%Y-%m-%dT%H:%M:%SZ\"",

View File

@@ -120,10 +120,10 @@ static void permute(char **argv, int dest, int src)
} }
static int musl_getopt_long_core(int argc, char **argv, char const *optstring, static int musl_getopt_long_core(int argc, char **argv, char const *optstring,
const struct option *longopts, int *idx, int longonly); const option *longopts, int *idx, int longonly);
static int musl_getopt_long(int argc, char **argv, char const *optstring, static int musl_getopt_long(int argc, char **argv, char const *optstring,
const struct option *longopts, int *idx, int longonly) const option *longopts, int *idx, int longonly)
{ {
int ret, skipped, resumed; int ret, skipped, resumed;
@@ -160,7 +160,7 @@ static int musl_getopt_long(int argc, char **argv, char const *optstring,
} }
static int musl_getopt_long_core(int argc, char **argv, char const *optstring, static int musl_getopt_long_core(int argc, char **argv, char const *optstring,
const struct option *longopts, int *idx, int longonly) const option *longopts, int *idx, int longonly)
{ {
musl_optarg = 0; musl_optarg = 0;
if (longopts && argv[musl_optind][0] == '-' && if (longopts && argv[musl_optind][0] == '-' &&
@@ -260,7 +260,7 @@ static int musl_getopt_long_core(int argc, char **argv, char const *optstring,
} }
int musl_getopt_long_only(int argc, char **argv, char const *optstring, int musl_getopt_long_only(int argc, char **argv, char const *optstring,
const struct option *longopts, int *idx) const option *longopts, int *idx)
{ {
return musl_getopt_long(argc, argv, optstring, longopts, idx, 1); return musl_getopt_long(argc, argv, optstring, longopts, idx, 1);
} }

View File

@@ -36,7 +36,7 @@ static const char *optstring = "Ccf:i:jk:l:m:n:Op:r:st:Vv";
* This is because long opt matching, even to a single char, is prioritized * This is because long opt matching, even to a single char, is prioritized
* over short opt matching * over short opt matching
*/ */
static struct option const longopts[] = { static option const longopts[] = {
{ "color-only", no_argument, NULL, 'C' }, { "color-only", no_argument, NULL, 'C' },
{ "color-compatible", no_argument, NULL, 'c' }, { "color-compatible", no_argument, NULL, 'c' },
{ "fix-spec", required_argument, NULL, 'f' }, { "fix-spec", required_argument, NULL, 'f' },

View File

@@ -110,7 +110,7 @@ static char const *optstring = "-Aa:b:Cc:Dd:FfhL:mN:n:Oo:Pp:Qq:r:s:Tt:U:uVvx:Z";
* This is because long opt matching, even to a single char, is prioritized * This is because long opt matching, even to a single char, is prioritized
* over short opt matching * over short opt matching
*/ */
static struct option const longopts[] = { static option const longopts[] = {
{"auto-attr-map", no_argument, NULL, 'A'}, {"auto-attr-map", no_argument, NULL, 'A'},
{"output-attr-map", no_argument, NULL, -'A'}, // Deprecated {"output-attr-map", no_argument, NULL, -'A'}, // Deprecated
{"attr-map", required_argument, NULL, 'a'}, {"attr-map", required_argument, NULL, 'a'},

View File

@@ -27,11 +27,11 @@ struct MemoryLocation {
struct FreeSpace { struct FreeSpace {
uint16_t address; uint16_t address;
uint16_t size; uint16_t size;
struct FreeSpace *next, *prev; FreeSpace *next, *prev;
}; };
// Table of free space for each bank // Table of free space for each bank
struct FreeSpace *memory[SECTTYPE_INVALID]; FreeSpace *memory[SECTTYPE_INVALID];
uint64_t nbSectionsToAssign; uint64_t nbSectionsToAssign;
@@ -39,13 +39,13 @@ uint64_t nbSectionsToAssign;
static void initFreeSpace(void) static void initFreeSpace(void)
{ {
for (enum SectionType type : EnumSeq(SECTTYPE_INVALID)) { for (enum SectionType type : EnumSeq(SECTTYPE_INVALID)) {
memory[type] = (struct FreeSpace *)malloc(sizeof(*memory[type]) * nbbanks(type)); memory[type] = (FreeSpace *)malloc(sizeof(*memory[type]) * nbbanks(type));
if (!memory[type]) if (!memory[type])
err("Failed to init free space for region %d", type); err("Failed to init free space for region %d", type);
for (uint32_t bank = 0; bank < nbbanks(type); bank++) { for (uint32_t bank = 0; bank < nbbanks(type); bank++) {
memory[type][bank].next = memory[type][bank].next =
(struct FreeSpace *)malloc(sizeof(*memory[type][0].next)); (FreeSpace *)malloc(sizeof(*memory[type][0].next));
if (!memory[type][bank].next) if (!memory[type][bank].next)
err("Failed to init free space for region %d bank %" PRIu32, err("Failed to init free space for region %d bank %" PRIu32,
type, bank); type, bank);
@@ -62,14 +62,14 @@ static void initFreeSpace(void)
* @param section The section to assign * @param section The section to assign
* @param location The location to assign the section to * @param location The location to assign the section to
*/ */
static void assignSection(struct Section *section, struct MemoryLocation const *location) static void assignSection(Section *section, MemoryLocation const *location)
{ {
section->org = location->address; section->org = location->address;
section->bank = location->bank; section->bank = location->bank;
// Propagate the assigned location to all UNIONs/FRAGMENTs // Propagate the assigned location to all UNIONs/FRAGMENTs
// so `jr` patches in them will have the correct offset // so `jr` patches in them will have the correct offset
for (struct Section *next = section->nextu; next != NULL; next = next->nextu) { for (Section *next = section->nextu; next != NULL; next = next->nextu) {
next->org = section->org; next->org = section->org;
next->bank = section->bank; next->bank = section->bank;
} }
@@ -88,9 +88,8 @@ static void assignSection(struct Section *section, struct MemoryLocation const *
* @param location The location to attempt placing the section at * @param location The location to attempt placing the section at
* @return True if the location is suitable, false otherwise. * @return True if the location is suitable, false otherwise.
*/ */
static bool isLocationSuitable(struct Section const *section, static bool isLocationSuitable(Section const *section, FreeSpace const *freeSpace,
struct FreeSpace const *freeSpace, MemoryLocation const *location)
struct MemoryLocation const *location)
{ {
if (section->isAddressFixed && section->org != location->address) if (section->isAddressFixed && section->org != location->address)
return false; return false;
@@ -108,12 +107,11 @@ static bool isLocationSuitable(struct Section const *section,
/* /*
* Finds a suitable location to place a section at. * Finds a suitable location to place a section at.
* @param section The section to be placed * @param section The section to be placed
* @param location A pointer to a location struct that will be filled * @param location A pointer to a memory location that will be filled
* @return A pointer to the free space encompassing the location, or NULL if * @return A pointer to the free space encompassing the location, or NULL if
* none was found * none was found
*/ */
static struct FreeSpace *getPlacement(struct Section const *section, static FreeSpace *getPlacement(Section const *section, MemoryLocation *location)
struct MemoryLocation *location)
{ {
static uint16_t curScrambleROM = 0; static uint16_t curScrambleROM = 0;
static uint8_t curScrambleWRAM = 0; static uint8_t curScrambleWRAM = 0;
@@ -137,7 +135,7 @@ static struct FreeSpace *getPlacement(struct Section const *section,
} else { } else {
location->bank = sectionTypeInfo[section->type].firstBank; location->bank = sectionTypeInfo[section->type].firstBank;
} }
struct FreeSpace *space; FreeSpace *space;
for (;;) { for (;;) {
// Switch to the beginning of the next bank // Switch to the beginning of the next bank
@@ -226,9 +224,9 @@ static struct FreeSpace *getPlacement(struct Section const *section,
* sections of decreasing size. * sections of decreasing size.
* @param section The section to place * @param section The section to place
*/ */
static void placeSection(struct Section *section) static void placeSection(Section *section)
{ {
struct MemoryLocation location; MemoryLocation location;
// Specially handle 0-byte SECTIONs, as they can't overlap anything // Specially handle 0-byte SECTIONs, as they can't overlap anything
if (section->size == 0) { if (section->size == 0) {
@@ -246,7 +244,7 @@ static void placeSection(struct Section *section)
// Place section using first-fit decreasing algorithm // Place section using first-fit decreasing algorithm
// https://en.wikipedia.org/wiki/Bin_packing_problem#First-fit_algorithm // https://en.wikipedia.org/wiki/Bin_packing_problem#First-fit_algorithm
struct FreeSpace *freeSpace = getPlacement(section, &location); FreeSpace *freeSpace = getPlacement(section, &location);
if (freeSpace) { if (freeSpace) {
assignSection(section, &location); assignSection(section, &location);
@@ -266,7 +264,7 @@ static void placeSection(struct Section *section)
free(freeSpace); free(freeSpace);
} else if (!noLeftSpace && !noRightSpace) { } else if (!noLeftSpace && !noRightSpace) {
// The free space is split in two // The free space is split in two
struct FreeSpace *newSpace = (struct FreeSpace *)malloc(sizeof(*newSpace)); FreeSpace *newSpace = (FreeSpace *)malloc(sizeof(*newSpace));
if (!newSpace) if (!newSpace)
err("Failed to split new free space"); err("Failed to split new free space");
@@ -334,14 +332,14 @@ static void placeSection(struct Section *section)
#define BANK_CONSTRAINED (1 << 2) #define BANK_CONSTRAINED (1 << 2)
#define ORG_CONSTRAINED (1 << 1) #define ORG_CONSTRAINED (1 << 1)
#define ALIGN_CONSTRAINED (1 << 0) #define ALIGN_CONSTRAINED (1 << 0)
static std::deque<struct Section *> unassignedSections[1 << 3]; static std::deque<Section *> unassignedSections[1 << 3];
/* /*
* Categorize a section depending on how constrained it is * Categorize a section depending on how constrained it is
* This is so the most-constrained sections are placed first * This is so the most-constrained sections are placed first
* @param section The section to categorize * @param section The section to categorize
*/ */
static void categorizeSection(struct Section *section) static void categorizeSection(Section *section)
{ {
uint8_t constraints = 0; uint8_t constraints = 0;
@@ -353,7 +351,7 @@ static void categorizeSection(struct Section *section)
else if (section->isAlignFixed) else if (section->isAlignFixed)
constraints |= ALIGN_CONSTRAINED; constraints |= ALIGN_CONSTRAINED;
std::deque<struct Section *> &sections = unassignedSections[constraints]; std::deque<Section *> &sections = unassignedSections[constraints];
auto pos = sections.begin(); auto pos = sections.begin();
// Insert section while keeping the list sorted by decreasing size // Insert section while keeping the list sorted by decreasing size
@@ -380,7 +378,7 @@ void assign_AssignSections(void)
// Specially process fully-constrained sections because of overlaying // Specially process fully-constrained sections because of overlaying
verbosePrint("Assigning bank+org-constrained...\n"); verbosePrint("Assigning bank+org-constrained...\n");
for (struct Section *section : unassignedSections[BANK_CONSTRAINED | ORG_CONSTRAINED]) for (Section *section : unassignedSections[BANK_CONSTRAINED | ORG_CONSTRAINED])
placeSection(section); placeSection(section);
// If all sections were fully constrained, we have nothing left to do // If all sections were fully constrained, we have nothing left to do
@@ -392,9 +390,9 @@ void assign_AssignSections(void)
if (overlayFileName) { if (overlayFileName) {
fprintf(stderr, "FATAL: All sections must be fixed when using an overlay file"); fprintf(stderr, "FATAL: All sections must be fixed when using an overlay file");
uint8_t nbSections = 0; uint8_t nbSections = 0;
for (int8_t constraints = BANK_CONSTRAINED | ALIGN_CONSTRAINED; for (int8_t constraints = BANK_CONSTRAINED | ALIGN_CONSTRAINED; constraints >= 0;
constraints >= 0; constraints--) { constraints--) {
for (struct Section *section : unassignedSections[constraints]) { for (Section *section : unassignedSections[constraints]) {
fprintf(stderr, "%c \"%s\"", nbSections == 0 ? ';': ',', fprintf(stderr, "%c \"%s\"", nbSections == 0 ? ';': ',',
section->name.c_str()); section->name.c_str());
nbSections++; nbSections++;
@@ -411,9 +409,8 @@ max_out:
} }
// Assign all remaining sections by decreasing constraint order // Assign all remaining sections by decreasing constraint order
for (int8_t constraints = BANK_CONSTRAINED | ALIGN_CONSTRAINED; for (int8_t constraints = BANK_CONSTRAINED | ALIGN_CONSTRAINED; constraints >= 0; constraints--) {
constraints >= 0; constraints--) { for (Section *section : unassignedSections[constraints])
for (struct Section *section : unassignedSections[constraints])
placeSection(section); placeSection(section);
if (!nbSectionsToAssign) if (!nbSectionsToAssign)
@@ -427,11 +424,10 @@ void assign_Cleanup(void)
{ {
for (enum SectionType type : EnumSeq(SECTTYPE_INVALID)) { for (enum SectionType type : EnumSeq(SECTTYPE_INVALID)) {
for (uint32_t bank = 0; bank < nbbanks(type); bank++) { for (uint32_t bank = 0; bank < nbbanks(type); bank++) {
struct FreeSpace *ptr = FreeSpace *ptr = memory[type][bank].next;
memory[type][bank].next;
while (ptr) { while (ptr) {
struct FreeSpace *next = ptr->next; FreeSpace *next = ptr->next;
free(ptr); free(ptr);
ptr = next; ptr = next;

View File

@@ -72,7 +72,7 @@ std::string const &FileStackNode::name() const {
} }
// Helper function to dump a file stack to stderr // Helper function to dump a file stack to stderr
std::string const *dumpFileStack(struct FileStackNode const *node) std::string const *dumpFileStack(FileStackNode const *node)
{ {
std::string const *lastName; std::string const *lastName;
@@ -96,7 +96,7 @@ std::string const *dumpFileStack(struct FileStackNode const *node)
} }
void printDiag(char const *fmt, va_list args, char const *type, void printDiag(char const *fmt, va_list args, char const *type,
struct FileStackNode const *where, uint32_t lineNo) FileStackNode const *where, uint32_t lineNo)
{ {
fputs(type, stderr); fputs(type, stderr);
fputs(": ", stderr); fputs(": ", stderr);
@@ -108,7 +108,7 @@ void printDiag(char const *fmt, va_list args, char const *type,
putc('\n', stderr); putc('\n', stderr);
} }
void warning(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) void warning(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...)
{ {
va_list args; va_list args;
@@ -117,7 +117,7 @@ void warning(struct FileStackNode const *where, uint32_t lineNo, char const *fmt
va_end(args); va_end(args);
} }
void error(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) void error(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...)
{ {
va_list args; va_list args;
@@ -143,7 +143,7 @@ void argErr(char flag, char const *fmt, ...)
nbErrors++; nbErrors++;
} }
[[noreturn]] void fatal(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) [[noreturn]] void fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...)
{ {
va_list args; va_list args;
@@ -172,7 +172,7 @@ static const char *optstring = "dl:m:Mn:O:o:p:S:s:tVvWwx";
* This is because long opt matching, even to a single char, is prioritized * This is because long opt matching, even to a single char, is prioritized
* over short opt matching * over short opt matching
*/ */
static struct option const longopts[] = { static option const longopts[] = {
{ "dmg", no_argument, NULL, 'd' }, { "dmg", no_argument, NULL, 'd' },
{ "linkerscript", required_argument, NULL, 'l' }, { "linkerscript", required_argument, NULL, 'l' },
{ "map", required_argument, NULL, 'm' }, { "map", required_argument, NULL, 'm' },

View File

@@ -25,9 +25,9 @@
#include "linkdefs.hpp" #include "linkdefs.hpp"
#include "version.hpp" #include "version.hpp"
static std::deque<std::vector<struct Symbol>> symbolLists; static std::deque<std::vector<Symbol>> symbolLists;
static std::vector<std::vector<struct FileStackNode>> nodes; static std::vector<std::vector<FileStackNode>> nodes;
static std::deque<struct Assertion> assertions; static std::deque<Assertion> assertions;
// Helper functions for reading object files // Helper functions for reading object files
@@ -128,10 +128,10 @@ static int64_t readlong(FILE *file)
* @param i The ID of the node in the array * @param i The ID of the node in the array
* @param fileName The filename to report in errors * @param fileName The filename to report in errors
*/ */
static void readFileStackNode(FILE *file, std::vector<struct FileStackNode> &fileNodes, uint32_t i, static void readFileStackNode(FILE *file, std::vector<FileStackNode> &fileNodes, uint32_t i,
char const *fileName) char const *fileName)
{ {
struct FileStackNode &node = fileNodes[i]; FileStackNode &node = fileNodes[i];
uint32_t parentID; uint32_t parentID;
tryReadlong(parentID, file, tryReadlong(parentID, file,
@@ -167,11 +167,11 @@ static void readFileStackNode(FILE *file, std::vector<struct FileStackNode> &fil
/* /*
* Reads a symbol from a file. * Reads a symbol from a file.
* @param file The file to read from * @param file The file to read from
* @param symbol The struct to fill * @param symbol The symbol to fill
* @param fileName The filename to report in errors * @param fileName The filename to report in errors
*/ */
static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName, static void readSymbol(FILE *file, Symbol *symbol, char const *fileName,
std::vector<struct FileStackNode> const &fileNodes) std::vector<FileStackNode> const &fileNodes)
{ {
tryReadstring(symbol->name, file, "%s: Cannot read symbol name: %s", fileName); tryReadstring(symbol->name, file, "%s: Cannot read symbol name: %s", fileName);
tryGetc(enum ExportLevel, symbol->type, file, "%s: Cannot read \"%s\"'s type: %s", tryGetc(enum ExportLevel, symbol->type, file, "%s: Cannot read \"%s\"'s type: %s",
@@ -198,12 +198,12 @@ static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName,
/* /*
* Reads a patch from a file. * Reads a patch from a file.
* @param file The file to read from * @param file The file to read from
* @param patch The struct to fill * @param patch The patch to fill
* @param fileName The filename to report in errors * @param fileName The filename to report in errors
* @param i The number of the patch to report in errors * @param i The number of the patch to report in errors
*/ */
static void readPatch(FILE *file, struct Patch *patch, char const *fileName, std::string const &sectName, static void readPatch(FILE *file, Patch *patch, char const *fileName, std::string const &sectName,
uint32_t i, std::vector<struct FileStackNode> const &fileNodes) uint32_t i, std::vector<FileStackNode> const &fileNodes)
{ {
uint32_t nodeID, rpnSize; uint32_t nodeID, rpnSize;
enum PatchType type; enum PatchType type;
@@ -243,9 +243,9 @@ static void readPatch(FILE *file, struct Patch *patch, char const *fileName, std
/* /*
* Sets a patch's pcSection from its pcSectionID. * Sets a patch's pcSection from its pcSectionID.
* @param patch The struct to fix * @param patch The patch to fix
*/ */
static void linkPatchToPCSect(struct Patch *patch, std::vector<struct Section *> const &fileSections) static void linkPatchToPCSect(Patch *patch, std::vector<Section *> const &fileSections)
{ {
patch->pcSection = patch->pcSectionID != (uint32_t)-1 ? fileSections[patch->pcSectionID] patch->pcSection = patch->pcSectionID != (uint32_t)-1 ? fileSections[patch->pcSectionID]
: NULL; : NULL;
@@ -254,11 +254,11 @@ static void linkPatchToPCSect(struct Patch *patch, std::vector<struct Section *>
/* /*
* Reads a section from a file. * Reads a section from a file.
* @param file The file to read from * @param file The file to read from
* @param section The struct to fill * @param section The section to fill
* @param fileName The filename to report in errors * @param fileName The filename to report in errors
*/ */
static void readSection(FILE *file, struct Section *section, char const *fileName, static void readSection(FILE *file, Section *section, char const *fileName,
std::vector<struct FileStackNode> const &fileNodes) std::vector<FileStackNode> const &fileNodes)
{ {
int32_t tmp; int32_t tmp;
uint8_t byte; uint8_t byte;
@@ -330,7 +330,7 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam
* @param symbol The symbol to link * @param symbol The symbol to link
* @param section The section to link * @param section The section to link
*/ */
static void linkSymToSect(struct Symbol &symbol, struct Section *section) static void linkSymToSect(Symbol &symbol, Section *section)
{ {
uint32_t a = 0, b = section->symbols.size(); uint32_t a = 0, b = section->symbols.size();
@@ -349,11 +349,11 @@ static void linkSymToSect(struct Symbol &symbol, struct Section *section)
/* /*
* Reads an assertion from a file * Reads an assertion from a file
* @param file The file to read from * @param file The file to read from
* @param assert The struct to fill * @param assert The assertion to fill
* @param fileName The filename to report in errors * @param fileName The filename to report in errors
*/ */
static void readAssertion(FILE *file, struct Assertion *assert, char const *fileName, uint32_t i, static void readAssertion(FILE *file, Assertion *assert, char const *fileName, uint32_t i,
std::vector<struct FileStackNode> const &fileNodes) std::vector<FileStackNode> const &fileNodes)
{ {
char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX
@@ -363,7 +363,7 @@ static void readAssertion(FILE *file, struct Assertion *assert, char const *file
tryReadstring(assert->message, file, "%s: Cannot read assertion's message: %s", fileName); tryReadstring(assert->message, file, "%s: Cannot read assertion's message: %s", fileName);
} }
static struct Section *getMainSection(struct Section *section) static Section *getMainSection(Section *section)
{ {
if (section->modifier != SECTION_NORMAL) if (section->modifier != SECTION_NORMAL)
section = sect_GetSection(section->name); section = sect_GetSection(section->name);
@@ -406,7 +406,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
.data = fileName .data = fileName
}); });
std::vector<struct Symbol> &fileSymbols = symbolLists.emplace_front(); std::vector<Symbol> &fileSymbols = symbolLists.emplace_front();
sdobj_ReadFile(&nodes[fileID].back(), file, fileSymbols); sdobj_ReadFile(&nodes[fileID].back(), file, fileSymbols);
return; return;
@@ -446,13 +446,13 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
readFileStackNode(file, nodes[fileID], i, fileName); readFileStackNode(file, nodes[fileID], i, fileName);
// This file's symbols, kept to link sections to them // This file's symbols, kept to link sections to them
std::vector<struct Symbol> &fileSymbols = symbolLists.emplace_front(nbSymbols); std::vector<Symbol> &fileSymbols = symbolLists.emplace_front(nbSymbols);
std::vector<uint32_t> nbSymPerSect(nbSections, 0); std::vector<uint32_t> nbSymPerSect(nbSections, 0);
verbosePrint("Reading %" PRIu32 " symbols...\n", nbSymbols); verbosePrint("Reading %" PRIu32 " symbols...\n", nbSymbols);
for (uint32_t i = 0; i < nbSymbols; i++) { for (uint32_t i = 0; i < nbSymbols; i++) {
// Read symbol // Read symbol
struct Symbol &symbol = fileSymbols[i]; Symbol &symbol = fileSymbols[i];
readSymbol(file, &symbol, fileName, nodes[fileID]); readSymbol(file, &symbol, fileName, nodes[fileID]);
@@ -463,12 +463,12 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
} }
// This file's sections, stored in a table to link symbols to them // This file's sections, stored in a table to link symbols to them
std::vector<struct Section *> fileSections(nbSections, NULL); std::vector<Section *> fileSections(nbSections, NULL);
verbosePrint("Reading %" PRIu32 " sections...\n", nbSections); verbosePrint("Reading %" PRIu32 " sections...\n", nbSections);
for (uint32_t i = 0; i < nbSections; i++) { for (uint32_t i = 0; i < nbSections; i++) {
// Read section // Read section
fileSections[i] = new(std::nothrow) struct Section(); fileSections[i] = new(std::nothrow) Section();
if (!fileSections[i]) if (!fileSections[i])
err("%s: Failed to create new section", fileName); err("%s: Failed to create new section", fileName);
@@ -483,7 +483,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
// Give patches' PC section pointers to their sections // Give patches' PC section pointers to their sections
for (uint32_t i = 0; i < nbSections; i++) { for (uint32_t i = 0; i < nbSections; i++) {
if (sect_HasData(fileSections[i]->type)) { if (sect_HasData(fileSections[i]->type)) {
for (struct Patch &patch : fileSections[i]->patches) for (Patch &patch : fileSections[i]->patches)
linkPatchToPCSect(&patch, fileSections); linkPatchToPCSect(&patch, fileSections);
} }
} }
@@ -495,7 +495,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
if (sectionID == -1) { if (sectionID == -1) {
fileSymbols[i].section = NULL; fileSymbols[i].section = NULL;
} else { } else {
struct Section *section = fileSections[sectionID]; Section *section = fileSections[sectionID];
// Give the section a pointer to the symbol as well // Give the section a pointer to the symbol as well
linkSymToSect(fileSymbols[i], section); linkSymToSect(fileSymbols[i], section);
@@ -515,7 +515,7 @@ 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 = assertions.emplace_front(); Assertion &assertion = assertions.emplace_front();
readAssertion(file, &assertion, fileName, i, nodes[fileID]); readAssertion(file, &assertion, fileName, i, nodes[fileID]);
linkPatchToPCSect(&assertion.patch, fileSections); linkPatchToPCSect(&assertion.patch, fileSections);
@@ -540,9 +540,9 @@ void obj_Setup(unsigned int nbFiles)
nodes.resize(nbFiles); nodes.resize(nbFiles);
} }
static void freeSection(struct Section *section) static void freeSection(Section *section)
{ {
for (struct Section *next; section; section = next) { for (Section *next; section; section = next) {
next = section->nextu; next = section->nextu;
delete section; delete section;
}; };

View File

@@ -30,16 +30,16 @@ FILE *symFile;
FILE *mapFile; FILE *mapFile;
struct SortedSymbol { struct SortedSymbol {
struct Symbol const *sym; Symbol const *sym;
uint16_t addr; uint16_t addr;
}; };
struct SortedSections { struct SortedSections {
std::deque<struct Section const *> sections; std::deque<Section const *> sections;
std::deque<struct Section const *> zeroLenSections; std::deque<Section const *> zeroLenSections;
}; };
static std::deque<struct SortedSections> sections[SECTTYPE_INVALID]; static std::deque<SortedSections> sections[SECTTYPE_INVALID];
// Defines the order in which types are output to the sym and map files // Defines the order in which types are output to the sym and map files
static enum SectionType typeMap[SECTTYPE_INVALID] = { static enum SectionType typeMap[SECTTYPE_INVALID] = {
@@ -53,7 +53,7 @@ static enum SectionType typeMap[SECTTYPE_INVALID] = {
SECTTYPE_HRAM SECTTYPE_HRAM
}; };
void out_AddSection(struct Section const *section) void out_AddSection(Section const *section)
{ {
static const uint32_t maxNbBanks[SECTTYPE_INVALID] = { static const uint32_t maxNbBanks[SECTTYPE_INVALID] = {
1, // SECTTYPE_WRAM0 1, // SECTTYPE_WRAM0
@@ -77,7 +77,7 @@ void out_AddSection(struct Section const *section)
for (uint32_t i = sections[section->type].size(); i < minNbBanks; i++) for (uint32_t i = sections[section->type].size(); i < minNbBanks; i++)
sections[section->type].emplace_back(); sections[section->type].emplace_back();
std::deque<struct Section const *> *ptr = section->size std::deque<Section const *> *ptr = section->size
? &sections[section->type][targetBank].sections ? &sections[section->type][targetBank].sections
: &sections[section->type][targetBank].zeroLenSections; : &sections[section->type][targetBank].zeroLenSections;
auto pos = ptr->begin(); auto pos = ptr->begin();
@@ -88,11 +88,11 @@ void out_AddSection(struct Section const *section)
ptr->insert(pos, section); ptr->insert(pos, section);
} }
struct Section const *out_OverlappingSection(struct Section const *section) Section const *out_OverlappingSection(Section const *section)
{ {
uint32_t bank = section->bank - sectionTypeInfo[section->type].firstBank; uint32_t bank = section->bank - sectionTypeInfo[section->type].firstBank;
for (struct Section const *ptr : sections[section->type][bank].sections) { for (Section const *ptr : sections[section->type][bank].sections) {
if (ptr->org < section->org + section->size && section->org < ptr->org + ptr->size) if (ptr->org < section->org + section->size && section->org < ptr->org + ptr->size)
return ptr; return ptr;
} }
@@ -159,13 +159,12 @@ static void coverOverlayBanks(uint32_t nbOverlayBanks)
* @param baseOffset The address of the bank's first byte in GB address space * @param baseOffset The address of the bank's first byte in GB address space
* @param size The size of the bank * @param size The size of the bank
*/ */
static void writeBank(std::deque<struct Section const *> *bankSections, uint16_t baseOffset, static void writeBank(std::deque<Section const *> *bankSections, uint16_t baseOffset, uint16_t size)
uint16_t size)
{ {
uint16_t offset = 0; uint16_t offset = 0;
if (bankSections) { if (bankSections) {
for (struct Section const *section : *bankSections) { for (Section const *section : *bankSections) {
assert(section->offset == 0); assert(section->offset == 0);
// Output padding up to the next SECTION // Output padding up to the next SECTION
while (offset + baseOffset < section->org) { while (offset + baseOffset < section->org) {
@@ -288,7 +287,7 @@ static void printSymName(char const *name)
// Comparator function for `std::stable_sort` to sort symbols // Comparator function for `std::stable_sort` to sort symbols
// Symbols are ordered by address, then by parentage // Symbols are ordered by address, then by parentage
static int compareSymbols(struct SortedSymbol const &sym1, struct SortedSymbol const &sym2) static int compareSymbols(SortedSymbol const &sym1, SortedSymbol const &sym2)
{ {
if (sym1.addr != sym2.addr) if (sym1.addr != sym2.addr)
return sym1.addr < sym2.addr ? -1 : 1; return sym1.addr < sym2.addr ? -1 : 1;
@@ -318,16 +317,15 @@ static int compareSymbols(struct SortedSymbol const &sym1, struct SortedSymbol c
* Write a bank's contents to the sym file * Write a bank's contents to the sym file
* @param bankSections The bank's sections * @param bankSections The bank's sections
*/ */
static void writeSymBank(struct SortedSections const &bankSections, static void writeSymBank(SortedSections const &bankSections, enum SectionType type, uint32_t bank)
enum SectionType type, uint32_t bank)
{ {
#define forEachSortedSection(sect, ...) do { \ #define forEachSortedSection(sect, ...) do { \
for (auto it = bankSections.zeroLenSections.begin(); it != bankSections.zeroLenSections.end(); it++) { \ for (auto it = bankSections.zeroLenSections.begin(); it != bankSections.zeroLenSections.end(); it++) { \
for (struct Section const *sect = *it; sect; sect = sect->nextu) \ for (Section const *sect = *it; sect; sect = sect->nextu) \
__VA_ARGS__ \ __VA_ARGS__ \
} \ } \
for (auto it = bankSections.sections.begin(); it != bankSections.sections.end(); it++) { \ for (auto it = bankSections.sections.begin(); it != bankSections.sections.end(); it++) { \
for (struct Section const *sect = *it; sect; sect = sect->nextu) \ for (Section const *sect = *it; sect; sect = sect->nextu) \
__VA_ARGS__ \ __VA_ARGS__ \
} \ } \
} while (0) } while (0)
@@ -341,12 +339,12 @@ static void writeSymBank(struct SortedSections const &bankSections,
if (!nbSymbols) if (!nbSymbols)
return; return;
std::vector<struct SortedSymbol> symList; std::vector<SortedSymbol> symList;
symList.reserve(nbSymbols); symList.reserve(nbSymbols);
forEachSortedSection(sect, { forEachSortedSection(sect, {
for (struct Symbol const *sym : sect->symbols) { for (Symbol const *sym : sect->symbols) {
// Don't output symbols that begin with an illegal character // Don't output symbols that begin with an illegal character
if (!sym->name.empty() && canStartSymName(sym->name[0])) if (!sym->name.empty() && canStartSymName(sym->name[0]))
symList.push_back({ .sym = sym, .addr = (uint16_t)(sym->offset + sect->org) }); symList.push_back({ .sym = sym, .addr = (uint16_t)(sym->offset + sect->org) });
@@ -359,7 +357,7 @@ static void writeSymBank(struct SortedSections const &bankSections,
uint32_t symBank = bank + sectionTypeInfo[type].firstBank; uint32_t symBank = bank + sectionTypeInfo[type].firstBank;
for (struct SortedSymbol &sym : symList) { for (SortedSymbol &sym : symList) {
fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym.addr); fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym.addr);
printSymName(sym.sym->name.c_str()); printSymName(sym.sym->name.c_str());
putc('\n', symFile); putc('\n', symFile);
@@ -379,8 +377,7 @@ static void writeEmptySpace(uint16_t begin, uint16_t end)
/* /*
* Write a bank's contents to the map file * Write a bank's contents to the map file
*/ */
static void writeMapBank(struct SortedSections const &sectList, enum SectionType type, static void writeMapBank(SortedSections const &sectList, enum SectionType type, uint32_t bank)
uint32_t bank)
{ {
fprintf(mapFile, "\n%s bank #%" PRIu32 ":\n", sectionTypeInfo[type].name.c_str(), fprintf(mapFile, "\n%s bank #%" PRIu32 ":\n", sectionTypeInfo[type].name.c_str(),
bank + sectionTypeInfo[type].firstBank); bank + sectionTypeInfo[type].firstBank);
@@ -395,7 +392,7 @@ static void writeMapBank(struct SortedSections const &sectList, enum SectionType
auto &pickedSection = section == sectList.sections.end() ? zeroLenSection auto &pickedSection = section == sectList.sections.end() ? zeroLenSection
: zeroLenSection == sectList.zeroLenSections.end() ? section : zeroLenSection == sectList.zeroLenSections.end() ? section
: (*section)->org < (*zeroLenSection)->org ? section : zeroLenSection; : (*section)->org < (*zeroLenSection)->org ? section : zeroLenSection;
struct Section const *sect = *pickedSection; Section const *sect = *pickedSection;
used += sect->size; used += sect->size;
assert(sect->offset == 0); assert(sect->offset == 0);
@@ -416,7 +413,7 @@ static void writeMapBank(struct SortedSections const &sectList, enum SectionType
if (!noSymInMap) { if (!noSymInMap) {
// Also print symbols in the following "pieces" // Also print symbols in the following "pieces"
for (uint16_t org = sect->org; sect; sect = sect->nextu) { for (uint16_t org = sect->org; sect; sect = sect->nextu) {
for (struct Symbol *sym : sect->symbols) for (Symbol *sym : sect->symbols)
// Space matches "\tSECTION: $xxxx ..." // Space matches "\tSECTION: $xxxx ..."
fprintf(mapFile, "\t $%04" PRIx32 " = %s\n", fprintf(mapFile, "\t $%04" PRIx32 " = %s\n",
sym->offset + org, sym->name.c_str()); sym->offset + org, sym->name.c_str());

View File

@@ -22,7 +22,7 @@ struct RPNStackEntry {
bool errorFlag; // Whether the value is a placeholder inserted for error recovery bool errorFlag; // Whether the value is a placeholder inserted for error recovery
}; };
std::deque<struct RPNStackEntry> rpnStack; std::deque<RPNStackEntry> rpnStack;
static void pushRPN(int32_t value, bool comesFromError) static void pushRPN(int32_t value, bool comesFromError)
{ {
@@ -33,12 +33,12 @@ static void pushRPN(int32_t value, bool comesFromError)
// has popped any values with the error flag set. // has popped any values with the error flag set.
static bool isError = false; static bool isError = false;
static int32_t popRPN(struct FileStackNode const *node, uint32_t lineNo) static int32_t popRPN(FileStackNode const *node, uint32_t lineNo)
{ {
if (rpnStack.empty()) if (rpnStack.empty())
fatal(node, lineNo, "Internal error, RPN stack empty"); fatal(node, lineNo, "Internal error, RPN stack empty");
struct RPNStackEntry entry = rpnStack.front(); RPNStackEntry entry = rpnStack.front();
rpnStack.pop_front(); rpnStack.pop_front();
isError |= entry.errorFlag; isError |= entry.errorFlag;
@@ -48,7 +48,7 @@ static int32_t popRPN(struct FileStackNode const *node, uint32_t lineNo)
// RPN operators // RPN operators
static uint32_t getRPNByte(uint8_t const **expression, int32_t *size, static uint32_t getRPNByte(uint8_t const **expression, int32_t *size,
struct FileStackNode const *node, uint32_t lineNo) FileStackNode const *node, uint32_t lineNo)
{ {
if (!(*size)--) if (!(*size)--)
fatal(node, lineNo, "Internal error, RPN expression overread"); fatal(node, lineNo, "Internal error, RPN expression overread");
@@ -56,10 +56,10 @@ static uint32_t getRPNByte(uint8_t const **expression, int32_t *size,
return *(*expression)++; return *(*expression)++;
} }
static struct Symbol const *getSymbol(std::vector<struct Symbol> const &symbolList, uint32_t index) static Symbol const *getSymbol(std::vector<Symbol> const &symbolList, uint32_t index)
{ {
assert(index != (uint32_t)-1); // PC needs to be handled specially, not here assert(index != (uint32_t)-1); // PC needs to be handled specially, not here
struct Symbol const &symbol = symbolList[index]; Symbol const &symbol = symbolList[index];
// If the symbol is defined elsewhere... // If the symbol is defined elsewhere...
if (symbol.type == SYMTYPE_IMPORT) if (symbol.type == SYMTYPE_IMPORT)
@@ -76,8 +76,7 @@ static struct Symbol const *getSymbol(std::vector<struct Symbol> const &symbolLi
* @return isError Set if an error occurred during evaluation, and further * @return isError Set if an error occurred during evaluation, and further
* errors caused by the value should be suppressed. * errors caused by the value should be suppressed.
*/ */
static int32_t computeRPNExpr(struct Patch const *patch, static int32_t computeRPNExpr(Patch const *patch, std::vector<Symbol> const &fileSymbols)
std::vector<struct Symbol> const &fileSymbols)
{ {
// Small shortcut to avoid a lot of repetition // Small shortcut to avoid a lot of repetition
#define popRPN() popRPN(patch->src, patch->lineNo) #define popRPN() popRPN(patch->src, patch->lineNo)
@@ -99,9 +98,9 @@ static int32_t computeRPNExpr(struct Patch const *patch,
// So, if there are two `popRPN` in the same expression, make // So, if there are two `popRPN` in the same expression, make
// sure the operation is commutative. // sure the operation is commutative.
switch (command) { switch (command) {
struct Symbol const *symbol; Symbol const *symbol;
char const *name; char const *name;
struct Section const *sect; Section const *sect;
case RPN_ADD: case RPN_ADD:
value = popRPN() + popRPN(); value = popRPN() + popRPN();
@@ -410,11 +409,11 @@ static int32_t computeRPNExpr(struct Patch const *patch,
#undef popRPN #undef popRPN
} }
void patch_CheckAssertions(std::deque<struct Assertion> &assertions) void patch_CheckAssertions(std::deque<Assertion> &assertions)
{ {
verbosePrint("Checking assertions...\n"); verbosePrint("Checking assertions...\n");
for (struct Assertion &assert : assertions) { for (Assertion &assert : assertions) {
int32_t value = computeRPNExpr(&assert.patch, *assert.fileSymbols); int32_t value = computeRPNExpr(&assert.patch, *assert.fileSymbols);
enum AssertionType type = (enum AssertionType)assert.patch.type; enum AssertionType type = (enum AssertionType)assert.patch.type;
@@ -448,10 +447,10 @@ void patch_CheckAssertions(std::deque<struct Assertion> &assertions)
* @param section The section component to patch * @param section The section component to patch
* @param dataSection The section to patch * @param dataSection The section to patch
*/ */
static void applyFilePatches(struct Section *section, struct Section *dataSection) static void applyFilePatches(Section *section, Section *dataSection)
{ {
verbosePrint("Patching section \"%s\"...\n", section->name.c_str()); verbosePrint("Patching section \"%s\"...\n", section->name.c_str());
for (struct Patch &patch : section->patches) { for (Patch &patch : section->patches) {
int32_t value = computeRPNExpr(&patch, *section->fileSymbols); int32_t value = computeRPNExpr(&patch, *section->fileSymbols);
uint16_t offset = patch.offset + section->offset; uint16_t offset = patch.offset + section->offset;
@@ -497,12 +496,12 @@ static void applyFilePatches(struct Section *section, struct Section *dataSectio
* Applies all of a section's patches, iterating over "components" of unionized sections * Applies all of a section's patches, iterating over "components" of unionized sections
* @param section The section to patch * @param section The section to patch
*/ */
static void applyPatches(struct Section *section) static void applyPatches(Section *section)
{ {
if (!sect_HasData(section->type)) if (!sect_HasData(section->type))
return; return;
for (struct Section *component = section; component; component = component->nextu) for (Section *component = section; component; component = component->nextu)
applyFilePatches(component, section); applyFilePatches(component, section);
} }

View File

@@ -25,7 +25,7 @@ enum NumberType {
OCT = 8, // Q OCT = 8, // Q
}; };
static void consumeLF(struct FileStackNode const *where, uint32_t lineNo, FILE *file) { static void consumeLF(FileStackNode const *where, uint32_t lineNo, FILE *file) {
if (getc(file) != '\n') if (getc(file) != '\n')
fatal(where, lineNo, "Bad line ending (CR without LF)"); fatal(where, lineNo, "Bad line ending (CR without LF)");
} }
@@ -33,7 +33,7 @@ static void consumeLF(struct FileStackNode const *where, uint32_t lineNo, FILE *
static char const *delim = " \f\n\r\t\v"; // Whitespace according to the C and POSIX locales static char const *delim = " \f\n\r\t\v"; // Whitespace according to the C and POSIX locales
static int nextLine(std::vector<char> &lineBuf, uint32_t &lineNo, static int nextLine(std::vector<char> &lineBuf, uint32_t &lineNo,
struct FileStackNode const *where, FILE *file) { FileStackNode const *where, FILE *file) {
retry: retry:
++lineNo; ++lineNo;
int firstChar = getc(file); int firstChar = getc(file);
@@ -88,7 +88,7 @@ static uint32_t readNumber(char const *restrict str, char const **endptr, enum N
} }
} }
static uint32_t parseNumber(struct FileStackNode const *where, uint32_t lineNo, char const *restrict str, enum NumberType base) { static uint32_t parseNumber(FileStackNode const *where, uint32_t lineNo, char const *restrict str, enum NumberType base) {
if (str[0] == '\0') if (str[0] == '\0')
fatal(where, lineNo, "Expected number, got empty string"); fatal(where, lineNo, "Expected number, got empty string");
@@ -100,7 +100,7 @@ static uint32_t parseNumber(struct FileStackNode const *where, uint32_t lineNo,
return res; return res;
} }
static uint8_t parseByte(struct FileStackNode const *where, uint32_t lineNo, char const *restrict str, enum NumberType base) { static uint8_t parseByte(FileStackNode const *where, uint32_t lineNo, char const *restrict str, enum NumberType base) {
uint32_t num = parseNumber(where, lineNo, str, base); uint32_t num = parseNumber(where, lineNo, str, base);
if (num > UINT8_MAX) if (num > UINT8_MAX)
@@ -133,7 +133,7 @@ enum RelocFlags {
| 1 << RELOC_EXPR24 | 1 << RELOC_BANKBYTE, | 1 << RELOC_EXPR24 | 1 << RELOC_BANKBYTE,
}; };
void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<struct Symbol> &fileSymbols) { void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector<Symbol> &fileSymbols) {
std::vector<char> line(256); std::vector<char> line(256);
char const *token; char const *token;
@@ -216,10 +216,10 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
// Now, let's parse the rest of the lines as they come! // Now, let's parse the rest of the lines as they come!
struct FileSection { struct FileSection {
struct Section *section; Section *section;
uint16_t writeIndex; uint16_t writeIndex;
}; };
std::vector<struct FileSection> fileSections; std::vector<FileSection> fileSections;
std::vector<uint8_t> data; std::vector<uint8_t> data;
for (;;) { for (;;) {
@@ -236,7 +236,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
if (fileSections.size() == expectedNbAreas) if (fileSections.size() == expectedNbAreas)
warning(where, lineNo, "Got more 'A' lines than the expected %" PRIu32, warning(where, lineNo, "Got more 'A' lines than the expected %" PRIu32,
expectedNbAreas); expectedNbAreas);
struct Section *curSection = new(std::nothrow) struct Section(); Section *curSection = new(std::nothrow) Section();
if (!curSection) if (!curSection)
fatal(where, lineNo, "Failed to alloc new area: %s", strerror(errno)); fatal(where, lineNo, "Failed to alloc new area: %s", strerror(errno));
@@ -244,7 +244,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
getToken(line.data(), "'A' line is too short"); getToken(line.data(), "'A' line is too short");
assert(strlen(token) != 0); // This should be impossible, tokens are non-empty assert(strlen(token) != 0); // This should be impossible, tokens are non-empty
// The following is required for fragment offsets to be reliably predicted // The following is required for fragment offsets to be reliably predicted
for (struct FileSection &entry : fileSections) { for (FileSection &entry : fileSections) {
if (!strcmp(token, entry.section->name.c_str())) if (!strcmp(token, entry.section->name.c_str()))
fatal(where, lineNo, "Area \"%s\" already defined earlier", fatal(where, lineNo, "Area \"%s\" already defined earlier",
token); token);
@@ -327,7 +327,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
if (fileSymbols.size() == expectedNbSymbols) if (fileSymbols.size() == expectedNbSymbols)
warning(where, lineNo, "Got more 'S' lines than the expected %" PRIu32, warning(where, lineNo, "Got more 'S' lines than the expected %" PRIu32,
expectedNbSymbols); expectedNbSymbols);
struct Symbol &symbol = fileSymbols.emplace_back(); Symbol &symbol = fileSymbols.emplace_back();
// Init other members // Init other members
symbol.objFileName = where->name().c_str(); symbol.objFileName = where->name().c_str();
@@ -358,7 +358,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
} else { } else {
// All symbols are exported // All symbols are exported
symbol.type = SYMTYPE_EXPORT; symbol.type = SYMTYPE_EXPORT;
struct Symbol const *other = sym_GetSymbol(symbol.name); Symbol const *other = sym_GetSymbol(symbol.name);
if (other) { if (other) {
// The same symbol can only be defined twice if neither // The same symbol can only be defined twice if neither
@@ -422,7 +422,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
fatal(where, lineNo, "'R' line references area #%" PRIu16 ", but there are only %zu (so far)", fatal(where, lineNo, "'R' line references area #%" PRIu16 ", but there are only %zu (so far)",
areaIdx, fileSections.size()); areaIdx, fileSections.size());
assert(!fileSections.empty()); // There should be at least one, from the above check assert(!fileSections.empty()); // There should be at least one, from the above check
struct Section *section = fileSections[areaIdx].section; Section *section = fileSections[areaIdx].section;
uint16_t *writeIndex = &fileSections[areaIdx].writeIndex; uint16_t *writeIndex = &fileSections[areaIdx].writeIndex;
uint8_t writtenOfs = ADDR_SIZE; // Bytes before this have been written to `->data` uint8_t writtenOfs = ADDR_SIZE; // Bytes before this have been written to `->data`
uint16_t addr = data[0] | data[1] << 8; uint16_t addr = data[0] | data[1] << 8;
@@ -489,7 +489,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
warning(where, lineNo, "Unknown reloc flags 0x%x", flags & ~RELOC_ALL_FLAGS); warning(where, lineNo, "Unknown reloc flags 0x%x", flags & ~RELOC_ALL_FLAGS);
// Turn this into a Patch // Turn this into a Patch
struct Patch &patch = section->patches.emplace_back(); Patch &patch = section->patches.emplace_back();
patch.lineNo = lineNo; patch.lineNo = lineNo;
patch.src = where; patch.src = where;
@@ -520,7 +520,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
if (idx >= fileSymbols.size()) if (idx >= fileSymbols.size())
fatal(where, lineNo, "Reloc refers to symbol #%" PRIu16 " out of %zu", fatal(where, lineNo, "Reloc refers to symbol #%" PRIu16 " out of %zu",
idx, fileSymbols.size()); idx, fileSymbols.size());
struct Symbol const &sym = fileSymbols[idx]; Symbol const &sym = fileSymbols[idx];
// SDCC has a bunch of "magic symbols" that start with a // SDCC has a bunch of "magic symbols" that start with a
// letter and an underscore. These are not compatibility // letter and an underscore. These are not compatibility
@@ -571,7 +571,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
if (fileSections[idx].section->isAddressFixed) if (fileSections[idx].section->isAddressFixed)
baseValue -= fileSections[idx].section->org; baseValue -= fileSections[idx].section->org;
std::string const &name = fileSections[idx].section->name; std::string const &name = fileSections[idx].section->name;
struct Section const *other = sect_GetSection(name); Section const *other = sect_GetSection(name);
// Unlike with `s_<AREA>`, referencing an area in this way // Unlike with `s_<AREA>`, referencing an area in this way
// wants the beginning of this fragment, so we must add the // wants the beginning of this fragment, so we must add the
@@ -678,8 +678,8 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
nbSectionsToAssign += fileSections.size(); nbSectionsToAssign += fileSections.size();
for (struct FileSection &entry : fileSections) { for (FileSection &entry : fileSections) {
struct Section *section = entry.section; Section *section = entry.section;
// RAM sections can have a size, but don't get any data (they shouldn't have any) // RAM sections can have a size, but don't get any data (they shouldn't have any)
if (entry.writeIndex != section->size && entry.writeIndex != 0) if (entry.writeIndex != section->size && entry.writeIndex != 0)
@@ -690,7 +690,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
if (section->modifier == SECTION_FRAGMENT) { if (section->modifier == SECTION_FRAGMENT) {
// Add the fragment's offset to all of its symbols // Add the fragment's offset to all of its symbols
for (struct Symbol *symbol : section->symbols) for (Symbol *symbol : section->symbols)
symbol->offset += section->offset; symbol->offset += section->offset;
} }
} }

View File

@@ -13,15 +13,15 @@
#include "error.hpp" #include "error.hpp"
#include "linkdefs.hpp" #include "linkdefs.hpp"
std::map<std::string, struct Section *> sections; std::map<std::string, Section *> sections;
void sect_ForEach(void (*callback)(struct Section *)) void sect_ForEach(void (*callback)(Section *))
{ {
for (auto &it : sections) for (auto &it : sections)
callback(it.second); callback(it.second);
} }
static void checkSectUnionCompat(struct Section *target, struct Section *other) static void checkSectUnionCompat(Section *target, Section *other)
{ {
if (other->isAddressFixed) { if (other->isAddressFixed) {
if (target->isAddressFixed) { if (target->isAddressFixed) {
@@ -59,7 +59,7 @@ static void checkSectUnionCompat(struct Section *target, struct Section *other)
} }
} }
static void checkFragmentCompat(struct Section *target, struct Section *other) static void checkFragmentCompat(Section *target, Section *other)
{ {
if (other->isAddressFixed) { if (other->isAddressFixed) {
uint16_t org = other->org - target->size; uint16_t org = other->org - target->size;
@@ -107,7 +107,7 @@ static void checkFragmentCompat(struct Section *target, struct Section *other)
} }
} }
static void mergeSections(struct Section *target, struct Section *other, enum SectionModifier mod) static void mergeSections(Section *target, Section *other, enum SectionModifier mod)
{ {
// Common checks // Common checks
@@ -144,7 +144,7 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se
if (!other->data.empty()) { if (!other->data.empty()) {
target->data.insert(target->data.end(), RANGE(other->data)); target->data.insert(target->data.end(), RANGE(other->data));
// Adjust patches' PC offsets // Adjust patches' PC offsets
for (struct Patch &patch : other->patches) for (Patch &patch : other->patches)
patch.pcOffset += other->offset; patch.pcOffset += other->offset;
} else if (!target->data.empty()) { } else if (!target->data.empty()) {
assert(other->size == 0); assert(other->size == 0);
@@ -159,10 +159,10 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se
target->nextu = other; target->nextu = other;
} }
void sect_AddSection(struct Section *section) void sect_AddSection(Section *section)
{ {
// Check if the section already exists // Check if the section already exists
if (struct Section *other = sect_GetSection(section->name); other) { if (Section *other = sect_GetSection(section->name); other) {
if (section->modifier != other->modifier) if (section->modifier != other->modifier)
errx("Section \"%s\" defined as %s and %s", section->name.c_str(), errx("Section \"%s\" defined as %s and %s", section->name.c_str(),
sectionModNames[section->modifier], sectionModNames[other->modifier]); sectionModNames[section->modifier], sectionModNames[other->modifier]);
@@ -179,13 +179,13 @@ void sect_AddSection(struct Section *section)
} }
} }
struct Section *sect_GetSection(std::string const &name) Section *sect_GetSection(std::string const &name)
{ {
auto search = sections.find(name); auto search = sections.find(name);
return search != sections.end() ? search->second : NULL; return search != sections.end() ? search->second : NULL;
} }
static void doSanityChecks(struct Section *section) static void doSanityChecks(Section *section)
{ {
// Sanity check the section's type // Sanity check the section's type
if (section->type < 0 || section->type >= SECTTYPE_INVALID) { if (section->type < 0 || section->type >= SECTTYPE_INVALID) {

View File

@@ -11,12 +11,12 @@
#include "error.hpp" #include "error.hpp"
std::map<std::string, struct Symbol *> symbols; std::map<std::string, Symbol *> symbols;
void sym_AddSymbol(struct Symbol *symbol) void sym_AddSymbol(Symbol *symbol)
{ {
// Check if the symbol already exists // Check if the symbol already exists
if (struct Symbol *other = sym_GetSymbol(symbol->name); other) { if (Symbol *other = sym_GetSymbol(symbol->name); other) {
fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name.c_str(), symbol->objFileName); fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name.c_str(), symbol->objFileName);
dumpFileStack(symbol->src); dumpFileStack(symbol->src);
fprintf(stderr, "(%" PRIu32 ") and in %s from ", symbol->lineNo, other->objFileName); fprintf(stderr, "(%" PRIu32 ") and in %s from ", symbol->lineNo, other->objFileName);
@@ -29,7 +29,7 @@ void sym_AddSymbol(struct Symbol *symbol)
symbols[symbol->name] = symbol; symbols[symbol->name] = symbol;
} }
struct Symbol *sym_GetSymbol(std::string const &name) Symbol *sym_GetSymbol(std::string const &name)
{ {
auto search = symbols.find(name); auto search = symbols.find(name);
return search != symbols.end() ? search->second : NULL; return search != symbols.end() ? search->second : NULL;

View File

@@ -7,7 +7,7 @@ using namespace std::literals;
// The default values are the most lax, as they are used as-is by RGBASM; only RGBLINK has the full info, // The default values are the most lax, as they are used as-is by RGBASM; only RGBLINK has the full info,
// so RGBASM's job is only to catch unconditional errors earlier. // so RGBASM's job is only to catch unconditional errors earlier.
struct SectionTypeInfo sectionTypeInfo[SECTTYPE_INVALID] = { SectionTypeInfo sectionTypeInfo[SECTTYPE_INVALID] = {
{ // SECTTYPE_WRAM0 { // SECTTYPE_WRAM0
.name = "WRAM0"s, .name = "WRAM0"s,
.startAddr = 0xC000, .startAddr = 0xC000,

View File

@@ -56,7 +56,7 @@ static unsigned long long getRandomBits(unsigned count) {
return result; return result;
} }
static void generate_tile_attributes(struct Attributes * restrict attributes) { static void generate_tile_attributes(Attributes * restrict attributes) {
/* /*
* Images have ten colors, grouped into two groups of 5 colors. The palette index indicates two * Images have ten colors, grouped into two groups of 5 colors. The palette index indicates two
* things: which one of those groups will be used, and which colors out of those 5 will be used * things: which one of those groups will be used, and which colors out of those 5 will be used
@@ -162,8 +162,8 @@ static uint8_t _5to8(uint8_t five) {
// Can't mark as `const`, as the array type is otherwise not compatible (augh) // Can't mark as `const`, as the array type is otherwise not compatible (augh)
static void write_image(char const *filename, uint16_t /* const */ palettes[MIN_NB_ELMS(60)][4], static void write_image(char const *filename, uint16_t /* const */ palettes[MIN_NB_ELMS(60)][4],
unsigned char /* const */ (*tileData)[8][8], unsigned char /* const */ (*tileData)[8][8], Attributes const *attributes,
struct Attributes const *attributes, uint8_t width, uint8_t height) { uint8_t width, uint8_t height) {
uint8_t const nbTiles = width * height; uint8_t const nbTiles = width * height;
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop pngInfo = png_create_info_struct(png); png_infop pngInfo = png_create_info_struct(png);
@@ -224,7 +224,7 @@ static void write_image(char const *filename, uint16_t /* const */ palettes[MIN_
static void generate_random_image(char const *filename) { static void generate_random_image(char const *filename) {
#define MIN_TILES_PER_SIDE 3 #define MIN_TILES_PER_SIDE 3
#define MAX_TILES ((MIN_TILES_PER_SIDE + 7) * (MIN_TILES_PER_SIDE + 7)) #define MAX_TILES ((MIN_TILES_PER_SIDE + 7) * (MIN_TILES_PER_SIDE + 7))
struct Attributes attributes[MAX_TILES]; Attributes attributes[MAX_TILES];
unsigned char tileData[MAX_TILES][8][8]; unsigned char tileData[MAX_TILES][8][8];
uint8_t width = getRandomBits(3) + MIN_TILES_PER_SIDE, uint8_t width = getRandomBits(3) + MIN_TILES_PER_SIDE,
height = getRandomBits(3) + MIN_TILES_PER_SIDE; height = getRandomBits(3) + MIN_TILES_PER_SIDE;