ref: c3fa922c2f7e09bdf577ca3041bfdbc683e55a91
dir: /src/asm/globlex.c/
#include "asm/asm.h"
#include "asm/symbol.h"
#include "asm/rpn.h"
#include "asm/symbol.h"
#include "asm/main.h"
#include "asm/lexer.h"
#include "asmy.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
UBYTE oDontExpandStrings = 0;
SLONG nGBGfxID = -1;
SLONG nBinaryID = -1;
SLONG
gbgfx2bin(char ch)
{
SLONG i;
for (i = 0; i <= 3; i += 1) {
if (CurrentOptions.gbgfx[i] == ch) {
return (i);
}
}
return (0);
}
SLONG
binary2bin(char ch)
{
SLONG i;
for (i = 0; i <= 1; i += 1) {
if (CurrentOptions.binary[i] == ch) {
return (i);
}
}
return (0);
}
SLONG
char2bin(char ch)
{
if (ch >= 'a' && ch <= 'f')
return (ch - 'a' + 10);
if (ch >= 'A' && ch <= 'F')
return (ch - 'A' + 10);
if (ch >= '0' && ch <= '9')
return (ch - '0');
return (0);
}
typedef SLONG(*x2bin) (char ch);
SLONG
ascii2bin(char *s)
{
SLONG radix = 10;
SLONG result = 0;
x2bin convertfunc = char2bin;
switch (*s) {
case '$':
radix = 16;
s += 1;
convertfunc = char2bin;
break;
case '&':
radix = 8;
s += 1;
convertfunc = char2bin;
break;
case '`':
radix = 4;
s += 1;
convertfunc = gbgfx2bin;
break;
case '%':
radix = 2;
s += 1;
convertfunc = binary2bin;
break;
}
if (radix == 4) {
SLONG c;
while (*s != '\0') {
c = convertfunc(*s++);
result = result * 2 + ((c & 1) << 8) + ((c & 2) >> 1);
}
} else {
while (*s != '\0')
result = result * radix + convertfunc(*s++);
}
return (result);
}
ULONG
ParseFixedPoint(char *s, ULONG size)
{
char dest[256];
ULONG i = 0, dot = 0;
while (size && dot != 2) {
if (s[i] == '.')
dot += 1;
if (dot < 2) {
dest[i] = s[i];
size -= 1;
i += 1;
}
}
dest[i] = 0;
yyunputbytes(size);
yylval.nConstValue = (SLONG) (atof(s) * 65536);
return (1);
}
ULONG
ParseNumber(char *s, ULONG size)
{
char dest[256];
strncpy(dest, s, size);
dest[size] = 0;
yylval.nConstValue = ascii2bin(dest);
return (1);
}
ULONG
ParseSymbol(char *src, ULONG size)
{
char dest[MAXSYMLEN + 1];
int copied = 0, size_backup = size;
while (size && copied < MAXSYMLEN) {
if (*src == '\\') {
char *marg;
src += 1;
size -= 1;
if (*src == '@')
marg = sym_FindMacroArg(-1);
else if (*src >= '0' && *src <= '9')
marg = sym_FindMacroArg(*src);
else {
fatalerror("Malformed ID");
return (0);
}
src += 1;
size -= 1;
if (marg) {
while (*marg)
dest[copied++] = *marg++;
}
} else {
dest[copied++] = *src++;
size -= 1;
}
}
if (copied > MAXSYMLEN)
fatalerror("Symbol too long");
dest[copied] = 0;
if (oDontExpandStrings == 0 && sym_isString(dest)) {
char *s;
yyskipbytes(size_backup);
yyunputstr(s = sym_GetStringValue(dest));
while (*s) {
if (*s++ == '\n') {
nLineNo -= 1;
}
}
return (0);
} else {
strcpy(yylval.tzString, dest);
return (1);
}
}
ULONG
PutMacroArg(char *src, ULONG size)
{
char *s;
yyskipbytes(size);
if ((s = sym_FindMacroArg(src[1] - '0')) != NULL) {
yyunputstr(s);
} else {
yyerror("Macro argument not defined");
}
return (0);
}
ULONG
PutUniqueArg(char *src, ULONG size)
{
src = src;
yyskipbytes(size);
yyunputstr(sym_FindMacroArg(-1));
return (0);
}
enum {
T_LEX_MACROARG = 3000,
T_LEX_MACROUNIQUE
};
extern struct sLexInitString localstrings[];
struct sLexInitString staticstrings[] = {
{"||", T_OP_LOGICOR},
{"&&", T_OP_LOGICAND},
{"==", T_OP_LOGICEQU},
{">", T_OP_LOGICGT},
{"<", T_OP_LOGICLT},
{">=", T_OP_LOGICGE},
{"<=", T_OP_LOGICLE},
{"!=", T_OP_LOGICNE},
{"!", T_OP_LOGICNOT},
{"|", T_OP_OR},
{"^", T_OP_XOR},
{"&", T_OP_AND},
{"<<", T_OP_SHL},
{">>", T_OP_SHR},
{"+", T_OP_ADD},
{"-", T_OP_SUB},
{"*", T_OP_MUL},
{"/", T_OP_DIV},
{"%", T_OP_MOD},
{"~", T_OP_NOT},
{"def", T_OP_DEF},
{"bank", T_OP_BANK},
{"div", T_OP_FDIV},
{"mul", T_OP_FMUL},
{"sin", T_OP_SIN},
{"cos", T_OP_COS},
{"tan", T_OP_TAN},
{"asin", T_OP_ASIN},
{"acos", T_OP_ACOS},
{"atan", T_OP_ATAN},
{"atan2", T_OP_ATAN2},
{"strcmp", T_OP_STRCMP},
{"strin", T_OP_STRIN},
{"strsub", T_OP_STRSUB},
{"strlen", T_OP_STRLEN},
{"strcat", T_OP_STRCAT},
{"strupr", T_OP_STRUPR},
{"strlwr", T_OP_STRLWR},
{"include", T_POP_INCLUDE},
{"printt", T_POP_PRINTT},
{"printv", T_POP_PRINTV},
{"printf", T_POP_PRINTF},
{"export", T_POP_EXPORT},
{"xdef", T_POP_EXPORT},
{"import", T_POP_IMPORT},
{"xref", T_POP_IMPORT},
{"global", T_POP_GLOBAL},
{"ds", T_POP_DS},
{NAME_DB, T_POP_DB},
{NAME_DW, T_POP_DW},
#ifdef NAME_DL
{NAME_DL, T_POP_DL},
#endif
{"section", T_POP_SECTION},
{"purge", T_POP_PURGE},
{"rsreset", T_POP_RSRESET},
{"rsset", T_POP_RSSET},
{"incbin", T_POP_INCBIN},
{"fail", T_POP_FAIL},
{"warn", T_POP_WARN},
{"macro", T_POP_MACRO},
/* Not needed but we have it here just to protect the name */
{"endm", T_POP_ENDM},
{"shift", T_POP_SHIFT},
{"rept", T_POP_REPT},
/* Not needed but we have it here just to protect the name */
{"endr", T_POP_ENDR},
{"if", T_POP_IF},
{"else", T_POP_ELSE},
{"endc", T_POP_ENDC},
{"bss", T_SECT_BSS},
#if defined(GAMEBOY) || defined(PCENGINE)
{"vram", T_SECT_VRAM},
#endif
{"code", T_SECT_CODE},
{"data", T_SECT_CODE},
#ifdef GAMEBOY
{"home", T_SECT_HOME},
{"hram", T_SECT_HRAM},
#endif
{NAME_RB, T_POP_RB},
{NAME_RW, T_POP_RW},
#ifdef NAME_RL
{NAME_RL, T_POP_RL},
#endif
{"equ", T_POP_EQU},
{"equs", T_POP_EQUS},
{"set", T_POP_SET},
{"=", T_POP_SET},
{"pushs", T_POP_PUSHS},
{"pops", T_POP_POPS},
{"pusho", T_POP_PUSHO},
{"popo", T_POP_POPO},
{"opt", T_POP_OPT},
{NULL, 0}
};
struct sLexFloat tNumberToken = {
ParseNumber,
T_NUMBER
};
struct sLexFloat tFixedPointToken = {
ParseFixedPoint,
T_NUMBER
};
struct sLexFloat tIDToken = {
ParseSymbol,
T_ID
};
struct sLexFloat tMacroArgToken = {
PutMacroArg,
T_LEX_MACROARG
};
struct sLexFloat tMacroUniqueToken = {
PutUniqueArg,
T_LEX_MACROUNIQUE
};
void
setuplex(void)
{
ULONG id;
lex_Init();
lex_AddStrings(staticstrings);
lex_AddStrings(localstrings);
//Macro arguments
id = lex_FloatAlloc(&tMacroArgToken);
lex_FloatAddFirstRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '0', '9');
id = lex_FloatAlloc(&tMacroUniqueToken);
lex_FloatAddFirstRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '@', '@');
//Decimal constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '0', '9');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddRange(id, '0', '9');
//Binary constants
nBinaryID = id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '%', '%');
lex_FloatAddSecondRange(id, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddSecondRange(id, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
lex_FloatAddRange(id, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddRange(id, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
//Octal constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '&', '&');
lex_FloatAddSecondRange(id, '0', '7');
lex_FloatAddRange(id, '0', '7');
//Gameboy gfx constants
nGBGfxID = id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '`', '`');
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3]);
//Hex constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '$', '$');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddSecondRange(id, 'A', 'F');
lex_FloatAddSecondRange(id, 'a', 'f');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, 'A', 'F');
lex_FloatAddRange(id, 'a', 'f');
//ID 's
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, 'a', 'z');
lex_FloatAddFirstRange(id, 'A', 'Z');
lex_FloatAddFirstRange(id, '_', '_');
lex_FloatAddSecondRange(id, 'a', 'z');
lex_FloatAddSecondRange(id, 'A', 'Z');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddSecondRange(id, '_', '_');
lex_FloatAddSecondRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '@', '@');
lex_FloatAddSecondRange(id, '#', '#');
lex_FloatAddRange(id, 'a', 'z');
lex_FloatAddRange(id, 'A', 'Z');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, '_', '_');
lex_FloatAddRange(id, '\\', '\\');
lex_FloatAddRange(id, '@', '@');
lex_FloatAddRange(id, '#', '#');
//Local ID
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, '.', '.');
lex_FloatAddSecondRange(id, 'a', 'z');
lex_FloatAddSecondRange(id, 'A', 'Z');
lex_FloatAddSecondRange(id, '_', '_');
lex_FloatAddRange(id, 'a', 'z');
lex_FloatAddRange(id, 'A', 'Z');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, '_', '_');
lex_FloatAddRange(id, '\\', '\\');
lex_FloatAddRange(id, '@', '@');
lex_FloatAddRange(id, '#', '#');
//@ID
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, '@', '@');
//Fixed point constants
id = lex_FloatAlloc(&tFixedPointToken);
lex_FloatAddFirstRange(id, '.', '.');
lex_FloatAddFirstRange(id, '0', '9');
lex_FloatAddSecondRange(id, '.', '.');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddRange(id, '.', '.');
lex_FloatAddRange(id, '0', '9');
}