shithub: rgbds

ref: b53e17078150a42cc74e78e3f4327457c66854e0
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');

}