#include <bastard.h>


/* API sections:
 *    16. Macros					:: User-defined/recorded seer scripts
 */

/* NOTE: These functions are redundant with ones macro.c and should replace them */
/* ---------------------------------------------------------------Macros */
   int RunSeer( scScript script) {
   /* convenience function -- not exported in API */
   /* NOTE: script is freed for you -- the caller must not free it! */
      scInstance *inst;
      int retval;
   
      inst = scCreate_Instance(script, " ");
      if (scErrorNo || ! inst) {
         printf("SeerC Error %d while creating instance! %s:%s\n",
            scErrorNo, scErrorLine, scErrorMsg);
         return(SetLastError(4620));
      }
   /* this should be mod. to allow var_args -- but how to pass from
    * the call to this func to the call to seer w/o using inline asm?
    * TBD. */
      retval = scCall_Instance(inst, scGet_Symbol(inst, "main"));
      if (scErrorNo) {
         printf("SeerC Error %d while calling main(): %s\n", 
            scErrorNo, scErrorMsg);
         return(SetLastError(4630));
      }
      scFree_Instance(inst);
      free(script);
      return(retval);
   }

   int RunScriptText(char *cmd) {
   /* this compiles the SeerC text in *cmd rather than compiling a file */
      scScript script;
   
      script = scCompile_Text(cmd);
      if (scErrorNo || ! script) {
         printf("SeerC Error %d compiling command! line %s: %s\n",
            scErrorNo, scErrorLine, scErrorMsg);
         return(SetLastError(4610));
      }
      return(RunSeer(script));
   
   }

   int RunScript(char *name) {
      struct stat s;
      char tmp[PATH_MAX];
      scScript script;
   
      if ( ! stat(name, &s) ) {
         strcpy(tmp, name);
      } 
      else {
         sprintf(tmp, "%sscripts/%s", disasm_env.home, name);
         if ( stat(tmp, &s)) 
            return(SetLastError(9020));
      }
      script = scCompile_File(tmp);
      if (scErrorNo || ! script) {
         printf("SeerC Error %d compiling %s! %s:%s\n",
            scErrorNo, tmp, scErrorLine, scErrorMsg);
         return(SetLastError(4610));
      }
      return(RunSeer(script));
   }

   int RunCompiledScript(char *name){
      struct stat s;
      char tmp[PATH_MAX];
      scScript script;
   
      if ( stat(name, &s) ) {
         strcpy(tmp, name);
      } 
      else {
         sprintf(tmp, "%sscripts/%s", disasm_env.home, name);
         if (! stat(tmp, &s)) 
            return(SetLastError(9020));
      }
      script = scLoad_Script(name);
      if (! script) 
         return(0);
      return(RunSeer(script));
   }

   int CompileScript(char *name){
   /* This calls the external SeerC compiler to compile a .sc [Seer source]
    * script to a .scx [Seer binary] bytecode file */
   /* TODO: Fix the "#include bastard" problem */
      struct stat s;
      char tmp[PATH_MAX], cmdBuf[PATH_MAX * 3];
   
      if ( stat(name, &s) ) {
         strcpy(tmp, name);
      } 
      else {
         sprintf(tmp, "%sscripts/%s", disasm_env.home, name);
         if (! stat(tmp, &s)) 
            return(SetLastError(9020));
      }
   /* 'seerc' is the SeerC compiler, and resides in $BASTARD_HOME/utils */
      sprintf(cmdBuf, "%s/utils/seerc %s -o %sx", disasm_env.home, tmp, tmp);
      if ( pclose( popen( cmdBuf, "r"))  == -1){
         return(SetLastError(4610));
      }
      return(1);
   }


	/* MACROs stored in the DB 
	 * TODO -- we need some provision for saving this
	 * across databases */

	int DefineMacro( char *name, char *macro ){
		struct seer_macro m;

		memset(&m, 0, sizeof(struct seer_macro));
		strncpy(m.name, name, 31);
		m.id = ++seq.seer_macro;
		m.name[31] = 0;
		if (strlen(macro) > 2047) {
			m.type = 2;
			
			/* write to file in $HOME/scripts/macros */
		} else {
			m.type = 1;
			strcpy(m.macro, macro);
		}
		if ( d_fillnew(SEER_MACRO, &m) != S_OKAY) 
				  return(SetLastError(dbError()));
		return(m.id);
		
	}

	int UndefineMacro( char *name ){
		struct seer_macro m;

		if (d_keyfind(SEER_MACRO_NAME, name)) {
			d_delete();
			return(1);
		}
		return(SetLastError(4601));
	}

	int RunMacro( char *name ){
		struct seer_macro m;
		/* if type 1, compile macro */
		/* if type 2, read file and compile macro */
		/* run seer script */

	}
	int RecordMacro( char *name ){
		struct seer_macro m;
		/* 'enter xxx to exit' */
		/* while !xxx */
		/* gets, add to buff[2048] */
		/* DefineMacro */

	}
