/* Agent Tcl
   Bob Gray
   7 December 1995

   tclRandomCmd.cc

   This file provides an interface to the random and srandom functions.

   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.
*/

#include "platPorting.h"
#include "agentTcl.h"
#include "agentTclInt.h"
#include "genUtility.h"
#include "tcl.h"

/* Agent_TrueeventCmd

   Tcl syntax: trueevent <char>

      Purpose: Seed the random number generator with random bits
	       that are generated from <char> and current
	       enviromental data

	Input: dummy  = client data
	       interp = the current interpreter
	       argc   = the number of command arguments
	       argv   = the command arguments

       Output: The procedure returns TCL_ERROR and sets the interpreter result
               to an appropriate error message on error.  Otherwise the
               procedure returns TCL_OK and sets the interpreter results
	       to the number of random bits that were generated from
	       <char> and current environmental data.
*/

int Agent_TrueeventCmd (ClientData, Tcl_Interp *interp, int argc, char **argv)
{
    char c; 
    int bits;
    char temp[16];

	/* assertions */

    assert (interp != NULL);
    assert (argv != NULL);

	/* check the number of command arguments */

    if (argc != 2) {
	Tcl_AppendResult (interp, "wrong # of args: should be \"", argv[0], " <char>\"", (char *) NULL);
	return TCL_ERROR;
    }

	/* get the character */

    if ((argv[1][0] == '\0') || (argv[1][1] != '\0')) {
	Tcl_SetResult (interp, "must specify a single character", TCL_STATIC);
	return TCL_ERROR;
    } 

    c = argv[1][0];

	/* see the random number generator */

    if ((bits = Agent_Trueevent (interp, c)) < 0) {
	return TCL_ERROR;
    }

    sprintf (temp, "%d", bits);
    Tcl_SetResult (interp, temp, TCL_VOLATILE);
    return TCL_OK;
}

/* Agent_TrueseedCmd

   Tcl syntax: trueseed <bits>

      Purpose: Seed the random number generator with <bits> random
	       bits that are generated by measuring the time between
	       user keystrokes

	Input: dummy  = client data
	       interp = the current interpreter
	       argc   = the number of command arguments
	       argv   = the command arguments

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

int Agent_TrueseedCmd (ClientData, Tcl_Interp *interp, int argc, char **argv)
{
    int bits;
    int code;

	/* assertions */

    assert (interp != NULL);
    assert (argv != NULL);

	/* check the number of command arguments */

    if (argc != 2) {
	Tcl_AppendResult (interp, "wrong # of args: should be \"", argv[0], " <bits>\"", (char *) NULL);
	return TCL_ERROR;
    }

	/* get the number of bits */

    if (Tcl_GetInt (interp, argv[1], &bits) != TCL_OK) {
	Tcl_ResetResult (interp);
	Tcl_AppendResult (interp, "invalid number of bits \"", argv[1], "\": must be an integer", (char *) NULL);
	return TCL_ERROR;
    } else if (bits <= 0) {
	Tcl_AppendResult (interp, "invalid number of bits \"", argv[1], "\": must be greater than 0", (char *) NULL);
	return TCL_ERROR;
    }

	/* seed the random number generator */

    code = Agent_Trueseed (interp, bits);
    return (code);
}

/* Agent_SeedCmd

   Tcl syntax: seed <integer>

      Purpose: Seed the random number generator

        Input: dummy  = client data (unused)
               interp = the current interpreter
	       argc   = the number of command arguments
	       argv   = the command arguments

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

int Agent_SeedCmd (ClientData, Tcl_Interp *interp, int argc, char **argv)
{
    int seed;

	/* check the number of command arguments */

    if (argc != 2) {
	Tcl_AppendResult (interp, "wrong # of args: should be \"", argv[0], " <seed>\"", (char *) NULL);
	return TCL_ERROR;
    }

	/* parse the random number seed */
 
    if (Tcl_GetInt (interp, argv[1], &seed) != TCL_OK) {
	Tcl_AppendResult (interp, ": invalid random seed", (char *) NULL);
	return TCL_ERROR;
    }

	/* seed the random number generator */

    (void) Agent_Seed (interp, (UINT_32) seed);
    return TCL_OK; 
}

/* Agent_RandomCmd

   Tcl syntax: random

      Purpose: Generate and return a random number

        Input: dummy  = client data (unused)
	       interp = the Tcl interpreter
	       argc   = the number of command arguments
	       argv   = the command arguments

       Output: The procedure returns TCL_ERROR and sets the intepreter result
               to an appropriate result on error.  Otherwise the procedure
               returns TCL_OK and sets the interpreter result to a randomly
	       generated number. 
*/

int Agent_RandomCmd (ClientData, Tcl_Interp *interp, int argc, char **argv)
{
    UINT_32 number;     /* random number */
    char temp[16];	/* scratch area  */
  
	/* check the number of arguments */

    if (argc != 1) {
        Tcl_AppendResult (interp, "wrong # of args: should be \"", argv[0], "\"", (char *) NULL);
        return TCL_ERROR;
    }

	/* get a random number */

    (void) Agent_Random (interp, &number);
    sprintf (temp, "%u", number);
    Tcl_SetResult (interp, temp, TCL_VOLATILE);
    return TCL_OK;
}
 
