%{

#include <stdio.h>
#include "macstuff.h"

FILE *outputfile;
FILE *cfgfile;

yyerror(char *yymsg)
{
	fprintf(stderr,"Bison yyerror %s\n",yymsg);
}

extern void macdefine();
extern void macinit();
extern void maclist();
extern TOKEN *explodemacro();
extern MAC_NODE *maclookup();

extern int line_number;
extern FILE *yyin;

%}

%union {
	int	integer;
	char	string[256];
}

%token <integer> NUM
%token <integer> DOLLAR
%token <integer> NEWLINE
%token 		 MACRO
%token 		 ENDM
%token 		 COMMA
%token		 HASH
%token <string>  SYMBOL
%token <string>  ID
%token <string>  STRING
%token <string>  MAC_USE
%token		 CONFIG
%token		 CLOCK
%token <integer> OSC
%token <integer> FLAG
%token		 ID
%token		 PIC
%token		 CP
%token		 WDT
%token		 PWRUP
%token		 ENDCFG

%%

tokens	:	token
	|	tokens token
	;

arg	:	argtoken
	|	arg argtoken
	;

arglist	:	/* empty */
	|	arg
	;

argtoken:	NUM			{ macaddtoken(NUM, $1, "");	}
	|	DOLLAR			{ macaddtoken(DOLLAR, $1, "");	}
	|	COMMA			{ macaddtoken(COMMA, 0, "");	}
	|	SYMBOL			{ macaddtoken(SYMBOL, 0, $1);	}
	|	ID			{ macaddtoken(ID, 0, $1);	}
	|	STRING			{ macaddtoken(STRING, 0, $1);	}
	;

macrotokens:	mtoken
	|	macrotokens mtoken
	;

mtoken	:	NUM			{ macaddtoken(NUM, $1, "");	}
	|	NEWLINE			{ macaddtoken(NEWLINE, 0, "");	}
	|	DOLLAR			{ macaddtoken(DOLLAR, $1, "");	}
	|	COMMA			{ macaddtoken(COMMA, 0, "");	}
	|	SYMBOL			{ macaddtoken(SYMBOL, 0, $1);	}
	|	ID			{ macaddtoken(ID, 0, $1);	}
	|	STRING			{ macaddtoken(STRING, 0, $1);	}
	|	MAC_USE			{ macaddtoken(MAC_USE, 0, $1);	}
	;

nums	:	NUM			{}
	|	nums NUM		{}
	;

somenums:	/* nothing */		{}
	|	nums			{}
	;

cfgopt	:	HASH STRING		{ fprintf(cfgfile,"# %s\n",$2); }
	|	PIC  NUM		{ fprintf(cfgfile,"T%d\n", $2); }
	|	CLOCK OSC NUM		{ fprintf(cfgfile,"C%d %d\n", $2, $3); }
	|	WDT FLAG		{ fprintf(cfgfile,"W%d\n", $2); }
	|	CP FLAG			{ fprintf(cfgfile,"P%d\n", 1-($2)); /* note inversion */ }
	|	PWRUP FLAG		{ fprintf(cfgfile,"U%d\n", $2); }
	|	ID NUM NUM NUM NUM	{ fprintf(cfgfile,"I%04X %04X %04X %04X\n", $2, $3, $4, $5); }
	;

token	:	NUM			{ fprintf(outputfile,"%d ", $1);}
	|	NEWLINE			{ fprintf(outputfile,"#%d\n",$1);}
	|	COMMA			{ fprintf(outputfile,", ");	}
	|	SYMBOL			{ fprintf(outputfile,"%s ", $1);}
	|	ID			{ fprintf(outputfile,"%s ", $1);}
	|	STRING			{ fprintf(outputfile,"%s ", $1);}
	|	HASH NUM STRING		{ fprintf(outputfile,"-->%s\n",$3); line_number = $2; fprintf(outputfile,"#%d\n",line_number); }
		somenums NEWLINE
	|	MACRO ID		{ macdefine($2); }
		macrotokens
		ENDM			{ explodemacro($2); }
	|	MAC_USE			{ macuseddefine(); macaddtoken(MAC_USE, 0, $1);	}
		arglist
		NEWLINE			{ macaddtoken(NEWLINE, 0, ""); macusedoutput(outputfile); }
	|	CONFIG cfgopt ENDCFG
	;

%%

int main(int argc, char **argv)
{
	MAC_NODE *somemacro;

	if (argc != 4)
	{
		printf("\t%s <input filename> <output filename> <config file>\n",argv[0]);
		exit(1);
	}

	if((yyin=fopen(argv[1],"r"))==NULL)
	{
		printf("Cannot Open Inputfile %s\n",argv[2]);
		exit(1);
	}

	if((outputfile=fopen(argv[2],"w"))==NULL)
	{
		printf("Cannot Open Outputfile %s\n",argv[2]);
		exit(1);
	}

	if((cfgfile=fopen(argv[3],"w"))==NULL)
	{
		printf("Cannot Open Configfile %s\n",argv[3]);
		exit(1);
	}

	macinit();	/* initialise macro definitions */

	yyparse();

	fclose(outputfile);
	fclose(cfgfile);
}

/* ... The End ... */
