/*
 * cpp.c -- support for generating C++ output
 *
 * SOFTWARE RIGHTS
 *
 * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public
 * domain.  An individual or company may do whatever they wish with
 * source code distributed with SORCERER or the code generated by
 * SORCERER, including the incorporation of SORCERER, or its output, into
 * commerical software.
 *
 * We encourage users to develop software with SORCERER.  However, we do
 * ask that credit is given to us for developing SORCERER.  By "credit",
 * we mean that if you incorporate our source code into one of your
 * programs (commercial product, research project, or otherwise) that you
 * acknowledge this fact somewhere in the documentation, research report,
 * etc...  If you like SORCERER and have developed a nice tool with the
 * output, please mention that you developed it using SORCERER.  In
 * addition, we ask that this header remain intact in our source code.
 * As long as these guidelines are kept, we expect to continue enhancing
 * this system and expect to make other tools available as they are
 * completed.
 *
 * SORCERER 1.00B
 * Terence Parr
 * AHPCRC, University of Minnesota
 * 1992-2001
 */
#include "stdpccts.h"
#include "sym.h"
#include "pcctscfg.h"
#include "proto.h"

void GenCPPClassHeader()
{
	FILE *Parser_h;
	char CPPParser_h_Name[MaxFileName+1];
	
	strcpy(CPPParser_h_Name, CurClassName);
	strcat(CPPParser_h_Name, ".h");
	Parser_h = fopen(OutMetaName(CPPParser_h_Name), "w");
	require(Parser_h != NULL, "can't open parser.h file");
#ifdef SPECIAL_FOPEN
       special_fopen_actions(OutMetaName(CPPParser_h_Name));
#endif

	/* Put a gate on the header file */
	fprintf(Parser_h, "#ifndef %s_h\n", CurClassName);
	fprintf(Parser_h, "#define %s_h\n", CurClassName);

	gen_info_hdr(Parser_h);

	fprintf(Parser_h, "#include \"%s\"\n", STPARSER_H);

	if ( header_action!=NULL )
		dumpAction(header_action, Parser_h, 0, -1, 0, 1);

	fprintf(Parser_h, "\n");
	fprintf(Parser_h, "class %s : public STreeParser {\n", CurClassName);
	fprintf(Parser_h, "protected:\n");
	/* Define @-vars in class */
	if ( AllRefVars!=NULL )
	{
		ListNode *p;
		for (p = AllRefVars->next; p!=NULL; p=p->next)
		{
			RefVarRec *r = (RefVarRec *)p->elem;
			fprintf(Parser_h, "\t%s;\n", r->decl);
		}
	}
	/* Generate list of tokens if demanded */
	if ( def_tokens )
	{
		ListNode *p;
		fprintf(Parser_h, "public:\n");
		fprintf(Parser_h, "\tenum STokenType {\n");
		for (p = token_list->next; p!=NULL; p=p->next)
		{
			SymEntry *t = (SymEntry *) p->elem;
			fprintf(Parser_h,
					"\t\t%s=%d", t->str, t->token_type);
			if ( p->next!=NULL ) fprintf(Parser_h, ",\n");
			else fprintf(Parser_h, "\n");
		}
		fprintf(Parser_h, "\t};\n");
	}
	fprintf(Parser_h, "public:\n");
	if (NoCtor) { /* MR23 */
		fprintf(Parser_h, "#if 0\n");
		fprintf(Parser_h, "\t// The default ctor has been suppressed\n\t// by the -noctor option.\n\n");
	}
	fprintf(Parser_h, "	%s();\n", CurClassName);
	if (NoCtor) { /* MR23 */
		fprintf(Parser_h, "#endif\n");
	}
/*	fprintf(Parser_h, "	virtual AST *ast_node(int, char *) {return NULL;}\n");*/
	fprintf(Parser_h, "\n");
	GenRulePrototypes( Parser_h, 1 );

	if ( class_actions != NULL )
	{
		ListNode *p;
		for (p = class_actions->next; p!=NULL; p=p->next)
	    dumpAction( (char *)p->elem, output, 1, -1, 0, 1);
	}

	fprintf(Parser_h, "};\n");

	fprintf(Parser_h, "\n#endif /* %s_h */\n", CurClassName);
	fclose(Parser_h);
}

void GenCPPClassCode()
{
	FILE *Parser_c;
	char CPPParser_C_Name[MaxFileName+1];
	
	strcpy(CPPParser_C_Name, CurClassName);
	strcat(CPPParser_C_Name, CPP_FILE_SUFFIX);
	ensure_no_C_file_collisions(CPPParser_C_Name);
	Parser_c = fopen(OutMetaName(CPPParser_C_Name), "w");
	require(Parser_c != NULL, "can't open class Parserx.c file");
#ifdef SPECIAL_FOPEN
       special_fopen_actions(OutMetaName(CPPParser_C_Name));
#endif

	gen_info_hdr(Parser_c);
	fprintf(Parser_c, "#include \"%s.h\"\n\n", CurClassName);

	if (NoCtor) { /* MR23 */
		fprintf(Parser_c, "#if 0\n\n");
		fprintf(Parser_c, "\t// The default ctor has been suppressed\n\t// by the -noctor option.\n\n");
	}

	/* Build constructor (init @-vars) */
	fprintf(Parser_c, "%s::%s()\n{\n", CurClassName, CurClassName);
	if ( AllRefVars!=NULL )
	{
		ListNode *p;
		for (p = AllRefVars->next; p!=NULL; p=p->next)
		{
			RefVarRec *r = (RefVarRec *)p->elem;
			if ( r->init[0]!='\0' )
				fprintf(Parser_c, "\t%s=%s;\n", r->var, r->init);
		}
	}
	fprintf(Parser_c, "}\n\n");

	if (NoCtor) { /* MR23 */
		fprintf(Parser_c, "#endif\n\n");
	}
	fclose(Parser_c);
}
