shithub: rgbds

ref: 97d431d1f4ad404e282e3781bd195be3f053734d
dir: /src/asm/fstack.c/

View raw version
/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * INCLUDES
 *
 */

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef STRL_IN_LIBC
#define strlcpy rgbds_strlcpy
#define strlcat rgbds_strlcat
size_t strlcpy(char *, const char *, size_t);
size_t strlcat(char *, const char *, size_t);
#endif

#include "asm/symbol.h"
#include "asm/fstack.h"
#include "asm/types.h"
#include "asm/main.h"
#include "asm/lexer.h"

/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * VARIABLES
 *
 */

struct sContext *pFileStack;
struct sSymbol *pCurrentMacro;
YY_BUFFER_STATE CurrentFlexHandle;
FILE *pCurrentFile;
ULONG nCurrentStatus;
char *tzCurrentFileName;
char IncludePaths[MAXINCPATHS][_MAX_PATH + 1];
SLONG NextIncPath = 0;
ULONG nMacroCount;

char *pCurrentREPTBlock;
ULONG nCurrentREPTBlockSize;
ULONG nCurrentREPTBlockCount;

ULONG ulMacroReturnValue;

/*
 * defines for nCurrentStatus
 */
#define STAT_isInclude 		0
#define STAT_isMacro	 		1
#define STAT_isMacroArg		2
#define STAT_isREPTBlock	3

/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * Context push and pop
 *
 */

void 
pushcontext(void)
{
	struct sContext **ppFileStack;

	ppFileStack = &pFileStack;
	while (*ppFileStack)
		ppFileStack = &((*ppFileStack)->pNext);

	if ((*ppFileStack =
		(struct sContext *) malloc(sizeof(struct sContext))) != NULL) {
		(*ppFileStack)->FlexHandle = CurrentFlexHandle;
		(*ppFileStack)->pNext = NULL;
		(*ppFileStack)->tzFileName = tzCurrentFileName;
		(*ppFileStack)->nLine = nLineNo;
		switch ((*ppFileStack)->nStatus = nCurrentStatus) {
		case STAT_isMacroArg:
		case STAT_isMacro:
			sym_SaveCurrentMacroArgs((*ppFileStack)->tzMacroArgs);
			(*ppFileStack)->pMacro = pCurrentMacro;
			break;
		case STAT_isInclude:
			(*ppFileStack)->pFile = pCurrentFile;
			break;
		case STAT_isREPTBlock:
			sym_SaveCurrentMacroArgs((*ppFileStack)->tzMacroArgs);
			(*ppFileStack)->pREPTBlock = pCurrentREPTBlock;
			(*ppFileStack)->nREPTBlockSize = nCurrentREPTBlockSize;
			(*ppFileStack)->nREPTBlockCount =
			    nCurrentREPTBlockCount;
			break;
		}
		nLineNo = 0;
	} else
		fatalerror("No memory for context");
}

int 
popcontext(void)
{
	struct sContext *pLastFile, **ppLastFile;

	if (nCurrentStatus == STAT_isREPTBlock) {
		if (--nCurrentREPTBlockCount) {
			yy_delete_buffer(CurrentFlexHandle);
			CurrentFlexHandle =
			    yy_scan_bytes(pCurrentREPTBlock,
			    nCurrentREPTBlockSize);
			yy_switch_to_buffer(CurrentFlexHandle);
			sym_UseCurrentMacroArgs();
			sym_SetMacroArgID(nMacroCount++);
			sym_UseNewMacroArgs();
			return (0);
		}
	}
	if ((pLastFile = pFileStack) != NULL) {
		ppLastFile = &pFileStack;
		while (pLastFile->pNext) {
			ppLastFile = &(pLastFile->pNext);
			pLastFile = *ppLastFile;
		}

		yy_delete_buffer(CurrentFlexHandle);
		nLineNo = pLastFile->nLine;
		if (nCurrentStatus == STAT_isInclude)
			fclose(pCurrentFile);
		if (nCurrentStatus == STAT_isMacro) {
			sym_FreeCurrentMacroArgs();
			nLineNo += 1;
		}
		if (nCurrentStatus == STAT_isREPTBlock)
			nLineNo += 1;

		CurrentFlexHandle = pLastFile->FlexHandle;
		tzCurrentFileName = pLastFile->tzFileName;
		switch (nCurrentStatus = pLastFile->nStatus) {
		case STAT_isMacroArg:
		case STAT_isMacro:
			sym_RestoreCurrentMacroArgs(pLastFile->tzMacroArgs);
			pCurrentMacro = pLastFile->pMacro;
			break;
		case STAT_isInclude:
			pCurrentFile = pLastFile->pFile;
			break;
		case STAT_isREPTBlock:
			sym_RestoreCurrentMacroArgs(pLastFile->tzMacroArgs);
			pCurrentREPTBlock = pLastFile->pREPTBlock;
			nCurrentREPTBlockSize = pLastFile->nREPTBlockSize;
			nCurrentREPTBlockCount = pLastFile->nREPTBlockCount;
			break;
		}

		free(*ppLastFile);
		*ppLastFile = NULL;
		yy_switch_to_buffer(CurrentFlexHandle);
		return (0);
	} else
		return (1);
}

int 
yywrap(void)
{
	return (popcontext());
}
/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * Dump the context stack to stderr
 *
 */

void 
fstk_Dump(void)
{
	struct sContext *pLastFile;

	pLastFile = pFileStack;

	while (pLastFile) {
		fprintf(stderr, "%s(%ld) -> ", pLastFile->tzFileName,
		    pLastFile->nLine);
		pLastFile = pLastFile->pNext;
	}

	fprintf(stderr, "%s(%ld)", tzCurrentFileName, nLineNo);
}
/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * Extra includepath stuff
 *
 */

void 
fstk_AddIncludePath(char *s)
{
	strcpy(IncludePaths[NextIncPath++], s);
}

FILE *
fstk_FindFile(char *fname)
{
	char path[PATH_MAX];
	int i;
	FILE *f;

	if ((f = fopen(fname, "rb")) != NULL || errno != ENOENT) {
		return f;
	}

	for (i = 0; i < NextIncPath; ++i) {
		if (strlcpy(path, IncludePaths[i], sizeof path) >= 
		    sizeof path) {
			continue;
		}
		if (strlcat(path, fname, sizeof path) >= sizeof path) {
			continue;
		}

		if ((f = fopen(path, "rb")) != NULL || errno != ENOENT) {
			return f;
		}
	}

	errno = ENOENT;
	return NULL;
}
/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * Set up an include file for parsing
 *
 */

void
fstk_RunInclude(char *tzFileName)
{
	FILE *f;

	f = fstk_FindFile(tzFileName);

	if (f == NULL) {
		fprintf(stderr, "Unable to open included file '%s': ",
		    tzFileName);
		perror(NULL);
		exit(1);
	}

	pushcontext();
	nLineNo = 1;
	nCurrentStatus = STAT_isInclude;
	tzCurrentFileName = tzFileName;
	pCurrentFile = f;
	CurrentFlexHandle = yy_create_buffer(pCurrentFile);
	yy_switch_to_buffer(CurrentFlexHandle);

	//Dirty hack to give the INCLUDE directive a linefeed

	yyunput('\n');
	nLineNo -= 1;
}
/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * Set up a macro for parsing
 *
 */

ULONG 
fstk_RunMacro(char *s)
{
	struct sSymbol *sym;

	if ((sym = sym_FindMacro(s)) != NULL) {
		pushcontext();
		sym_SetMacroArgID(nMacroCount++);
		nLineNo = -1;
		sym_UseNewMacroArgs();
		nCurrentStatus = STAT_isMacro;
		tzCurrentFileName = s;
		pCurrentMacro = sym;
		CurrentFlexHandle =
		    yy_scan_bytes(pCurrentMacro->pMacro,
		    pCurrentMacro->ulMacroSize);
		yy_switch_to_buffer(CurrentFlexHandle);
		return (1);
	} else
		return (0);
}

/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * Set up a stringequate for parsing
 *
 */

void 
fstk_RunString(char *s)
{
	struct sSymbol *pSym;

	if ((pSym = sym_FindSymbol(s)) != NULL) {
		pushcontext();
		nCurrentStatus = STAT_isMacroArg;
		tzCurrentFileName = s;
		CurrentFlexHandle =
		    yy_scan_bytes(pSym->pMacro, strlen(pSym->pMacro));
		yy_switch_to_buffer(CurrentFlexHandle);
	} else
		yyerror("No such string symbol '%s'", s);
}
/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * Set up a repeat block for parsing
 *
 */

void 
fstk_RunRept(ULONG count)
{
	if (count) {
		pushcontext();
		sym_UseCurrentMacroArgs();
		sym_SetMacroArgID(nMacroCount++);
		sym_UseNewMacroArgs();
		nCurrentREPTBlockCount = count;
		nCurrentStatus = STAT_isREPTBlock;
		nCurrentREPTBlockSize = ulNewMacroSize;
		pCurrentREPTBlock = tzNewMacro;
		CurrentFlexHandle =
		    yy_scan_bytes(pCurrentREPTBlock, nCurrentREPTBlockSize);
		yy_switch_to_buffer(CurrentFlexHandle);
	}
}
/*
 * RGBAsm - FSTACK.C (FileStack routines)
 *
 * Initialize the filestack routines
 *
 */

void
fstk_Init(char *s)
{
	char tzFileName[_MAX_PATH + 1];

	sym_AddString("__FILE__", s);

	strcpy(tzFileName, s);
	pFileStack = NULL;
	pCurrentFile = fopen(tzFileName, "rb");
	if (pCurrentFile == NULL) {
		fprintf(stderr, "Unable to open file '%s': ",
		    tzFileName);
		perror(NULL);
		exit(1);
	}

	nMacroCount = 0;
	nCurrentStatus = STAT_isInclude;
	tzCurrentFileName = tzFileName;
	CurrentFlexHandle = yy_create_buffer(pCurrentFile);
	yy_switch_to_buffer(CurrentFlexHandle);
	nLineNo = 1;
}