/*
 * Copyright 2000 Silicon Graphics, Inc. All rights reserved.
 */

#include <stdio.h>
#include "sial.h"
#include "sial.tab.h"
/*
	This utility generates a operator function table for the base type.
	Each combinaison of operand type and operation needs a dedicated
	function. We use a table defined here in to generate an indirect table
	that if indexed (from within sial_op.c) using :

	value_t * (func)(value_t *v1, value_t *v2) = table[type1][type2][op];
*/
static struct opss {
	char *str;
	char *acro;
	int code;
} opstbl[] = {
	{ "+", "ADD", ADD },
        { "-", "SUB", SUB },
        { "/", "DIV", DIV },
        { "*", "MUL", MUL },
        { "^", "XOR", XOR },
        { "%", "MOD", MOD },
        { "|", "OR",  OR  },
        { "&", "AND", AND },
	{ "<<", "SHL", SHL },
	{ ">>", "SHR", SHR },
	{ "==", "EQ", EQ }, /* most be first bool */
	{ ">", "GT", GT },
	{ "<", "LT", LT },
	{ ">=", "GE", GE },
	{ "<=", "LE", LE },
	{ "!=", "NE", NE },
};

static char *typtbl[] = { "sc", "uc", "ss", "us", "sl", "ul", "sll", "ull" };

#define NOPS (sizeof(opstbl)/sizeof(opstbl[0]))
#define NTYPS (sizeof(typtbl)/sizeof(typtbl[0]))

int
main()
{
int i,j,k;

	printf("\
#include \"sial.h\"\n\
#include \"sial.tab.h\"\n\
/**************************************************************\n\
 This file is generated by a program. Do not modify it!\n\
***************************************************************/\n");


	/* create all the functions for all combinaison */
	for(i=0;i<NTYPS;i++) {
	
		for(j=0; j<NTYPS;j++) {

			int bool=0;

			for(k=0;k<NOPS;k++) {

				if(opstbl[k].code==EQ) bool++;


				if(!bool) {

					printf(""
"static void \n"
"op_%s_%s_%s(value_t *v1,value_t *v2,value_t *ret)\n"
"{\n"
"	ret->v.%s = v1->v.%s %s v2->v.%s;\n"
"	ret->type.type=%s->type.type;\n"
"	ret->type.idx=%s->type.idx;\n"
"	ret->type.size=%s->type.size;\n"
"}\n", 
					opstbl[k].acro, 
					typtbl[i], 
					typtbl[j], 
					j>=i?typtbl[j]:typtbl[i], 
					typtbl[i], 
					opstbl[k].str,
					typtbl[j],
					j>=i?"v2":"v1",
					j>=i?"v2":"v1",
					j>=i?"v2":"v1");

				} else {

					printf(""
"static void \n"
"op_%s_%s_%s(value_t *v1,value_t *v2,value_t *ret)\n"
"{\n"
"	ret->v.%s = ( v1->v.%s %s v2->v.%s );\n"
"	ret->type.type=V_BASE;\n"
"	ret->type.idx=B_UL;\n"
"	ret->type.size=4;\n"
"}\n",
					opstbl[k].acro, 
					typtbl[i], 
					typtbl[j], 
					"ul",
					typtbl[i], 
					opstbl[k].str,
					typtbl[j]);
				}

			}

		}

	}

	/* create the array from within which the runtime functions
	   will indexed to get a function pointer */

	printf("void (*opfuncs[%d][%d][%d])()={\n", NTYPS, NTYPS, NOPS);

	for(i=0;i<NTYPS;i++) {
	
		for(j=0; j<NTYPS;j++) {

			printf("\t");

			for(k=0;k<NOPS;k++) {

				if(!k%6) printf("\n\t");
				printf("op_%s_%s_%s, ", opstbl[k].acro, typtbl[i], typtbl[j]);

			}
			printf("\n");

		}

	}
	printf("};\n");

	/* output a ops lut */
	printf("\nstatic int opslut[%d]={\n", NOPS);

	for(i=0;i<NOPS;i++) {

		printf("%s, ", opstbl[i].acro);

	}
	printf("};\n");

	/* output the main op execution function */
	printf("\n\
void\n\
sial_baseop(int op, value_t *v1, value_t *v2, value_t *ret)\n\
{\n\
int i;\n\
\n\
	for(i=0;i<%d;i++) {\n\
\n\
		if(opslut[i]==op) break;\n\
\n\
	}\n\
	if(i==%d) sial_error(\"Oops!ops!\");\n\
	(opfuncs[v1->type.idx][v2->type.idx][i])(v1,v2,ret);\n\
}\n", NOPS, NOPS);
	exit(0);
}
