shithub: rgbds

ref: b6c749ffbd30138de7beef13fb9265372a461a96
dir: /src/asm/globlex.c/

View raw version
#include "asm.h"
#include "symbol.h"
#include "rpn.h"
#include "asmy.h"
#include "symbol.h"
#include "main.h"
#include "lexer.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,
	"endm", T_POP_ENDM,	//      Not needed but we have it here just to protect the name
	"shift", T_POP_SHIFT,

	"rept", T_POP_REPT,
	"endr", T_POP_ENDR,	//      Not needed but we have it here just to protect the name

	"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');

}