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

#ifndef GENERATEESOURCE_C
#define GENERATEESOURCE_C

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

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

#ifdef MYDEBUG_H
	DebugOut("WriteEArguments");
#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 GenerateESource(struct List *list, UBYTE *filename)
{
	BPTR fp;
	register struct Node *node;

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

	if(fp=Open(filename, MODE_NEWFILE))
	{
		/*** Intro **********************************************************************/
		{
			register UBYTE	intro[]="-> Source machine generated by the ARexx Interface Designer for EasyRexx\n"
															"-> which is (c) 1994, 1995 to Ketil Hunn\n\n"
															"OPT PREPROCESS\n\n"
															"MODULE 'intuition/intuition'\n"
															"MODULE 'utility/tagitem'\n"
															"MODULE 'rexx/errors'\n"
															"MODULE 'exec/ports'\n"
															"MODULE 'easyrexx'\n"
															"MODULE 'libraries/easyrexx'\n"
															"MODULE 'libraries/easyrexx_macros'\n\n"
															"CONST MAXLONG=2147483647\n\n";
			Write(fp, intro, strlen(intro));
		}

		/*** Defines ********************************************************************/
		{
			register UBYTE define[MAXNAMELEN+100];

			Write(fp, "ENUM\n", 5);
			for(every_node)
			{
				if(node==list->lh_Head)
					sprintf(define, "  AREXX_%s=1,\n", node->ln_Name);
				else
					sprintf(define, "  AREXX_%s%s\n",
													node->ln_Name,
													(node==list->lh_TailPred ? "\n":","));
				Write(fp, define, strlen(define));
			}
		}

		/*** MyReturn structure *********************************************************/
		if(code.handle==HANDLE_FUNCS)
		{
			register UBYTE retvals[]=	"OBJECT arexxretvalues\n"
																"  result       :LONG\n"
																"  resultlong   :LONG\n"
																"  resultstring :PTR TO CHAR\n"
																"  error        :PTR TO CHAR\n"
																"ENDOBJECT\n\n"
																"DEF myreturn:arexxretvalues\n\n";
			Write(fp, retvals, strlen(retvals));
		}

		/*** Context predefinition ******************************************************/
		{
			register UBYTE	start[]	="DEF commandtable=NIL:PTR TO arexxcommandtable\n\n";

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

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

			for(every_node)
			{
				register BYTE quit=(Stricmp(node->ln_Name, "QUIT")==0);

				sprintf(template, "PROC arexxfunc%s(c:PTR TO arexxcontext)\n"
													"  -> insert own code here\n"
													"ENDPROC %s\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	handlerstart[]=	"PROC myHandleARexx(c:PTR TO arexxcontext)\n"
																						"  DEF done=FALSE, id\n"
																						"  DEF result=NIL, resultstring=NIL, error=NIL\n"
																						"  DEF resultlong=MAXLONG\n\n"
																						"  WHILE GetARexxMsg(c)\n"
																						"    c:=c.id\n"
																						"    SELECT id\n",
														handlerend[]=		"    ENDSELECT\n"
																						"    ReplyARexxMsgA(c, [ER_ReturnCode,         result,\n"
																						"                       IF resultstring        THEN ER_ResultString ELSE TAG_IGNORE, resultstring,\n"
																						"                       IF resultlong<>MAXLONG THEN ER_ResultLong   ELSE TAG_IGNORE, resultlong,\n"
																						"                       IF error               THEN ER_ErrorMessage ELSE TAG_IGNORE, error,\n"
																						"                       TAG_DONE])\n"
																						"  ENDWHILE\n"
																						"ENDPROC done\n\n",
														donestr[]=			"        done:=TRUE;\n";
						Write(fp, handlerstart, strlen(handlerstart));

						for(every_node)
						{
							register 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, handlerend, strlen(handlerend));
					}
					break;

				case HANDLE_FUNCS:
					{
						register UBYTE funchandler[]	="PROC myHandleARexx(c:PTR TO arexxcontext)\n"
																					"  DEF id=0, i=0, done=FALSE, function=NIL\n\n"
																					"  myreturn.result      :=RC_OK\n"
																					"  myreturn.resultlong  :=MAXLONG\n"
																					"  myreturn.resultstring:=NIL\n"
																					"  myreturn.error       :=NIL\n\n"
																					"  IF GetARexxMsg(c)\n"
																					"    WHILE (c.table[i].command<>NIL) AND (function<>NIL)\n"
																					"      IF c.table[i].id=c.id\n"
																					"        IF function:=c.table[i].userdata\n"
																					"          done:=function(c)\n"
																					"        ELSE\n"
																					"          function:=TRUE\n"
																					"      ENDIF\n"
																					"    ELSE\n"
																					"      INC i\n"
																					"    ENDIF\n"
																					"  ENDWHILE\n"
																					"  ReplyARexxMsgA(c, [ER_ReturnCode,                  myreturn.result,\n"
																					"                     IF myreturn.error               THEN ER_ErrorMessage ELSE TAG_IGNORE, myreturn.error,\n"
																					"                     IF myreturn.resultstring        THEN ER_ResultString ELSE TAG_IGNORE, myreturn.resultstring,\n"
																					"                     IF myreturn.resultlong<>MAXLONG THEN ER_ResultLong   ELSE TAG_IGNORE, myreturn.resultlong,\n"
																					"                     TAG_DONE])\n"
																					"  ENDIF\n"
																					"ENDPROC done\n\n";
						Write(fp, funchandler, strlen(funchandler));
					}
					break;
			}

		/*** Context ********************************************************************/
		{
			register UBYTE	start[]="PROC initCommandTable()\n"
															"  commandtable:=[",
											pads[]=	"                 ",
											end[]=	"                 TABLE_END\n"
															"                ]:arexxcommandtable\n"
															"ENDPROC\n\n",
											data[]=	",	NIL,\n",
											command[MAXNAMELEN*2+50];

			Write(fp, start, strlen(start));
			for(every_node)
			{
				if(node!=list->lh_Head)
					Write(fp, pads, strlen(pads));
				sprintf(command, "AREXX_%s,	'%s',	", node->ln_Name, node->ln_Name);
				Write(fp, command, strlen(command));
				WriteEArguments(fp, ((struct CommandNode *)node)->argumentlist);

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

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

		/*** Main code ******************************************************************/
		if(code.main)
		{
			register UBYTE	start[]=	"PROC main()\n"
																"  DEF done=0\n"
																"  DEF context=NIL:PTR TO arexxcontext, signals=0\n\n"
																"  IF easyrexxbase:=OpenLibrary(EASYREXXNAME, EASYREXXVERSION)\n"
																"    initCommandTable()\n"
																"    context:=AllocARexxContextA([ER_CommandTable, commandtable,\n",
											contags[]="                                 ER_Author,       '%s',\n"
																"                                 ER_Copyright,    '%s',\n"
																"                                 ER_Version,      '%s',\n"
																"                                 ER_Portname,     '%s',\n",
											end[]=		"                                 TAG_DONE])\n"
																"  ENDIF\n"
																"  WHILE (done=0) OR (ER_SAFETOQUIT(context)=FALSE)\n"
																"    signals:=Wait(ER_SIGNAL(context))\n"
																"    ER_SETSIGNALS(context, signals)\n\n"
																"    IF (signals AND ER_SIGNAL(context))\n"
																"      done:=myHandleARexx(context)\n"
																"    ENDIF\n"
																"  ENDWHILE\n"
																"  IF easyrexxbase\n"
																"    FreeARexxContext(context)\n"
																"    CloseLibrary(easyrexxbase)\n"
																"  ENDIF\n"
																"ENDPROC\n",
											tags[MAXDATALEN+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
