/* preprocess.c */
#include "ctype.h"
#include "error.h"
#include "lex.h"
#include "parse.h"
#include "preprocess.h"
#include "stdlib.h"
#include "vars.h"

/*	>>>>>> start of cc4 <<<<<<<	*/
/** macro line buffer used to hold temps also **/
char keepch(char c)
{
	mline[mptr] = c;
	if (mptr < MP_MAX)
		mptr++;
	return c;
}

/** space or tab chr compression **/
/** quoted string handler **/
/** char constant handler **/
/** comments handler **/
/** macro substitution **/
void preprocess()
{
	int k;
	char c, sname[NAMESIZE];

	if (cmode == 0)
		return;						/** ck preprocess flg **/
	mptr = lptr = 0;       					/** reset static ptrs **/
	while (inspect_chr())
	{
		if ((inspect_chr() == ' ') | (inspect_chr() == 9))
		{
			/** space or tab chr compression **/
			keepch(' ');				/** keep one space, compact the rest **/
			while ((inspect_chr() == ' ') | (inspect_chr() == 9))
				g_nxtchr();			/** rets chr or null at line[lptr] **/
		}
		else if (inspect_chr() == '"')
		{
			/** quoted string into macro buffer **/
			keepch(inspect_chr());			/** copy into mline **/
			g_nxtchr();
			while (inspect_chr() != '"')
			{
				if (inspect_chr() == 0)
				{
					error("missing quote");
					break;
				}
				keepch(g_nxtchr());
			}
			g_nxtchr();
			keepch('"');				/** copy into mline **/
		}
		else if (inspect_chr() == 39)
		{
			/** 39d is single quote, apostrophe **/
			keepch(39);
			g_nxtchr();
			while (inspect_chr() != 39)
			{
				if (inspect_chr() == 0)
				{
					error("missing apostrophe");
					break;
				}
				keepch(g_nxtchr());
			}
			g_nxtchr();
			keepch(39);				/** cpy into mline **/
		}
		else if ((inspect_chr() == '/') & (lookahead() == '*'))
		{
			/** comments, like this one **/
			inchar();
			inchar();
			while (((inspect_chr() == '*') & (lookahead() == '/')) == 0)
			{
				if (inspect_chr() == 0)
					input_line();
				else
					inchar();
				if (eof_flg)
					break;
			}
			inchar();
			inchar();
		}
		else if (an(inspect_chr()))
		{
			/** macro substitution by lookup is done here **/
			k = 0;
			while (an(inspect_chr()))
			{
				/** copy token **/
				if (k < NAMEMAX)
					sname[k++] = inspect_chr();
				
				/** advance thru line[] **/
				g_nxtchr();
			}
			
			/** append null to extracted token **/
			sname[k] = 0;
			if (k = findmac(sname))			/** token is macr defined **/
				while (c = macq[k++]) keepch(c)
					;			/** cpy into mline **/
			else
			{
				/** ordinary token is copied without substitution **/
				k = 0;
				while (c = sname[k++])
					keepch(c);		/** cpy into mline **/
			}
		}
		else
			keepch(g_nxtchr());			/** cpy into mline **/
	}
	
	/** null terminate token placed into mline[] **/
	keepch(0);
	
	if (mptr >= MP_MAX)
		error("line too long");
	
	lptr = mptr = 0;
	
	while (line[lptr++] = mline[mptr++])
		;						/** do the substitution **/
	lptr = 0;
}

void addmac()
{
	char sname[NAMESIZE];
	int k;

	if (is_identifier(sname) == 0)
	{
		/** is_identifier() gets & validates identifier **/
		illname();
		kill();
		return;
	}
	k = 0;
	while (putmac(sname[k++]))
		;
	while (inspect_chr() == ' ' | inspect_chr() == 9)
		g_nxtchr();
	while (putmac(g_nxtchr()))
		;
	if (macptr >= MAC_MAX)
		error("macro table full");
}

char putmac(char c)
{
	macq[macptr] = c;
	if (macptr < MAC_MAX)
		macptr++;
	return c;
}

int findmac(char* sname)
{
	int k;

	k = 0;
	while (k < macptr)
	{
		if(astreq(sname, macq + k, NAMEMAX))
		{
			while (macq[k++])
				;
			return k;
		}
		while (macq[k++])
			;
		while (macq[k++])
			;
	}
	return 0;
}