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:
ISSOtm
2020-07-23 12:12:58 +02:00
parent 3a44cc7722
commit 6dc4ce6599
15 changed files with 497 additions and 1586 deletions

View File

@@ -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 \

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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"

View File

@@ -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));

View File

@@ -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;
}

View File

@@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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)

View File

@@ -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);
}
/*

View File

@@ -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();
}

View File

@@ -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);
}