/* 
 * Copyright (C) 1992 by Gustaf Neumann
 *
 *      Wirtschaftsuniversitaet Wien,
 *      Abteilung fuer Wirtschaftsinformatik
 *      Augasse 2-6,
 *      A-1090 Vienna, Austria
 *      neumann@wu-wien.ac.at, neumann@watson.ibm.com
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appears in all copies and that both that
 * copyright notice and this permission notice appear in all supporting
 * documentation.  This software is provided "as is" without expressed or
 * implied warranty.
 *
 * Date: Mon, June 6, 1994
 * Author: Gustaf Neumann    
 * Version: 1.0
 */

#define MAIN
#include <wafe.h>

/* the following includes will redefine 
 *   - None
 *   - False
 *   - True
 * but this should not hurt ..
 */

#include "allobjects.h"
#include "modsupport.h"
#include "import.h"     /* for add_module */
#include "pythonrun.h"  /* for run_string */
#include "graminit.h"   /* for file_input*/

static object *
wafe_cmd(self, args)
     object *self; /* Not used */
     object *args;
{
  char *cmd, *result;

  if (!getargs(args, "s", &cmd))
    return NULL;

  if (wafeEval(wafeInterpreter,cmd,"python") == TCL_ERROR)
      {
      err_setstr(RuntimeError, "Wafe function ended with error condition");
      return NULL;
      }

  return mkvalue("s",wafeInterpreter->result);
}

static object *
wafe_set(self, args)
     object *self; /* Not used */
     object *args;
{
  char *name, *value;

  if (!getargs(args, "(ss)", &name, &value))
    return NULL;
  Tcl_SetVar(wafeInterpreter, name, value, TCL_GLOBAL_ONLY);

  INCREF(None);
  return None;
}

static object *
wafe_process_events(self, args)
     object *self; /* Not used */
     object *args;
{
#ifdef RDD
  rddAppMainLoop(wafeAppContext);
#else
  XtAppMainLoop(wafeAppContext);
#endif
  INCREF(None);
  return None;
}

#define pythonString     1
#define pythonExpression 2
#define pythonStatement  3

static int
com_python(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     object *m, *d, *v;
     char *resultString;
     int interface;

     DBUG_ENTER("python");  

     if (argc < 3) 
         {
         wafeArgcError("python","at least ",2,argc);
         DBUG_RETURN (TCL_ERROR);
         }

     if (strcmp(argv[1],"call") == 0) 
        interface = pythonString;
     else
     if (strcmp(argv[1],"exec") == 0) 
        interface = pythonStatement;
     else
     if (strcmp(argv[1],"eval") == 0) 
        interface = pythonExpression;
     else
        {
        Tcl_SetResult(comInterpreter, 
                      "first argument must be 'call' or 'exec' or 'eval'",
		      TCL_STATIC);
        DBUG_RETURN (TCL_ERROR);
        }

     m = add_module("__main__");
     if (m == NULL)
       DBUG_RETURN (TCL_ERROR);
     d = getmoduledict(m);

     if (interface == pythonString)
         {
         object *arglist, 
                *func = dictlookup(d,argv[2]);
         int i;

	 if (func == NULL) 
	     {
	     Tcl_SetResult(wafeInterpreter, 
			   "unknown python function name", TCL_VOLATILE);
	     DBUG_RETURN (TCL_ERROR);
	     }

	 arglist = newtupleobject(argc-3);
	 if (arglist == NULL)
	   DBUG_RETURN(TCL_ERROR); /* Exception */

	 for (i = 3; i < argc; i++) 
	     {
	     object *w = newstringobject(argv[i]);
	     if (w == NULL) 
	         {
		 DECREF(arglist);
		 DBUG_RETURN(TCL_ERROR); /* Exception */
	         }
	     settupleitem(arglist, i-3, w); /* "eats" reference count */
	     }

	 v = call_object(func,arglist);
	 DECREF(arglist);
	 }
     else 
         {
	 int startSymbol = 
	     interface == pythonStatement ? file_input : eval_input;

         if (argc != 3) 
	     {
             wafeArgcError("python","",2,argc);
             DBUG_RETURN (TCL_ERROR);
             }
	 
	 v = run_string(argv[2], startSymbol, d, d);
         }

     if (v == NULL) 
         {
	 print_error();
	 DBUG_RETURN (TCL_ERROR);
         }
     /*
	fprintf(stderr,
	        "interface=%d, type %s\n",
		 interface, v->ob_type->tp_name);
      */
     if (interface != pythonStatement) 
         {
	 object *t = strobject(v);
	 DECREF(v);
	 resultString = getstringvalue(t);
	 Tcl_SetResult(comInterpreter, resultString, TCL_VOLATILE);
	 XDECREF(t);
         }
     else
         DECREF(v);
     
     DBUG_RETURN (TCL_OK);
     }


static struct methodlist wafe_methods[] = {
        {"cmd",            wafe_cmd},
        {"set",            wafe_set},
	{"process_events", wafe_process_events},
        {NULL,             NULL}           /* sentinel */
};


void
initwafe()
{
  object *m, *d, *x;

  int argc = 0;
  char **argv = NULL;

  /* Create the module and add the functions */
  m = initmodule("wafe", wafe_methods);

  /* Add some symbolic constants to the module */
  d = getmoduledict(m);
  x = newstringobject("wafe.error");
  dictinsert(d, "error", x);
  x = newintobject(42L);
  dictinsert(d, "magic", x);

  /* Check for errors */
  if (err_occurred())
    fatal("can't initialize module wafe");

  wafeScriptName = "python";
  wafeTopLevel = XtVaAppInitialize(&wafeAppContext, 
				   "Python", NULL, 0, 
				   &argc, argv, NULL, NULL);
  MOTIF_EDITRES_HANDLER(wafeTopLevel);

  wafeInit(argc,argv, 
	   (Boolean)0 /* inputMode */,  
	   (Boolean)0 /* promptMode */
	   );
  Tcl_CreateCommand(wafeInterpreter, "python", com_python, NULL, NULL);
}
