mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
786 lines
14 KiB
C
786 lines
14 KiB
C
#include "asm/asm.h"
|
|
#include "asm/lexer.h"
|
|
#include "asm/types.h"
|
|
#include "asm/main.h"
|
|
#include "asm/rpn.h"
|
|
#include "asm/fstack.h"
|
|
|
|
#include "asmy.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
struct sLexString {
|
|
char *tzName;
|
|
ULONG nToken;
|
|
ULONG nNameLength;
|
|
struct sLexString *pNext;
|
|
};
|
|
|
|
#define pLexBuffer (pCurrentBuffer->pBuffer)
|
|
#define nLexBufferLeng (pCurrentBuffer->nBufferSize)
|
|
|
|
#define SAFETYMARGIN 1024
|
|
|
|
extern ULONG symvaluetostring(char *dest, char *s);
|
|
|
|
struct sLexFloat tLexFloat[32];
|
|
struct sLexString *tLexHash[LEXHASHSIZE];
|
|
YY_BUFFER_STATE pCurrentBuffer;
|
|
ULONG yyleng;
|
|
ULONG nLexMaxLeng;
|
|
|
|
ULONG tFloatingSecondChar[256];
|
|
ULONG tFloatingFirstChar[256];
|
|
ULONG tFloatingChars[256];
|
|
ULONG nFloating;
|
|
enum eLexerState lexerstate = LEX_STATE_NORMAL;
|
|
|
|
#define AtLineStart pCurrentBuffer->oAtLineStart
|
|
|
|
#ifdef __GNUC__
|
|
void strupr(char *s)
|
|
{
|
|
while (*s) {
|
|
*s = toupper(*s);
|
|
s += 1;
|
|
}
|
|
}
|
|
|
|
void strlwr(char *s)
|
|
{
|
|
while (*s) {
|
|
*s = tolower(*s);
|
|
s += 1;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
void yyskipbytes(ULONG count)
|
|
{
|
|
pLexBuffer += count;
|
|
}
|
|
|
|
void yyunputbytes(ULONG count)
|
|
{
|
|
pLexBuffer -= count;
|
|
}
|
|
|
|
void yyunput(char c)
|
|
{
|
|
*(--pLexBuffer) = c;
|
|
}
|
|
|
|
void yyunputstr(char *s)
|
|
{
|
|
SLONG i;
|
|
|
|
i = strlen(s) - 1;
|
|
|
|
while (i >= 0)
|
|
yyunput(s[i--]);
|
|
}
|
|
|
|
void yy_switch_to_buffer(YY_BUFFER_STATE buf)
|
|
{
|
|
pCurrentBuffer = buf;
|
|
}
|
|
|
|
void yy_set_state(enum eLexerState i)
|
|
{
|
|
lexerstate = i;
|
|
}
|
|
|
|
void yy_delete_buffer(YY_BUFFER_STATE buf)
|
|
{
|
|
free(buf->pBufferStart - SAFETYMARGIN);
|
|
free(buf);
|
|
}
|
|
|
|
YY_BUFFER_STATE yy_scan_bytes(char *mem, ULONG size)
|
|
{
|
|
YY_BUFFER_STATE pBuffer;
|
|
|
|
if ((pBuffer =
|
|
(YY_BUFFER_STATE) malloc(sizeof(struct yy_buffer_state))) !=
|
|
NULL) {
|
|
if ((pBuffer->pBuffer = pBuffer->pBufferStart =
|
|
(char *)malloc(size + 1 + SAFETYMARGIN)) != NULL) {
|
|
pBuffer->pBuffer += SAFETYMARGIN;
|
|
pBuffer->pBufferStart += SAFETYMARGIN;
|
|
memcpy(pBuffer->pBuffer, mem, size);
|
|
pBuffer->nBufferSize = size;
|
|
pBuffer->oAtLineStart = 1;
|
|
pBuffer->pBuffer[size] = 0;
|
|
return (pBuffer);
|
|
}
|
|
}
|
|
|
|
fatalerror("Out of memory!");
|
|
return (NULL);
|
|
}
|
|
|
|
YY_BUFFER_STATE yy_create_buffer(FILE * f)
|
|
{
|
|
YY_BUFFER_STATE pBuffer;
|
|
|
|
if ((pBuffer =
|
|
(YY_BUFFER_STATE) malloc(sizeof(struct yy_buffer_state))) !=
|
|
NULL) {
|
|
ULONG size;
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
size = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
|
|
if ((pBuffer->pBuffer = pBuffer->pBufferStart =
|
|
(char *)malloc(size + 2 + SAFETYMARGIN)) != NULL) {
|
|
char *mem;
|
|
ULONG instring = 0;
|
|
|
|
pBuffer->pBuffer += SAFETYMARGIN;
|
|
pBuffer->pBufferStart += SAFETYMARGIN;
|
|
|
|
size = fread(pBuffer->pBuffer, sizeof(UBYTE), size, f);
|
|
|
|
pBuffer->pBuffer[size] = '\n';
|
|
pBuffer->pBuffer[size + 1] = 0;
|
|
pBuffer->nBufferSize = size + 1;
|
|
|
|
mem = pBuffer->pBuffer;
|
|
|
|
while (*mem) {
|
|
if (*mem == '\"')
|
|
instring = 1 - instring;
|
|
|
|
if (instring) {
|
|
mem += 1;
|
|
} else {
|
|
if ((mem[0] == 10 && mem[1] == 13)
|
|
|| (mem[0] == 13 && mem[1] == 10)) {
|
|
mem[0] = ' ';
|
|
mem[1] = '\n';
|
|
mem += 2;
|
|
} else if (mem[0] == 10 || mem[0] == 13) {
|
|
mem[0] = '\n';
|
|
mem += 1;
|
|
} else if (mem[0] == '\n'
|
|
&& mem[1] == '*') {
|
|
mem += 1;
|
|
while (!
|
|
(*mem == '\n'
|
|
|| *mem == '\0'))
|
|
*mem++ = ' ';
|
|
} else if (*mem == ';') {
|
|
while (!
|
|
(*mem == '\n'
|
|
|| *mem == '\0'))
|
|
*mem++ = ' ';
|
|
} else
|
|
mem += 1;
|
|
}
|
|
}
|
|
|
|
pBuffer->oAtLineStart = 1;
|
|
return (pBuffer);
|
|
}
|
|
}
|
|
|
|
fatalerror("Out of memory!");
|
|
return (NULL);
|
|
}
|
|
|
|
ULONG lex_FloatAlloc(struct sLexFloat * tok)
|
|
{
|
|
tLexFloat[nFloating] = (*tok);
|
|
|
|
return (1 << (nFloating++));
|
|
}
|
|
|
|
void lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end)
|
|
{
|
|
while (start <= end) {
|
|
tFloatingChars[start] &= ~id;
|
|
start += 1;
|
|
}
|
|
}
|
|
|
|
void lex_FloatAddRange(ULONG id, UWORD start, UWORD end)
|
|
{
|
|
while (start <= end) {
|
|
tFloatingChars[start] |= id;
|
|
start += 1;
|
|
}
|
|
}
|
|
|
|
void lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end)
|
|
{
|
|
while (start <= end) {
|
|
tFloatingFirstChar[start] &= ~id;
|
|
start += 1;
|
|
}
|
|
}
|
|
|
|
void lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end)
|
|
{
|
|
while (start <= end) {
|
|
tFloatingFirstChar[start] |= id;
|
|
start += 1;
|
|
}
|
|
}
|
|
|
|
void lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end)
|
|
{
|
|
while (start <= end) {
|
|
tFloatingSecondChar[start] &= ~id;
|
|
start += 1;
|
|
}
|
|
}
|
|
|
|
void lex_FloatAddSecondRange(ULONG id, UWORD start, UWORD end)
|
|
{
|
|
while (start <= end) {
|
|
tFloatingSecondChar[start] |= id;
|
|
start += 1;
|
|
}
|
|
}
|
|
|
|
struct sLexFloat *lexgetfloat(ULONG id)
|
|
{
|
|
ULONG r = 0, mask = 1;
|
|
|
|
if (id == 0)
|
|
return (NULL);
|
|
|
|
while ((id & mask) == 0) {
|
|
mask <<= 1;
|
|
r += 1;
|
|
}
|
|
|
|
return (&tLexFloat[r]);
|
|
}
|
|
|
|
ULONG lexcalchash(char *s)
|
|
{
|
|
ULONG r = 0;
|
|
|
|
while (*s) {
|
|
r = ((r << 1) + (toupper(*s))) % LEXHASHSIZE;
|
|
s += 1;
|
|
}
|
|
|
|
return (r);
|
|
}
|
|
|
|
void lex_Init(void)
|
|
{
|
|
ULONG i;
|
|
|
|
for (i = 0; i < LEXHASHSIZE; i += 1) {
|
|
tLexHash[i] = NULL;
|
|
}
|
|
|
|
for (i = 0; i < 256; i += 1) {
|
|
tFloatingFirstChar[i] = 0;
|
|
tFloatingSecondChar[i] = 0;
|
|
tFloatingChars[i] = 0;
|
|
}
|
|
|
|
nLexMaxLeng = 0;
|
|
nFloating = 0;
|
|
}
|
|
|
|
void lex_AddStrings(struct sLexInitString *lex)
|
|
{
|
|
while (lex->tzName) {
|
|
struct sLexString **ppHash;
|
|
ULONG hash;
|
|
|
|
ppHash = &tLexHash[hash = lexcalchash(lex->tzName)];
|
|
while (*ppHash)
|
|
ppHash = &((*ppHash)->pNext);
|
|
|
|
// printf( "%s has hashvalue %d\n", lex->tzName, hash );
|
|
|
|
if (((*ppHash) =
|
|
(struct sLexString *)malloc(sizeof(struct sLexString))) !=
|
|
NULL) {
|
|
if (((*ppHash)->tzName =
|
|
(char *)strdup(lex->tzName)) != NULL) {
|
|
(*ppHash)->nNameLength = strlen(lex->tzName);
|
|
(*ppHash)->nToken = lex->nToken;
|
|
(*ppHash)->pNext = NULL;
|
|
|
|
strupr((*ppHash)->tzName);
|
|
|
|
if ((*ppHash)->nNameLength > nLexMaxLeng)
|
|
nLexMaxLeng = (*ppHash)->nNameLength;
|
|
|
|
} else
|
|
fatalerror("Out of memory!");
|
|
} else
|
|
fatalerror("Out of memory!");
|
|
|
|
lex += 1;
|
|
}
|
|
}
|
|
|
|
ULONG yylex(void)
|
|
{
|
|
ULONG hash, maxlen;
|
|
char *s;
|
|
struct sLexString *pLongestFixed = NULL;
|
|
ULONG nFloatMask, nOldFloatMask, nFloatLen;
|
|
ULONG linestart = AtLineStart;
|
|
|
|
switch (lexerstate) {
|
|
case LEX_STATE_NORMAL:
|
|
AtLineStart = 0;
|
|
|
|
scanagain:
|
|
|
|
while (*pLexBuffer == ' ' || *pLexBuffer == '\t') {
|
|
linestart = 0;
|
|
pLexBuffer += 1;
|
|
}
|
|
|
|
if (*pLexBuffer == 0) {
|
|
if (yywrap() == 0) {
|
|
linestart = AtLineStart;
|
|
AtLineStart = 0;
|
|
goto scanagain;
|
|
}
|
|
}
|
|
|
|
s = pLexBuffer;
|
|
nOldFloatMask = nFloatLen = 0;
|
|
nFloatMask = tFloatingFirstChar[(int) *s++];
|
|
while (nFloatMask && nFloatLen < nLexBufferLeng) {
|
|
nFloatLen += 1;
|
|
nOldFloatMask = nFloatMask;
|
|
if (nFloatLen == 1)
|
|
nFloatMask &= tFloatingSecondChar[(int) *s++];
|
|
else
|
|
nFloatMask &= tFloatingChars[(int) *s++];
|
|
}
|
|
|
|
maxlen = nLexBufferLeng;
|
|
if (nLexMaxLeng < maxlen)
|
|
maxlen = nLexMaxLeng;
|
|
|
|
yyleng = 0;
|
|
hash = 0;
|
|
s = pLexBuffer;
|
|
while (yyleng < nLexMaxLeng) {
|
|
yyleng += 1;
|
|
hash = ((hash << 1) + (toupper(*s))) % LEXHASHSIZE;
|
|
s += 1;
|
|
if (tLexHash[hash]) {
|
|
struct sLexString *lex;
|
|
|
|
lex = tLexHash[hash];
|
|
while (lex) {
|
|
if (lex->nNameLength == yyleng) {
|
|
if (strnicmp
|
|
(pLexBuffer, lex->tzName,
|
|
yyleng) == 0) {
|
|
pLongestFixed = lex;
|
|
}
|
|
}
|
|
lex = lex->pNext;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (nFloatLen == 0 && pLongestFixed == NULL) {
|
|
if (*pLexBuffer == '"') {
|
|
ULONG index = 0;
|
|
|
|
pLexBuffer += 1;
|
|
while ((*pLexBuffer != '"')
|
|
&& (*pLexBuffer != '\n')) {
|
|
char ch, *marg;
|
|
|
|
if ((ch = *pLexBuffer++) == '\\') {
|
|
switch (ch = (*pLexBuffer++)) {
|
|
case 'n':
|
|
ch = '\n';
|
|
break;
|
|
case 't':
|
|
ch = '\t';
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if ((marg =
|
|
sym_FindMacroArg(ch
|
|
-
|
|
'0'))
|
|
!= NULL) {
|
|
while (*marg)
|
|
yylval.
|
|
tzString
|
|
[index++]
|
|
=
|
|
*marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
case '@':
|
|
if ((marg =
|
|
sym_FindMacroArg
|
|
(-1)) != NULL) {
|
|
while (*marg)
|
|
yylval.
|
|
tzString
|
|
[index++]
|
|
=
|
|
*marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
}
|
|
} else if (ch == '{') {
|
|
char sym[MAXSYMLEN];
|
|
int i = 0;
|
|
|
|
while ((*pLexBuffer != '}')
|
|
&& (*pLexBuffer != '"')
|
|
&& (*pLexBuffer !=
|
|
'\n')) {
|
|
if ((ch =
|
|
*pLexBuffer++) ==
|
|
'\\') {
|
|
switch (ch =
|
|
(*pLexBuffer++))
|
|
{
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if ((marg = sym_FindMacroArg(ch - '0')) != NULL) {
|
|
while
|
|
(*marg)
|
|
sym[i++] = *marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
case '@':
|
|
if ((marg = sym_FindMacroArg(-1)) != NULL) {
|
|
while
|
|
(*marg)
|
|
sym[i++] = *marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
}
|
|
} else
|
|
sym[i++] = ch;
|
|
}
|
|
|
|
sym[i] = 0;
|
|
index +=
|
|
symvaluetostring(&yylval.
|
|
tzString
|
|
[index],
|
|
sym);
|
|
if (*pLexBuffer == '}')
|
|
pLexBuffer += 1;
|
|
else
|
|
yyerror("Missing }");
|
|
ch = 0;
|
|
}
|
|
|
|
if (ch)
|
|
yylval.tzString[index++] = ch;
|
|
}
|
|
|
|
yylval.tzString[index++] = 0;
|
|
|
|
if (*pLexBuffer == '\n')
|
|
yyerror("Unterminated string");
|
|
else
|
|
pLexBuffer += 1;
|
|
|
|
return (T_STRING);
|
|
} else if (*pLexBuffer == '{') {
|
|
char sym[MAXSYMLEN], ch, *marg;
|
|
int i = 0;
|
|
|
|
pLexBuffer += 1;
|
|
|
|
while ((*pLexBuffer != '}')
|
|
&& (*pLexBuffer != '\n')) {
|
|
if ((ch = *pLexBuffer++) == '\\') {
|
|
switch (ch = (*pLexBuffer++)) {
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if ((marg =
|
|
sym_FindMacroArg(ch
|
|
-
|
|
'0'))
|
|
!= NULL) {
|
|
while (*marg)
|
|
sym[i++]
|
|
=
|
|
*marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
case '@':
|
|
if ((marg =
|
|
sym_FindMacroArg
|
|
(-1)) != NULL) {
|
|
while (*marg)
|
|
sym[i++]
|
|
=
|
|
*marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
}
|
|
} else
|
|
sym[i++] = ch;
|
|
}
|
|
sym[i] = 0;
|
|
symvaluetostring(yylval.tzString, sym);
|
|
if (*pLexBuffer == '}')
|
|
pLexBuffer += 1;
|
|
else
|
|
yyerror("Missing }");
|
|
|
|
return (T_STRING);
|
|
} else {
|
|
if (*pLexBuffer == '\n')
|
|
AtLineStart = 1;
|
|
|
|
yyleng = 1;
|
|
return (*pLexBuffer++);
|
|
}
|
|
}
|
|
|
|
if (nFloatLen == 0) {
|
|
yyleng = pLongestFixed->nNameLength;
|
|
pLexBuffer += yyleng;
|
|
return (pLongestFixed->nToken);
|
|
}
|
|
|
|
if (pLongestFixed == NULL) {
|
|
struct sLexFloat *tok;
|
|
|
|
tok = lexgetfloat(nOldFloatMask);
|
|
yyleng = nFloatLen;
|
|
if (tok->Callback) {
|
|
if (tok->Callback(pLexBuffer, yyleng) == 0)
|
|
goto scanagain;
|
|
}
|
|
|
|
if (tok->nToken == T_ID && linestart) {
|
|
pLexBuffer += yyleng;
|
|
return (T_LABEL);
|
|
} else {
|
|
pLexBuffer += yyleng;
|
|
return (tok->nToken);
|
|
}
|
|
}
|
|
|
|
if (nFloatLen > pLongestFixed->nNameLength) {
|
|
struct sLexFloat *tok;
|
|
|
|
tok = lexgetfloat(nOldFloatMask);
|
|
yyleng = nFloatLen;
|
|
if (tok->Callback) {
|
|
if (tok->Callback(pLexBuffer, yyleng) == 0)
|
|
goto scanagain;
|
|
}
|
|
|
|
if (tok->nToken == T_ID && linestart) {
|
|
pLexBuffer += yyleng;
|
|
return (T_LABEL);
|
|
} else {
|
|
pLexBuffer += yyleng;
|
|
return (tok->nToken);
|
|
}
|
|
} else {
|
|
yyleng = pLongestFixed->nNameLength;
|
|
pLexBuffer += yyleng;
|
|
return (pLongestFixed->nToken);
|
|
}
|
|
break;
|
|
|
|
case LEX_STATE_MACROARGS:
|
|
{
|
|
ULONG index = 0;
|
|
|
|
while (*pLexBuffer == ' ' || *pLexBuffer == '\t') {
|
|
linestart = 0;
|
|
pLexBuffer += 1;
|
|
}
|
|
|
|
while ((*pLexBuffer != ',')
|
|
&& (*pLexBuffer != '\n')) {
|
|
char ch, *marg;
|
|
|
|
if ((ch = *pLexBuffer++) == '\\') {
|
|
switch (ch = (*pLexBuffer++)) {
|
|
case 'n':
|
|
ch = '\n';
|
|
break;
|
|
case 't':
|
|
ch = '\t';
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if ((marg =
|
|
sym_FindMacroArg(ch -
|
|
'0')) !=
|
|
NULL) {
|
|
while (*marg)
|
|
yylval.
|
|
tzString
|
|
[index++] =
|
|
*marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
case '@':
|
|
if ((marg =
|
|
sym_FindMacroArg(-1)) !=
|
|
NULL) {
|
|
while (*marg)
|
|
yylval.
|
|
tzString
|
|
[index++] =
|
|
*marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
}
|
|
} else if (ch == '{') {
|
|
char sym[MAXSYMLEN];
|
|
int i = 0;
|
|
|
|
while ((*pLexBuffer != '}')
|
|
&& (*pLexBuffer != '"')
|
|
&& (*pLexBuffer != '\n')) {
|
|
if ((ch =
|
|
*pLexBuffer++) == '\\') {
|
|
switch (ch =
|
|
(*pLexBuffer++))
|
|
{
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if ((marg =
|
|
sym_FindMacroArg
|
|
(ch -
|
|
'0')) !=
|
|
NULL) {
|
|
while
|
|
(*marg)
|
|
sym[i++] = *marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
case '@':
|
|
if ((marg =
|
|
sym_FindMacroArg
|
|
(-1)) !=
|
|
NULL) {
|
|
while
|
|
(*marg)
|
|
sym[i++] = *marg++;
|
|
ch = 0;
|
|
}
|
|
break;
|
|
}
|
|
} else
|
|
sym[i++] = ch;
|
|
}
|
|
sym[i] = 0;
|
|
index +=
|
|
symvaluetostring(&yylval.
|
|
tzString[index],
|
|
sym);
|
|
if (*pLexBuffer == '}')
|
|
pLexBuffer += 1;
|
|
else
|
|
yyerror("Missing }");
|
|
ch = 0;
|
|
}
|
|
|
|
if (ch)
|
|
yylval.tzString[index++] = ch;
|
|
}
|
|
|
|
if (index) {
|
|
yyleng = index;
|
|
yylval.tzString[index] = 0;
|
|
if (*pLexBuffer == '\n') {
|
|
while (yylval.tzString[--index] == ' ') {
|
|
yylval.tzString[index] = 0;
|
|
yyleng -= 1;
|
|
}
|
|
}
|
|
return (T_STRING);
|
|
} else if (*pLexBuffer == '\n') {
|
|
pLexBuffer += 1;
|
|
AtLineStart = 1;
|
|
yyleng = 1;
|
|
return ('\n');
|
|
} else if (*pLexBuffer == ',') {
|
|
pLexBuffer += 1;
|
|
yyleng = 1;
|
|
return (',');
|
|
} else {
|
|
yyerror("INTERNAL ERROR IN YYLEX");
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
yyerror("INTERNAL ERROR IN YYLEX");
|
|
return (0);
|
|
}
|