/* Agent Tcl
   Bob Gray
   12 February 1995

   This file implements the Agent_AppInit procedure and "main".

   Copyright (c) 1995, Robert S. Gray Dartmouth College

   See the file "agent.terms" for information on usage and redistribution
   of this file and for a DISCLAIMER OF ALL WARRANTIES.
*/

/*
 * If you are modifying this file and compiling it without the Agent Tcl
 * makefiles, you will need to replace the #include "platPorting.h" with 
 * the system include files that are needed for your Agent_AppInit
 * procedures.
 */

#include "platPorting.h"  
#include "tcl.h"
#include "agentTcl.h"
#include "blobTcl.h"
#include "restrictTcl.h"
#include "tcpipTcl.h"
#include "tclUtility.h"

/*
 * The following variable is a special hack that is needed in order for
 * Sun shared libraries to be used for Tcl.  You may DELETE them if you are not
 * running on a Sun.
 */

extern "C" { 
  int matherr();
}

int *tclDummyMathPtr = (int *) matherr;

/*
 * The following variable is a special hack that we seem to need for certain
 * RedHat Linux/gcc combinations.  Under these combinations, if this variable
 * is not here, a reference to the "environ" variable is not included in the 
 * static executable, and the "environ" variable is not correctly initialized
 * to point to the user's environment.
 */

char **tclDummyEnviron = environ;

/* Agent_AppInit

   Purpose: Initialize an Agent Tcl interpreter

     Input: interp = the current interpreter
		     (struct Tcl_Interp *)

    Output: The procedure returns TCL_ERROR and sets the interpreter result
	    to an appropriate error message on error.  Otherwise the
	    procedure returns TCL_OK.
*/

int Agent_AppInit (Tcl_Interp *interp)
{
    Tcl_Interp *masterInterp;    /* master interpreter */

	/*
	 * Assertions on the parameters.
	 */

    assert (interp != NULL);

	/* 
         * See if we have a master interpreter.  If we do, then we are a 
         * slave interpreter and must perform safe initialization rather 
         * than normal initialization.					
   	 */

    masterInterp = Tcl_GetMaster (interp);

	/* 
	 * An "unsafe" slave interpreter is an error. 
	 */

    if (masterInterp != NULL) {
	if (!Tcl_IsSafe(interp)) {
	    Tcl_SetResult (interp, "slave interpreter is not \"safe\"", TCL_STATIC);    
	    return TCL_ERROR;
	}
    }

	/*
	 * Intialize the Tcl core.  
	 */

    if (masterInterp != NULL) {

	if (Tcl_SafeInit(interp, masterInterp) != TCL_OK) {
	    return TCL_ERROR;
	}

    } else {

	if (Tcl_Init(interp) != TCL_OK) {
	    printf ("Tcl_Init failed!\n");
	    return TCL_ERROR;
	}
    }

	/* agents -- use default version information if necessary */

#ifdef FIX_LATER
	/* version code currently appears in two places       */
	/* (here and in Agent_ServerMain in tclServerMain.cc) */
#endif

#ifndef LANGUAGE_NAME
#define LANGUAGE_NAME "STATE-TCL"
#endif

    Version version (LANGUAGE_NAME, TCL_MAJOR_VERSION, TCL_MINOR_VERSION, Version::e_PRODUCTION);

    if (Agent_Init (interp, version) != TCL_OK) { 
	printf ("Agent_Init failed!\n");
	return TCL_ERROR;
    }

	/* restrictions */

    if (Restrict_Init (interp) != TCL_OK) {
	return TCL_ERROR;
    }

	/* TCP/IP */

    if (Tcpip_Init (interp) != TCL_OK) {
	return TCL_ERROR;
    }

	/* blobs */

    if (Blob_Init (interp) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Call the init procedures for included packages.  Each call should
     * look like this:
     *
     * if (Mod_Init(interp) == TCL_ERROR) {
     *     return TCL_ERROR;
     * }
     *
     * where "Mod" is the name of the module.
     */

    /*
     * Call Tcl_CreateCommand for application-specific commands, if
     * they weren't already created by the init procedures called above.
     */

    /*
     * Specify a user-specific startup file to invoke if the application
     * is run interactively.  Typically the startup file is "~/.apprc"
     * where "app" is the name of the application.  If these two lines are
     * deleted then no user-specific startup file will be run under any 
     * conditions.
     */

    Tcl_SetVar (interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY);
#ifndef TCL8
    Tcl_GlueVar (interp, "tcl_rcFileName", TCL_GLOBAL_ONLY); 
#endif
    return TCL_OK;
}

int main (int argc, char **argv)
{
    /*
     * Handle agents that arrive via the server -- Agent_ServerMain  never returns!
     */

    if ((argc > 1) && (!strcmp(argv[1], "-agent"))) {
	Agent_ServerMain (Agent_AppInit);
	abort_with_message ("should never get here");   // should never get here
    }

    /*
     * Normal interpreter startup
     */

    Agent_Main (argc, argv, Agent_AppInit);
    return 1;    /* should never get here -- prevents a compiler warning */  
}
