/*
 *	File:					GenerateCSource.c
 *	Description:	
 *
 *	(C) 1995, Ketil Hunn
 *
 */

#ifndef GENERATECSOURCE_C
#define GENERATECSOURCE_C

/*** PRIVATE INCLUDES ****************************************************************/
#include "System.h"
#include "GenerateCSource.h"
#include "TASK_Code.h"

/*** FUNCTIONS ***********************************************************************/
void WriteCArguments(BPTR fp, struct List *list)
{
	register struct Node *node;

#ifdef MYDEBUG_H
	DebugOut("WriteArguments");
#endif

	Write(fp, "\"", 1);
	for(every_node)
	{
		Write(fp, node->ln_Name, strlen(node->ln_Name));
		if(node!=list->lh_TailPred)
			Write(fp, ",", 1);
	}
	Write(fp, "\",", 1);
}

void GenerateCSource(struct List *list, UBYTE *filename)
{
	BPTR fp;
	register struct Node *node;

#ifdef MYDEBUG_H
	DebugOut("GenerateCSource");
#endif

	if(fp=Open(filename, MODE_NEWFILE))
	{
		/*** Intro **********************************************************************/
		{
			register UBYTE intro[]=	"/*\n"
															"** Source machine generated by the ARexx Interface Designer for EasyRexx\n"
															"** which is (c) 1994, 1995 to Ketil Hunn\n"
															"**\n"
															"*/\n\n"
															"#ifndef AREXX_INTERFACE\n"
															"#define AREXX_INTERFACE\n\n"
															"#include <libraries/easyrexx.h>\n"
															"struct Library *EasyRexxBase=NULL;\n\n";
			Write(fp, intro, strlen(intro));
		}

		/*** Defines ********************************************************************/
		{
			register ULONG i=0;
			register UBYTE define[MAXNAMELEN+100];

			for(every_node)
			{
				sprintf(define, "#define AREXX_%s		%ld\n", node->ln_Name, ++i);
				Write(fp, define, strlen(define));
			}
			Write(fp, "\n", 1);
		}

		/*** Prototypes *****************************************************************/
		if(code.handle==HANDLE_FUNCS)
		{
			register UBYTE template[MAXNAMELEN+100];

			for(every_node)
			{
				sprintf(template, "LONG arexxfunc%s(struct ARexxContext *c);\n", node->ln_Name);
				Write(fp, template, strlen(template));
			}
			Write(fp, "\n", 1);
		}

		/*** Context ********************************************************************/
		{
			register UBYTE	context[]		="struct ARexxCommandTable commandTable[]=\n{\n",
											endcontext[]="  TABLE_END,\n};\n\n",
											data[]			=",	NULL,\n",
											command[MAXNAMELEN*2+50];

			Write(fp, context, strlen(context));
			for(every_node)
			{
				sprintf(command, "  AREXX_%s,	\"%s\",	", node->ln_Name, node->ln_Name);
				Write(fp, command, strlen(command));
				WriteCArguments(fp, ((struct CommandNode *)node)->argumentlist);

				if(code.handle==HANDLE_FUNCS)
				{
					register UBYTE func[MAXNAMELEN+50];

					sprintf(func, ",	(APTR)arexxfunc%s,\n", node->ln_Name);
					Write(fp, func, strlen(func));
				}
				else
					Write(fp, data, strlen(data));
			}
			Write(fp, endcontext, strlen(endcontext));
		}

		/*** MyReturn structure *********************************************************/
		if(code.handle==HANDLE_FUNCS)
		{
			register UBYTE retvals[]=	"struct ARexxRetValues\n"
																"{\n"
																"  LONG  result,\n"
																"        resultlong;\n"
																"  UBYTE *resultstring,\n"
																"        *error;\n"
																"} myreturn;\n\n\n";

			Write(fp, retvals, strlen(retvals));
		}

		/*** Function templates *********************************************************/
		if(code.handle==HANDLE_FUNCS && code.templates)
		{
			register UBYTE template[MAXNAMELEN+200];

			for(every_node)
			{
				BYTE quit=(Stricmp(node->ln_Name, "QUIT")==0);
				sprintf(template, "BYTE arexxfunc%s(struct ARexxContext *c)\n"
													"{\n"
													"  /* insert own code here */\n"
													"  return %s\n"
													"}\n\n",
													node->ln_Name,
													quit ? "1; /* Quit */":"0;");
				Write(fp, template, strlen(template));
			}
		}

		/*** ARexx handler **************************************************************/
		if(code.arexxhandler)
			switch(code.handle)
			{
				case HANDLE_IDS:
					{
						register UBYTE	start[]="BYTE myHandleARexx(struct ARexxContext *c)\n"
																		"{\n"
																		"  BYTE  done          =FALSE;\n"
																		"  LONG  result        =RC_OK,\n"
																		"        resultlong    =~0;\n"
																		"  UBYTE *resultstring =NULL,\n"
																		"        *error        =NULL;\n\n"
																		" while(GetARexxMsg(c))\n"
																		" {\n"
																		"   switch(c->id)\n"
																		"   {\n",
														end[]=	"   }\n"
																		"   ReplyARexxMsg(c,\n"
																		"                 ER_ReturnCode,    result,\n"
																		"                 (resultstring   ? ER_ResultString :TAG_IGNORE), resultstring,\n"
																		"                 (resultlong!=~0 ? ER_ResultLong   :TAG_IGNORE), resultlong,\n"
																		"                 (error          ? ER_ErrorMessage :TAG_IGNORE), error,\n"
																		"                 TAG_DONE);\n"
																		" }\n"
																		" return done;\n"
																		"}\n\n",
													donestr[]="       done=TRUE;\n",
												breakstr[]=	"       break;\n";

						Write(fp, start, strlen(start));
						for(every_node)
						{
							UBYTE command[MAXNAMELEN+100], done=(0==Stricmp(node->ln_Name, "QUIT"));

							sprintf(command,	"     case AREXX_%s:\n"
																"       /* insert own code here */\n",
																node->ln_Name);
							Write(fp, command, strlen(command));
							if(done)
								Write(fp, donestr, strlen(donestr));
							Write(fp, breakstr, strlen(breakstr));
						}
						Write(fp, end, strlen(end));
					}
					break;

				case HANDLE_FUNCS:
					{
						register UBYTE funchandler[]=	"LONG myHandleARexx(struct ARexxContext *c)\n"
																					"{\n"
																					"  BYTE done=FALSE;\n\n"
																					"  myreturn.result       =RC_OK;\n"
																					"  myreturn.resultstring =NULL;\n"
																					"  myreturn.resultlong   =~0';\n"
																					"  myreturn.error        =NULL;\n\n"
																					"  while(GetARexxMsg(c))\n"
																					"  {\n"
																					"    register ULONG i=0L;\n\n"
																					"    while(c->table[i].command)\n"
																					"    {\n"
																					"      if(c->table[i].id==c->id)\n"
																					"      {\n"
																					"        ARexxFunc func;\n"
																					"        if(func=(ARexxFunc)(c->table[i].userdata))\n"
																					"          done=func(c);\n"
																					"        break;\n"
																					"      }\n"
																					"      else\n"
																					"        ++i;\n"
																					"    }\n"
																					"    ReplyARexxMsg(c,\n"
																					"                  ER_ReturnCode,             myreturn.result,\n"
																					"                  (myreturn.resultstring   ? ER_ResultString :TAG_IGNORE), myreturn.resultstring,\n"
																					"                  (myreturn.resultlong!=~0 ? ER_ResultLong   :TAG_IGNORE), myreturn.resultlong,\n"
																					"                  (myreturn.error          ? ER_ErrorMessage :TAG_IGNORE), myreturn.error,\n"
																					"                  TAG_DONE);\n"
																					"  }\n"
																					"  return done;\n"
																					"}\n\n";
						Write(fp, funchandler, strlen(funchandler));
					}
					break;
			}

		/*** Main code ******************************************************************/
		if(code.main)
		{
			register UBYTE	start[]="void main(void)\n"
															"{\n"
															"  BYTE done=FALSE;\n"
															"  struct ARexxContext *context=NULL;\n\n"
															"  if(EasyRexxBase=OpenLibrary((UBYTE *)EASYREXXNAME, (ULONG)EASYREXXVERSION))\n"
															"    context=AllocARexxContext(ER_CommandTable, commandTable,\n",
										contags[]="                              ER_Author,      \"%s\",\n"
															"                              ER_Copyright,   \"%s\",\n"
															"                              ER_Version,     \"%s\",\n"
															"                              ER_Portname,    \"%s\",\n"
															"                              TAG_DONE);\n",
											end[]=	"  while(done==FALSE | ER_SAFETOQUIT(context)==FALSE)\n"
															"  {\n"
															"    ULONG signals=Wait(ER_SIGNAL(context));\n"
															"    ER_SETSIGNALS(context, signals);\n\n"
															"    if(signals & ER_SIGNAL(context))\n"
															"      done=myHandleARexx(context);\n"
															"  }\n"
															"  if(EasyRexxBase)\n"
															"  {\n"
															"    FreeARexxContext(context);\n"
															"    CloseLibrary(EasyRexxBase);\n"
															"  }\n"
															"}\n"
															"#endif\n",
										tags[MAXDATALEN*4+200];

			Write(fp, start, strlen(start));
			sprintf(tags, contags, code.author, code.copyright, code.version, code.portname);
			Write(fp, tags, strlen(tags));
			Write(fp, end, strlen(end));
		}
		Close(fp);
	}
}

#endif
