mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Implement infrastructure around new lexer
The lexer itself is very much incomplete, but this is intended to be a safe point to revert to should further implementation go south.
This commit is contained in:
3
Makefile
3
Makefile
@@ -56,7 +56,6 @@ rgbasm_obj := \
|
||||
src/asm/asmy.o \
|
||||
src/asm/charmap.o \
|
||||
src/asm/fstack.o \
|
||||
src/asm/globlex.o \
|
||||
src/asm/lexer.o \
|
||||
src/asm/macro.o \
|
||||
src/asm/main.o \
|
||||
@@ -73,7 +72,7 @@ rgbasm_obj := \
|
||||
src/hashmap.o \
|
||||
src/linkdefs.o
|
||||
|
||||
src/asm/globlex.o src/asm/lexer.o src/asm/constexpr.o: src/asm/asmy.h
|
||||
src/asm/lexer.o: src/asm/asmy.h
|
||||
|
||||
rgblink_obj := \
|
||||
src/link/assign.o \
|
||||
|
||||
@@ -24,11 +24,8 @@
|
||||
#define MAXMACROARGS 99999
|
||||
#define MAXINCPATHS 128
|
||||
|
||||
extern int32_t nLineNo;
|
||||
extern uint32_t nTotalLines;
|
||||
extern uint32_t nIFDepth;
|
||||
extern bool skipElif;
|
||||
extern char tzCurrentFileName[_MAX_PATH + 1];
|
||||
extern struct Section *pCurrentSection;
|
||||
extern bool oDontExpandStrings;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
struct MacroArgs;
|
||||
|
||||
struct sContext {
|
||||
YY_BUFFER_STATE FlexHandle;
|
||||
struct LexerState *lexerState;
|
||||
struct Symbol const *pMacro;
|
||||
struct sContext *next;
|
||||
char tzFileName[_MAX_PATH + 1];
|
||||
@@ -32,7 +32,6 @@ struct sContext {
|
||||
uint32_t uniqueID;
|
||||
int32_t nLine;
|
||||
uint32_t nStatus;
|
||||
FILE *pFile;
|
||||
char *pREPTBlock;
|
||||
uint32_t nREPTBlockCount;
|
||||
uint32_t nREPTBlockSize;
|
||||
@@ -46,11 +45,17 @@ void fstk_RunInclude(char *tzFileName);
|
||||
void fstk_Init(char *s);
|
||||
void fstk_Dump(void);
|
||||
void fstk_DumpToStr(char *buf, size_t len);
|
||||
void fstk_DumpStringExpansions(void);
|
||||
void fstk_AddIncludePath(char *s);
|
||||
void fstk_RunMacro(char *s, struct MacroArgs *args);
|
||||
void fstk_RunRept(uint32_t count, int32_t nReptLineNo);
|
||||
FILE *fstk_FindFile(char const *fname, char **incPathUsed);
|
||||
/**
|
||||
* @param path The user-provided file name
|
||||
* @param fullPath The address of a pointer, which will be made to point at the full path
|
||||
* The pointer's value must be a valid argument to `realloc`, including NULL
|
||||
* @param size Current size of the buffer, or 0 if the pointer is NULL
|
||||
* @return True if the file was found, false if no path worked
|
||||
*/
|
||||
bool fstk_FindFile(char const *path, char **fullPath, size_t *size);
|
||||
int32_t fstk_GetLine(void);
|
||||
|
||||
#endif /* RGBDS_ASM_FSTACK_H */
|
||||
|
||||
@@ -9,78 +9,44 @@
|
||||
#ifndef RGBDS_ASM_LEXER_H
|
||||
#define RGBDS_ASM_LEXER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define LEXHASHSIZE (1 << 11)
|
||||
#define MAXSTRLEN 255
|
||||
|
||||
struct sLexInitString {
|
||||
char *tzName;
|
||||
uint32_t nToken;
|
||||
struct LexerState;
|
||||
extern struct LexerState *lexerState;
|
||||
extern struct LexerState *lexerStateEOL;
|
||||
|
||||
static inline struct LexerState *lexer_GetState(void)
|
||||
{
|
||||
return lexerState;
|
||||
}
|
||||
|
||||
static inline void lexer_SetState(struct LexerState *state)
|
||||
{
|
||||
lexerState = state;
|
||||
}
|
||||
|
||||
static inline void lexer_SetStateAtEOL(struct LexerState *state)
|
||||
{
|
||||
lexerStateEOL = state;
|
||||
}
|
||||
|
||||
struct LexerState *lexer_OpenFile(char const *path);
|
||||
struct LexerState *lexer_OpenFileView(void);
|
||||
void lexer_DeleteState(struct LexerState *state);
|
||||
|
||||
enum LexerMode {
|
||||
LEXER_NORMAL,
|
||||
LEXER_RAW
|
||||
};
|
||||
|
||||
struct sLexFloat {
|
||||
uint32_t (*Callback)(char *s, uint32_t size);
|
||||
uint32_t nToken;
|
||||
};
|
||||
void lexer_SetMode(enum LexerMode mode);
|
||||
void lexer_ToggleStringExpansion(bool enable);
|
||||
|
||||
struct yy_buffer_state {
|
||||
/* Actual starting address */
|
||||
char *pBufferRealStart;
|
||||
/* Address where the data is initially written after a safety margin */
|
||||
char *pBufferStart;
|
||||
char *pBuffer;
|
||||
size_t nBufferSize;
|
||||
uint32_t oAtLineStart;
|
||||
};
|
||||
|
||||
enum eLexerState {
|
||||
LEX_STATE_NORMAL,
|
||||
LEX_STATE_MACROARGS
|
||||
};
|
||||
|
||||
struct sStringExpansionPos {
|
||||
char *tzName;
|
||||
char *pBuffer;
|
||||
char *pBufferPos;
|
||||
struct sStringExpansionPos *pParent;
|
||||
};
|
||||
|
||||
#define INITIAL 0
|
||||
#define macroarg 3
|
||||
|
||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
|
||||
void setup_lexer(void);
|
||||
|
||||
void yy_set_state(enum eLexerState i);
|
||||
YY_BUFFER_STATE yy_create_buffer(FILE *f);
|
||||
YY_BUFFER_STATE yy_scan_bytes(char const *mem, uint32_t size);
|
||||
void yy_delete_buffer(YY_BUFFER_STATE buf);
|
||||
void yy_switch_to_buffer(YY_BUFFER_STATE buf);
|
||||
uint32_t lex_FloatAlloc(const struct sLexFloat *tok);
|
||||
void lex_FloatAddRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatDeleteRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatAddFirstRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatDeleteFirstRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatAddSecondRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatDeleteSecondRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_Init(void);
|
||||
void lex_AddStrings(const struct sLexInitString *lex);
|
||||
void lex_SetBuffer(char *buffer, uint32_t len);
|
||||
void lex_BeginStringExpansion(const char *tzName);
|
||||
int yywrap(void);
|
||||
char const *lexer_GetFileName(void);
|
||||
unsigned int lexer_GetLineNo(void);
|
||||
void lexer_DumpStringExpansions(void);
|
||||
int yylex(void);
|
||||
void yyunput(char c);
|
||||
void yyunputstr(const char *s);
|
||||
void yyskipbytes(uint32_t count);
|
||||
void yyunputbytes(uint32_t count);
|
||||
|
||||
extern YY_BUFFER_STATE pCurrentBuffer;
|
||||
extern struct sStringExpansionPos *pCurrentStringExpansion;
|
||||
|
||||
void upperstring(char *s);
|
||||
void lowerstring(char *s);
|
||||
void lexer_SkipToBlockEnd(int blockStartToken, int blockEndToken, int endToken,
|
||||
char **capture, size_t *size, char const *name);
|
||||
|
||||
#endif /* RGBDS_ASM_LEXER_H */
|
||||
|
||||
@@ -43,6 +43,10 @@ void opt_Push(void);
|
||||
void opt_Pop(void);
|
||||
void opt_Parse(char *s);
|
||||
|
||||
void upperstring(char *s);
|
||||
void lowerstring(char *s);
|
||||
|
||||
/* TODO: are these really needed? */
|
||||
#define YY_FATAL_ERROR fatalerror
|
||||
|
||||
#ifdef YYLMAX
|
||||
|
||||
@@ -31,7 +31,6 @@ set(rgbasm_src
|
||||
"${BISON_ASMy_OUTPUT_SOURCE}"
|
||||
"asm/charmap.c"
|
||||
"asm/fstack.c"
|
||||
"asm/globlex.c"
|
||||
"asm/lexer.c"
|
||||
"asm/macro.c"
|
||||
"asm/main.c"
|
||||
|
||||
328
src/asm/asmy.y
328
src/asm/asmy.y
@@ -39,6 +39,7 @@ uint32_t nListCountEmpty;
|
||||
char *tzNewMacro;
|
||||
uint32_t ulNewMacroSize;
|
||||
int32_t nPCOffset;
|
||||
bool skipElifs; /* If this is set, ELIFs cannot be executed anymore */
|
||||
|
||||
size_t symvaluetostring(char *dest, size_t maxLength, char *symName,
|
||||
const char *mode)
|
||||
@@ -111,278 +112,6 @@ static uint32_t str2int2(uint8_t *s, int32_t length)
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint32_t isWhiteSpace(char s)
|
||||
{
|
||||
return (s == ' ') || (s == '\t') || (s == '\0') || (s == '\n');
|
||||
}
|
||||
|
||||
static uint32_t isRept(char *s)
|
||||
{
|
||||
return (strncasecmp(s, "REPT", 4) == 0)
|
||||
&& isWhiteSpace(*(s - 1)) && isWhiteSpace(s[4]);
|
||||
}
|
||||
|
||||
static uint32_t isEndr(char *s)
|
||||
{
|
||||
return (strncasecmp(s, "ENDR", 4) == 0)
|
||||
&& isWhiteSpace(*(s - 1)) && isWhiteSpace(s[4]);
|
||||
}
|
||||
|
||||
static void copyrept(void)
|
||||
{
|
||||
int32_t level = 1, len, instring = 0;
|
||||
char *src = pCurrentBuffer->pBuffer;
|
||||
char *bufferEnd = pCurrentBuffer->pBufferStart
|
||||
+ pCurrentBuffer->nBufferSize;
|
||||
|
||||
while (src < bufferEnd && level) {
|
||||
if (instring == 0) {
|
||||
if (isRept(src)) {
|
||||
level++;
|
||||
src += 4;
|
||||
} else if (isEndr(src)) {
|
||||
level--;
|
||||
src += 4;
|
||||
} else {
|
||||
if (*src == '\"')
|
||||
instring = 1;
|
||||
src++;
|
||||
}
|
||||
} else {
|
||||
if (*src == '\\') {
|
||||
src += 2;
|
||||
} else if (*src == '\"') {
|
||||
src++;
|
||||
instring = 0;
|
||||
} else {
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (level != 0)
|
||||
fatalerror("Unterminated REPT block\n");
|
||||
|
||||
len = src - pCurrentBuffer->pBuffer - 4;
|
||||
|
||||
src = pCurrentBuffer->pBuffer;
|
||||
ulNewMacroSize = len;
|
||||
|
||||
tzNewMacro = malloc(ulNewMacroSize + 1);
|
||||
|
||||
if (tzNewMacro == NULL)
|
||||
fatalerror("Not enough memory for REPT block.\n");
|
||||
|
||||
uint32_t i;
|
||||
|
||||
tzNewMacro[ulNewMacroSize] = 0;
|
||||
for (i = 0; i < ulNewMacroSize; i++) {
|
||||
tzNewMacro[i] = src[i];
|
||||
if (src[i] == '\n')
|
||||
nLineNo++;
|
||||
}
|
||||
|
||||
yyskipbytes(ulNewMacroSize + 4);
|
||||
|
||||
}
|
||||
|
||||
static uint32_t isMacro(char *s)
|
||||
{
|
||||
return (strncasecmp(s, "MACRO", 4) == 0)
|
||||
&& isWhiteSpace(*(s - 1)) && isWhiteSpace(s[5]);
|
||||
}
|
||||
|
||||
static uint32_t isEndm(char *s)
|
||||
{
|
||||
return (strncasecmp(s, "ENDM", 4) == 0)
|
||||
&& isWhiteSpace(*(s - 1)) && isWhiteSpace(s[4]);
|
||||
}
|
||||
|
||||
static void copymacro(void)
|
||||
{
|
||||
int32_t level = 1, len, instring = 0;
|
||||
char *src = pCurrentBuffer->pBuffer;
|
||||
char *bufferEnd = pCurrentBuffer->pBufferStart
|
||||
+ pCurrentBuffer->nBufferSize;
|
||||
|
||||
while (src < bufferEnd && level) {
|
||||
if (instring == 0) {
|
||||
if (isMacro(src)) {
|
||||
level++;
|
||||
src += 4;
|
||||
} else if (isEndm(src)) {
|
||||
level--;
|
||||
src += 4;
|
||||
} else {
|
||||
if(*src == '\"')
|
||||
instring = 1;
|
||||
src++;
|
||||
}
|
||||
} else {
|
||||
if (*src == '\\') {
|
||||
src += 2;
|
||||
} else if (*src == '\"') {
|
||||
src++;
|
||||
instring = 0;
|
||||
} else {
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (level != 0)
|
||||
fatalerror("Unterminated MACRO definition.\n");
|
||||
|
||||
len = src - pCurrentBuffer->pBuffer - 4;
|
||||
|
||||
src = pCurrentBuffer->pBuffer;
|
||||
ulNewMacroSize = len;
|
||||
|
||||
tzNewMacro = (char *)malloc(ulNewMacroSize + 1);
|
||||
if (tzNewMacro == NULL)
|
||||
fatalerror("Not enough memory for MACRO definition.\n");
|
||||
|
||||
uint32_t i;
|
||||
|
||||
tzNewMacro[ulNewMacroSize] = 0;
|
||||
for (i = 0; i < ulNewMacroSize; i++) {
|
||||
tzNewMacro[i] = src[i];
|
||||
if (src[i] == '\n')
|
||||
nLineNo++;
|
||||
}
|
||||
|
||||
yyskipbytes(ulNewMacroSize + 4);
|
||||
}
|
||||
|
||||
static bool endsIf(char c)
|
||||
{
|
||||
return isWhiteSpace(c) || c == '(' || c == '{';
|
||||
}
|
||||
|
||||
static uint32_t isIf(char *s)
|
||||
{
|
||||
return (strncasecmp(s, "IF", 2) == 0)
|
||||
&& isWhiteSpace(s[-1]) && endsIf(s[2]);
|
||||
}
|
||||
|
||||
static uint32_t isElif(char *s)
|
||||
{
|
||||
return (strncasecmp(s, "ELIF", 4) == 0)
|
||||
&& isWhiteSpace(s[-1]) && endsIf(s[4]);
|
||||
}
|
||||
|
||||
static uint32_t isElse(char *s)
|
||||
{
|
||||
return (strncasecmp(s, "ELSE", 4) == 0)
|
||||
&& isWhiteSpace(s[-1]) && isWhiteSpace(s[4]);
|
||||
}
|
||||
|
||||
static uint32_t isEndc(char *s)
|
||||
{
|
||||
return (strncasecmp(s, "ENDC", 4) == 0)
|
||||
&& isWhiteSpace(s[-1]) && isWhiteSpace(s[4]);
|
||||
}
|
||||
|
||||
static void if_skip_to_else(void)
|
||||
{
|
||||
int32_t level = 1;
|
||||
bool inString = false;
|
||||
char *src = pCurrentBuffer->pBuffer;
|
||||
|
||||
while (*src && level) {
|
||||
if (*src == '\n')
|
||||
nLineNo++;
|
||||
|
||||
if (!inString) {
|
||||
if (isIf(src)) {
|
||||
level++;
|
||||
src += 2;
|
||||
|
||||
} else if (level == 1 && isElif(src)) {
|
||||
level--;
|
||||
skipElif = false;
|
||||
|
||||
} else if (level == 1 && isElse(src)) {
|
||||
level--;
|
||||
src += 4;
|
||||
|
||||
} else if (isEndc(src)) {
|
||||
level--;
|
||||
if (level != 0)
|
||||
src += 4;
|
||||
|
||||
} else {
|
||||
if (*src == '\"')
|
||||
inString = true;
|
||||
src++;
|
||||
}
|
||||
} else {
|
||||
if (*src == '\"') {
|
||||
inString = false;
|
||||
} else if (*src == '\\') {
|
||||
/* Escaped quotes don't end the string */
|
||||
if (*++src != '\"')
|
||||
src--;
|
||||
}
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
if (level != 0)
|
||||
fatalerror("Unterminated IF construct\n");
|
||||
|
||||
int32_t len = src - pCurrentBuffer->pBuffer;
|
||||
|
||||
yyskipbytes(len);
|
||||
yyunput('\n');
|
||||
nLineNo--;
|
||||
}
|
||||
|
||||
static void if_skip_to_endc(void)
|
||||
{
|
||||
int32_t level = 1;
|
||||
bool inString = false;
|
||||
char *src = pCurrentBuffer->pBuffer;
|
||||
|
||||
while (*src && level) {
|
||||
if (*src == '\n')
|
||||
nLineNo++;
|
||||
|
||||
if (!inString) {
|
||||
if (isIf(src)) {
|
||||
level++;
|
||||
src += 2;
|
||||
} else if (isEndc(src)) {
|
||||
level--;
|
||||
if (level != 0)
|
||||
src += 4;
|
||||
} else {
|
||||
if (*src == '\"')
|
||||
inString = true;
|
||||
src++;
|
||||
}
|
||||
} else {
|
||||
if (*src == '\"') {
|
||||
inString = false;
|
||||
} else if (*src == '\\') {
|
||||
/* Escaped quotes don't end the string */
|
||||
if (*++src != '\"')
|
||||
src--;
|
||||
}
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
if (level != 0)
|
||||
fatalerror("Unterminated IF construct\n");
|
||||
|
||||
int32_t len = src - pCurrentBuffer->pBuffer;
|
||||
|
||||
yyskipbytes(len);
|
||||
yyunput('\n');
|
||||
nLineNo--;
|
||||
}
|
||||
|
||||
static size_t strlenUTF8(const char *s)
|
||||
{
|
||||
size_t len = 0;
|
||||
@@ -660,7 +389,6 @@ lines : /* empty */
|
||||
nListCountEmpty = 0;
|
||||
nPCOffset = 0;
|
||||
} line '\n' {
|
||||
nLineNo++;
|
||||
nTotalLines++;
|
||||
}
|
||||
;
|
||||
@@ -699,9 +427,9 @@ label : /* empty */
|
||||
;
|
||||
|
||||
macro : T_ID {
|
||||
yy_set_state(LEX_STATE_MACROARGS);
|
||||
lexer_SetMode(LEXER_RAW);
|
||||
} macroargs {
|
||||
yy_set_state(LEX_STATE_NORMAL);
|
||||
lexer_SetMode(LEXER_NORMAL);
|
||||
fstk_RunMacro($1, $3);
|
||||
}
|
||||
;
|
||||
@@ -786,9 +514,9 @@ align : T_OP_ALIGN uconst {
|
||||
;
|
||||
|
||||
opt : T_POP_OPT {
|
||||
yy_set_state(LEX_STATE_MACROARGS);
|
||||
lexer_SetMode(LEXER_RAW);
|
||||
} opt_list {
|
||||
yy_set_state(LEX_STATE_NORMAL);
|
||||
lexer_SetMode(LEXER_NORMAL);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -875,15 +603,21 @@ load : T_POP_LOAD string ',' sectiontype sectorg sectattrs {
|
||||
;
|
||||
|
||||
rept : T_POP_REPT uconst {
|
||||
uint32_t nDefinitionLineNo = nLineNo;
|
||||
copyrept();
|
||||
uint32_t nDefinitionLineNo = lexer_GetLineNo();
|
||||
char *body;
|
||||
size_t size;
|
||||
lexer_SkipToBlockEnd(T_POP_REPT, T_POP_ENDR, T_POP_ENDR,
|
||||
&body, &size, "REPT block");
|
||||
fstk_RunRept($2, nDefinitionLineNo);
|
||||
}
|
||||
;
|
||||
|
||||
macrodef : T_LABEL ':' T_POP_MACRO {
|
||||
int32_t nDefinitionLineNo = nLineNo;
|
||||
copymacro();
|
||||
int32_t nDefinitionLineNo = lexer_GetLineNo();
|
||||
char *body;
|
||||
size_t size;
|
||||
lexer_SkipToBlockEnd(T_POP_MACRO, T_POP_ENDM, T_POP_ENDM,
|
||||
&body, &size, "macro definition");
|
||||
sym_AddMacro($1, nDefinitionLineNo);
|
||||
}
|
||||
;
|
||||
@@ -956,9 +690,9 @@ dl : T_POP_DL constlist_32bit_entry ',' constlist_32bit {
|
||||
;
|
||||
|
||||
purge : T_POP_PURGE {
|
||||
oDontExpandStrings = true;
|
||||
lexer_ToggleStringExpansion(false);
|
||||
} purge_list {
|
||||
oDontExpandStrings = false;
|
||||
lexer_ToggleStringExpansion(true);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1054,8 +788,14 @@ printf : T_POP_PRINTF const { math_Print($2); }
|
||||
|
||||
if : T_POP_IF const {
|
||||
nIFDepth++;
|
||||
if (!$2)
|
||||
if_skip_to_else();
|
||||
if (!$2) {
|
||||
/* The function is hardcoded to also stop on T_POP_ELSE and ENDC */
|
||||
lexer_SkipToBlockEnd(T_POP_IF, T_POP_ENDC, T_POP_ELIF,
|
||||
NULL, NULL, "if block");
|
||||
skipElifs = false;
|
||||
} else {
|
||||
skipElifs = true;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1063,7 +803,7 @@ elif : T_POP_ELIF const {
|
||||
if (nIFDepth <= 0)
|
||||
fatalerror("Found ELIF outside an IF construct\n");
|
||||
|
||||
if (skipElif) {
|
||||
if (skipElifs) {
|
||||
/*
|
||||
* Executed when ELIF is reached at the end of
|
||||
* an IF or ELIF block for which the condition
|
||||
@@ -1071,21 +811,24 @@ elif : T_POP_ELIF const {
|
||||
*
|
||||
* Continue parsing at ENDC keyword
|
||||
*/
|
||||
if_skip_to_endc();
|
||||
lexer_SkipToBlockEnd(T_POP_IF, T_POP_ENDC, T_POP_ENDC,
|
||||
NULL, NULL, "elif block");
|
||||
} else {
|
||||
/*
|
||||
* Executed when ELIF is skipped to because the
|
||||
* condition of the previous IF or ELIF block
|
||||
* was false.
|
||||
*/
|
||||
skipElif = true;
|
||||
|
||||
if (!$2) {
|
||||
/*
|
||||
* Continue parsing after ELSE, or at
|
||||
* ELIF or ENDC keyword.
|
||||
*/
|
||||
if_skip_to_else();
|
||||
lexer_SkipToBlockEnd(T_POP_IF, T_POP_ENDC, T_POP_ELIF,
|
||||
NULL, NULL, "elif block");
|
||||
} else {
|
||||
skipElifs = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1096,7 +839,8 @@ else : T_POP_ELSE {
|
||||
fatalerror("Found ELSE outside an IF construct\n");
|
||||
|
||||
/* Continue parsing at ENDC keyword */
|
||||
if_skip_to_endc();
|
||||
lexer_SkipToBlockEnd(T_POP_IF, T_POP_ENDC, T_POP_ENDC,
|
||||
NULL, NULL, "else block");
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1267,13 +1011,13 @@ relocexpr_no_str : scoped_id { rpn_Symbol(&$$, $1); }
|
||||
}
|
||||
| T_OP_BANK '(' string ')' { rpn_BankSection(&$$, $3); }
|
||||
| T_OP_DEF {
|
||||
oDontExpandStrings = true;
|
||||
lexer_ToggleStringExpansion(false);
|
||||
} '(' scoped_id ')' {
|
||||
struct Symbol const *sym = sym_FindSymbol($4);
|
||||
|
||||
rpn_Number(&$$, !!sym);
|
||||
|
||||
oDontExpandStrings = false;
|
||||
lexer_ToggleStringExpansion(true);
|
||||
}
|
||||
| T_OP_ROUND '(' const ')' {
|
||||
rpn_Number(&$$, math_Round($3));
|
||||
|
||||
204
src/asm/fstack.c
204
src/asm/fstack.c
@@ -36,10 +36,7 @@ static struct sContext *pFileStack;
|
||||
static unsigned int nFileStackDepth;
|
||||
unsigned int nMaxRecursionDepth;
|
||||
static struct Symbol const *pCurrentMacro;
|
||||
static YY_BUFFER_STATE CurrentFlexHandle;
|
||||
static FILE *pCurrentFile;
|
||||
static uint32_t nCurrentStatus;
|
||||
char tzCurrentFileName[_MAX_PATH + 1];
|
||||
static char IncludePaths[MAXINCPATHS][_MAX_PATH + 1];
|
||||
static int32_t NextIncPath;
|
||||
static uint32_t nMacroCount;
|
||||
@@ -81,10 +78,8 @@ static void pushcontext(void)
|
||||
if (*ppFileStack == NULL)
|
||||
fatalerror("No memory for context\n");
|
||||
|
||||
(*ppFileStack)->FlexHandle = CurrentFlexHandle;
|
||||
(*ppFileStack)->next = NULL;
|
||||
strcpy((char *)(*ppFileStack)->tzFileName, (char *)tzCurrentFileName);
|
||||
(*ppFileStack)->nLine = nLineNo;
|
||||
(*ppFileStack)->nLine = lexer_GetLineNo();
|
||||
|
||||
switch ((*ppFileStack)->nStatus = nCurrentStatus) {
|
||||
case STAT_isMacroArg:
|
||||
@@ -93,7 +88,6 @@ static void pushcontext(void)
|
||||
(*ppFileStack)->pMacro = pCurrentMacro;
|
||||
break;
|
||||
case STAT_isInclude:
|
||||
(*ppFileStack)->pFile = pCurrentFile;
|
||||
break;
|
||||
case STAT_isREPTBlock:
|
||||
(*ppFileStack)->macroArgs = macro_GetCurrentArgs();
|
||||
@@ -107,8 +101,6 @@ static void pushcontext(void)
|
||||
fatalerror("%s: Internal error.\n", __func__);
|
||||
}
|
||||
(*ppFileStack)->uniqueID = macro_GetUniqueID();
|
||||
|
||||
nLineNo = 0;
|
||||
}
|
||||
|
||||
static int32_t popcontext(void)
|
||||
@@ -122,20 +114,15 @@ static int32_t popcontext(void)
|
||||
int nNbCharsWritten;
|
||||
int nNbCharsLeft;
|
||||
|
||||
yy_delete_buffer(CurrentFlexHandle);
|
||||
CurrentFlexHandle =
|
||||
yy_scan_bytes(pCurrentREPTBlock,
|
||||
nCurrentREPTBlockSize);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
macro_SetUniqueID(nMacroCount++);
|
||||
|
||||
/* Increment REPT count in file path */
|
||||
pREPTIterationWritePtr =
|
||||
strrchr(tzCurrentFileName, '~') + 1;
|
||||
strrchr(lexer_GetFileName(), '~') + 1;
|
||||
nREPTIterationNo =
|
||||
strtoul(pREPTIterationWritePtr, NULL, 10);
|
||||
nNbCharsLeft = sizeof(tzCurrentFileName)
|
||||
- (pREPTIterationWritePtr - tzCurrentFileName);
|
||||
nNbCharsLeft = sizeof(lexer_GetFileName())
|
||||
- (pREPTIterationWritePtr - lexer_GetFileName());
|
||||
nNbCharsWritten = snprintf(pREPTIterationWritePtr,
|
||||
nNbCharsLeft, "%lu",
|
||||
nREPTIterationNo + 1);
|
||||
@@ -150,7 +137,6 @@ static int32_t popcontext(void)
|
||||
fatalerror("Cannot write REPT count to file path\n");
|
||||
}
|
||||
|
||||
nLineNo = nCurrentREPTBodyFirstLine;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -165,19 +151,8 @@ static int32_t popcontext(void)
|
||||
pLastFile = *ppLastFile;
|
||||
}
|
||||
|
||||
yy_delete_buffer(CurrentFlexHandle);
|
||||
nLineNo = nCurrentStatus == STAT_isREPTBlock ? nCurrentREPTBodyLastLine
|
||||
: pLastFile->nLine;
|
||||
|
||||
if (nCurrentStatus == STAT_isInclude)
|
||||
fclose(pCurrentFile);
|
||||
|
||||
if (nCurrentStatus == STAT_isMacro
|
||||
|| nCurrentStatus == STAT_isREPTBlock)
|
||||
nLineNo++;
|
||||
|
||||
CurrentFlexHandle = pLastFile->FlexHandle;
|
||||
strcpy((char *)tzCurrentFileName, (char *)pLastFile->tzFileName);
|
||||
lexer_DeleteState(lexer_GetState());
|
||||
lexer_SetState(pLastFile->lexerState);
|
||||
|
||||
switch (pLastFile->nStatus) {
|
||||
struct MacroArgs *args;
|
||||
@@ -193,7 +168,6 @@ static int32_t popcontext(void)
|
||||
pCurrentMacro = pLastFile->pMacro;
|
||||
break;
|
||||
case STAT_isInclude:
|
||||
pCurrentFile = pLastFile->pFile;
|
||||
break;
|
||||
case STAT_isREPTBlock:
|
||||
args = macro_GetCurrentArgs();
|
||||
@@ -218,7 +192,6 @@ static int32_t popcontext(void)
|
||||
|
||||
free(*ppLastFile);
|
||||
*ppLastFile = NULL;
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -229,11 +202,11 @@ int32_t fstk_GetLine(void)
|
||||
switch (nCurrentStatus) {
|
||||
case STAT_isInclude:
|
||||
/* This is the normal mode, also used when including a file. */
|
||||
return nLineNo;
|
||||
return lexer_GetLineNo();
|
||||
case STAT_isMacro:
|
||||
break; /* Peek top file of the stack */
|
||||
case STAT_isMacroArg:
|
||||
return nLineNo; /* ??? */
|
||||
return lexer_GetLineNo(); /* ??? */
|
||||
case STAT_isREPTBlock:
|
||||
break; /* Peek top file of the stack */
|
||||
default:
|
||||
@@ -277,7 +250,7 @@ void fstk_Dump(void)
|
||||
pLastFile = pLastFile->next;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s(%" PRId32 ")", tzCurrentFileName, nLineNo);
|
||||
fprintf(stderr, "%s(%" PRId32 ")", lexer_GetFileName(), lexer_GetLineNo());
|
||||
}
|
||||
|
||||
void fstk_DumpToStr(char *buf, size_t buflen)
|
||||
@@ -299,7 +272,7 @@ void fstk_DumpToStr(char *buf, size_t buflen)
|
||||
}
|
||||
|
||||
retcode = snprintf(&buf[buflen - len], len, "%s(%" PRId32 ")",
|
||||
tzCurrentFileName, nLineNo);
|
||||
lexer_GetFileName(), lexer_GetLineNo());
|
||||
if (retcode < 0)
|
||||
fatalerror("Failed to dump file stack to string: %s\n", strerror(errno));
|
||||
else if (retcode >= len)
|
||||
@@ -311,20 +284,6 @@ void fstk_DumpToStr(char *buf, size_t buflen)
|
||||
warning(WARNING_LONG_STR, "File stack dump too long, got truncated\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the string expansion stack to stderr
|
||||
*/
|
||||
void fstk_DumpStringExpansions(void)
|
||||
{
|
||||
const struct sStringExpansionPos *pExpansion = pCurrentStringExpansion;
|
||||
|
||||
while (pExpansion) {
|
||||
fprintf(stderr, "while expanding symbol \"%s\"\n",
|
||||
pExpansion->tzName);
|
||||
pExpansion = pExpansion->pParent;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extra includepath stuff
|
||||
*/
|
||||
@@ -351,63 +310,58 @@ static void printdep(const char *fileName)
|
||||
}
|
||||
}
|
||||
|
||||
static FILE *getFile(char const *pathname)
|
||||
static bool isPathValid(char const *pathname)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat(pathname, &statbuf) != 0)
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
/* Reject directories */
|
||||
if (S_ISDIR(statbuf.st_mode))
|
||||
return NULL;
|
||||
|
||||
return fopen(pathname, "rb");
|
||||
return !S_ISDIR(statbuf.st_mode);
|
||||
}
|
||||
|
||||
FILE *fstk_FindFile(char const *fname, char **incPathUsed)
|
||||
bool fstk_FindFile(char const *path, char **fullPath, size_t *size)
|
||||
{
|
||||
if (fname == NULL)
|
||||
return NULL;
|
||||
|
||||
char path[_MAX_PATH];
|
||||
FILE *f = getFile(fname);
|
||||
|
||||
if (f) {
|
||||
printdep(fname);
|
||||
return f;
|
||||
if (!*size) {
|
||||
*size = 64; /* This is arbitrary, really */
|
||||
*fullPath = realloc(*fullPath, *size);
|
||||
if (!*fullPath)
|
||||
error("realloc error during include path search: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < NextIncPath; ++i) {
|
||||
/*
|
||||
* The function snprintf() does not write more than `size` bytes
|
||||
* (including the terminating null byte ('\0')). If the output
|
||||
* was truncated due to this limit, the return value is the
|
||||
* number of characters (excluding the terminating null byte)
|
||||
* which would have been written to the final string if enough
|
||||
* space had been available. Thus, a return value of `size` or
|
||||
* more means that the output was truncated.
|
||||
*/
|
||||
int fullpathlen = snprintf(path, sizeof(path), "%s%s",
|
||||
IncludePaths[i], fname);
|
||||
if (*fullPath) {
|
||||
for (size_t i = 0; i <= NextIncPath; ++i) {
|
||||
char *incPath = i ? IncludePaths[i - 1] : "";
|
||||
int len = snprintf(*fullPath, *size, "%s%s", incPath, path);
|
||||
|
||||
if (fullpathlen >= (int)sizeof(path))
|
||||
continue;
|
||||
/* Oh how I wish `asnprintf` was standard... */
|
||||
if (len >= *size) { /* `len` doesn't include the terminator, `size` does */
|
||||
*size = len + 1;
|
||||
*fullPath = realloc(*fullPath, *size);
|
||||
if (!*fullPath) {
|
||||
error("realloc error during include path search: %s\n",
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
len = sprintf(*fullPath, "%s%s", incPath, path);
|
||||
}
|
||||
|
||||
f = getFile(path);
|
||||
if (f) {
|
||||
printdep(path);
|
||||
|
||||
if (incPathUsed)
|
||||
*incPathUsed = IncludePaths[i];
|
||||
return f;
|
||||
if (len < 0) {
|
||||
error("snprintf error during include path search: %s\n",
|
||||
strerror(errno));
|
||||
} else if (isPathValid(*fullPath)) {
|
||||
printdep(*fullPath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errno = ENOENT;
|
||||
if (oGeneratedMissingIncludes)
|
||||
printdep(fname);
|
||||
return NULL;
|
||||
printdep(path);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -415,33 +369,31 @@ FILE *fstk_FindFile(char const *fname, char **incPathUsed)
|
||||
*/
|
||||
void fstk_RunInclude(char *tzFileName)
|
||||
{
|
||||
char *incPathUsed = "";
|
||||
FILE *f = fstk_FindFile(tzFileName, &incPathUsed);
|
||||
char *fullPath = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
if (f == NULL) {
|
||||
if (oGeneratedMissingIncludes) {
|
||||
if (!fstk_FindFile(tzFileName, &fullPath, &size)) {
|
||||
if (oGeneratedMissingIncludes)
|
||||
oFailedOnMissingInclude = true;
|
||||
return;
|
||||
}
|
||||
error("Unable to open included file '%s': %s\n", tzFileName, strerror(errno));
|
||||
else
|
||||
error("Unable to open included file '%s': %s\n",
|
||||
tzFileName, strerror(errno));
|
||||
free(fullPath);
|
||||
return;
|
||||
}
|
||||
|
||||
pushcontext();
|
||||
nLineNo = 1;
|
||||
nCurrentStatus = STAT_isInclude;
|
||||
snprintf(tzCurrentFileName, sizeof(tzCurrentFileName), "%s%s",
|
||||
incPathUsed, tzFileName);
|
||||
if (verbose)
|
||||
printf("Assembling %s\n", tzCurrentFileName);
|
||||
pCurrentFile = f;
|
||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
printf("Assembling %s\n", fullPath);
|
||||
|
||||
/* Dirty hack to give the INCLUDE directive a linefeed */
|
||||
struct LexerState *state = lexer_OpenFile(fullPath);
|
||||
|
||||
yyunput('\n');
|
||||
nLineNo--;
|
||||
if (!state)
|
||||
/* If lexer had an error, it already reported it */
|
||||
fatalerror("Failed to open file for INCLUDE\n"); /* TODO: make this non-fatal? */
|
||||
lexer_SetStateAtEOL(state);
|
||||
free(fullPath);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -450,7 +402,6 @@ void fstk_RunInclude(char *tzFileName)
|
||||
void fstk_RunMacro(char *s, struct MacroArgs *args)
|
||||
{
|
||||
struct Symbol const *sym = sym_FindSymbol(s);
|
||||
int nPrintedChars;
|
||||
|
||||
if (sym == NULL) {
|
||||
error("Macro \"%s\" not defined\n", s);
|
||||
@@ -464,21 +415,10 @@ void fstk_RunMacro(char *s, struct MacroArgs *args)
|
||||
pushcontext();
|
||||
macro_SetUniqueID(nMacroCount++);
|
||||
/* Minus 1 because there is a newline at the beginning of the buffer */
|
||||
nLineNo = sym->fileLine - 1;
|
||||
macro_UseNewArgs(args);
|
||||
nCurrentStatus = STAT_isMacro;
|
||||
nPrintedChars = snprintf(tzCurrentFileName, _MAX_PATH + 1,
|
||||
"%s::%s", sym->fileName, s);
|
||||
if (nPrintedChars > _MAX_PATH) {
|
||||
popcontext();
|
||||
fatalerror("File name + macro name is too large to fit into buffer\n");
|
||||
}
|
||||
|
||||
pCurrentMacro = sym;
|
||||
/* TODO: why is `strlen` being used when there's a macro size field? */
|
||||
CurrentFlexHandle = yy_scan_bytes(pCurrentMacro->macro,
|
||||
strlen(pCurrentMacro->macro));
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -487,11 +427,6 @@ void fstk_RunMacro(char *s, struct MacroArgs *args)
|
||||
void fstk_RunRept(uint32_t count, int32_t nReptLineNo)
|
||||
{
|
||||
if (count) {
|
||||
static const char *tzReptStr = "::REPT~1";
|
||||
|
||||
/* For error printing to make sense, fake nLineNo */
|
||||
nCurrentREPTBodyLastLine = nLineNo;
|
||||
nLineNo = nReptLineNo;
|
||||
pushcontext();
|
||||
macro_SetUniqueID(nMacroCount++);
|
||||
nCurrentREPTBlockCount = count;
|
||||
@@ -499,15 +434,6 @@ void fstk_RunRept(uint32_t count, int32_t nReptLineNo)
|
||||
nCurrentREPTBlockSize = ulNewMacroSize;
|
||||
pCurrentREPTBlock = tzNewMacro;
|
||||
nCurrentREPTBodyFirstLine = nReptLineNo + 1;
|
||||
nLineNo = nReptLineNo;
|
||||
|
||||
if (strlen(tzCurrentFileName) + strlen(tzReptStr) > _MAX_PATH)
|
||||
fatalerror("Cannot append \"%s\" to file path\n", tzReptStr);
|
||||
strcat(tzCurrentFileName, tzReptStr);
|
||||
|
||||
CurrentFlexHandle =
|
||||
yy_scan_bytes(pCurrentREPTBlock, nCurrentREPTBlockSize);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +452,6 @@ void fstk_Init(char *pFileName)
|
||||
// minus 2 to account for trailing "\"\0"
|
||||
// minus 1 to avoid a buffer overflow in extreme cases
|
||||
while (*c && fileNameIndex < sizeof(tzSymFileName) - 2 - 1) {
|
||||
|
||||
if (*c == '"') {
|
||||
tzSymFileName[fileNameIndex++] = '\\';
|
||||
}
|
||||
@@ -541,19 +466,8 @@ void fstk_Init(char *pFileName)
|
||||
sym_AddString("__FILE__", tzSymFileName);
|
||||
|
||||
pFileStack = NULL;
|
||||
if (strcmp(pFileName, "-") == 0) {
|
||||
pCurrentFile = stdin;
|
||||
} else {
|
||||
pCurrentFile = fopen(pFileName, "rb");
|
||||
if (pCurrentFile == NULL)
|
||||
fatalerror("Unable to open file '%s': %s\n", pFileName, strerror(errno));
|
||||
}
|
||||
nFileStackDepth = 0;
|
||||
|
||||
nMacroCount = 0;
|
||||
nCurrentStatus = STAT_isInclude;
|
||||
snprintf(tzCurrentFileName, _MAX_PATH + 1, "%s", pFileName);
|
||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
nLineNo = 1;
|
||||
}
|
||||
|
||||
@@ -287,10 +287,10 @@ uint32_t ParseSymbol(char *src, uint32_t size)
|
||||
/* Feed the symbol's contents into the buffer */
|
||||
yyunputstr(s = sym_GetStringValue(sym));
|
||||
|
||||
/* Lines inserted this way shall not increase nLineNo */
|
||||
/* Lines inserted this way shall not increase lexer_GetLineNo() */
|
||||
while (*s) {
|
||||
if (*s++ == '\n')
|
||||
nLineNo--;
|
||||
lexer_GetLineNo()--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
1300
src/asm/lexer.c
1300
src/asm/lexer.c
File diff suppressed because it is too large
Load Diff
@@ -61,7 +61,7 @@ void macro_AppendArg(struct MacroArgs **argPtr, char *s)
|
||||
#define macArgs (*argPtr)
|
||||
if (macArgs->nbArgs == MAXMACROARGS)
|
||||
error("A maximum of " EXPAND_AND_STR(MAXMACROARGS)
|
||||
" arguments is allowed\n");
|
||||
" arguments is allowed\n");
|
||||
if (macArgs->nbArgs >= macArgs->capacity) {
|
||||
macArgs->capacity *= 2;
|
||||
/* Check that overflow didn't roll us back */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <inttypes.h>
|
||||
@@ -41,10 +42,6 @@ char **cldefines;
|
||||
|
||||
clock_t nStartClock, nEndClock;
|
||||
uint32_t nTotalLines, nIFDepth;
|
||||
bool skipElif;
|
||||
uint32_t unionStart[128], unionSize[128];
|
||||
|
||||
int32_t nLineNo;
|
||||
|
||||
#if defined(YYDEBUG) && YYDEBUG
|
||||
extern int yydebug;
|
||||
@@ -76,64 +73,8 @@ struct sOptionStackEntry *pOptionStack;
|
||||
|
||||
void opt_SetCurrentOptions(struct sOptions *pOpt)
|
||||
{
|
||||
if (nGBGfxID != -1) {
|
||||
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
}
|
||||
if (nBinaryID != -1) {
|
||||
lex_FloatDeleteRange(nBinaryID, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatDeleteRange(nBinaryID, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
lex_FloatDeleteSecondRange(nBinaryID, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatDeleteSecondRange(nBinaryID, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
}
|
||||
CurrentOptions = *pOpt;
|
||||
|
||||
if (nGBGfxID != -1) {
|
||||
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
}
|
||||
if (nBinaryID != -1) {
|
||||
lex_FloatAddRange(nBinaryID, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatAddRange(nBinaryID, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
lex_FloatAddSecondRange(nBinaryID, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatAddSecondRange(nBinaryID, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
}
|
||||
/* TODO */
|
||||
(void)pOpt;
|
||||
}
|
||||
|
||||
void opt_Parse(char *s)
|
||||
@@ -251,6 +192,22 @@ static void opt_ParseDefines(void)
|
||||
sym_AddString(cldefines[i], cldefines[i + 1]);
|
||||
}
|
||||
|
||||
void upperstring(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
void lowerstring(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = tolower(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Escapes Make-special chars from a string */
|
||||
static char *make_escape(const char *str)
|
||||
{
|
||||
@@ -516,8 +473,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
tzMainfile = argv[argc - 1];
|
||||
|
||||
setup_lexer();
|
||||
|
||||
if (verbose)
|
||||
printf("Assembling %s\n", tzMainfile);
|
||||
|
||||
@@ -530,17 +485,20 @@ int main(int argc, char *argv[])
|
||||
|
||||
nStartClock = clock();
|
||||
|
||||
nLineNo = 1;
|
||||
nTotalLines = 0;
|
||||
nIFDepth = 0;
|
||||
skipElif = true;
|
||||
sym_Init();
|
||||
sym_SetExportAll(exportall);
|
||||
fstk_Init(tzMainfile);
|
||||
struct LexerState *state = lexer_OpenFile(tzMainfile);
|
||||
|
||||
if (!state)
|
||||
fatalerror("Failed to open main file!");
|
||||
lexer_SetState(state);
|
||||
|
||||
opt_ParseDefines();
|
||||
charmap_New("main", NULL);
|
||||
|
||||
yy_set_state(LEX_STATE_NORMAL);
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
|
||||
if (yyparse() != 0 || nbErrors != 0)
|
||||
|
||||
@@ -656,9 +656,15 @@ void out_BinaryFile(char const *s, int32_t startPos)
|
||||
startPos = 0;
|
||||
}
|
||||
|
||||
FILE *f = fstk_FindFile(s, NULL);
|
||||
char *fullPath = NULL;
|
||||
size_t size = 0;
|
||||
FILE *f = NULL;
|
||||
|
||||
if (fstk_FindFile(s, &fullPath, &size))
|
||||
f = fopen(fullPath, "rb");
|
||||
|
||||
if (!f) {
|
||||
free(fullPath);
|
||||
if (oGeneratedMissingIncludes) {
|
||||
oFailedOnMissingInclude = true;
|
||||
return;
|
||||
@@ -699,6 +705,7 @@ void out_BinaryFile(char const *s, int32_t startPos)
|
||||
error("Error reading INCBIN file '%s': %s\n", s, strerror(errno));
|
||||
|
||||
fclose(f);
|
||||
free(fullPath);
|
||||
}
|
||||
|
||||
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length)
|
||||
@@ -715,9 +722,15 @@ void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length)
|
||||
if (length == 0) /* Don't even bother with 0-byte slices */
|
||||
return;
|
||||
|
||||
FILE *f = fstk_FindFile(s, NULL);
|
||||
char *fullPath = NULL;
|
||||
size_t size = 0;
|
||||
FILE *f = NULL;
|
||||
|
||||
if (fstk_FindFile(s, &fullPath, &size))
|
||||
f = fopen(fullPath, "rb");
|
||||
|
||||
if (!f) {
|
||||
free(fullPath);
|
||||
if (oGeneratedMissingIncludes) {
|
||||
oFailedOnMissingInclude = true;
|
||||
return;
|
||||
@@ -767,6 +780,7 @@ void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length)
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
free(fullPath);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -82,7 +82,7 @@ static int32_t Callback_NARG(void)
|
||||
|
||||
static int32_t Callback__LINE__(void)
|
||||
{
|
||||
return nLineNo;
|
||||
return lexer_GetLineNo();
|
||||
}
|
||||
|
||||
static int32_t CallbackPC(void)
|
||||
@@ -113,8 +113,9 @@ int32_t sym_GetValue(struct Symbol const *sym)
|
||||
static void updateSymbolFilename(struct Symbol *sym)
|
||||
{
|
||||
if (snprintf(sym->fileName, _MAX_PATH + 1, "%s",
|
||||
tzCurrentFileName) > _MAX_PATH)
|
||||
fatalerror("%s: File name is too long: '%s'\n", __func__, tzCurrentFileName);
|
||||
lexer_GetFileName()) > _MAX_PATH)
|
||||
fatalerror("%s: File name is too long: '%s'\n", __func__,
|
||||
lexer_GetFileName());
|
||||
sym->fileLine = fstk_GetLine();
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ void verror(const char *fmt, va_list args, char const *flag)
|
||||
fstk_Dump();
|
||||
fprintf(stderr, flag ? ": [-Werror=%s]\n " : ":\n ", flag);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fstk_DumpStringExpansions();
|
||||
lexer_DumpStringExpansions();
|
||||
nbErrors++;
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ void warning(enum WarningID id, char const *fmt, ...)
|
||||
fstk_Dump();
|
||||
fprintf(stderr, ": [-W%s]\n ", flag);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fstk_DumpStringExpansions();
|
||||
lexer_DumpStringExpansions();
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user