//-----------------------------------------------------------------------------
// COPYRIGHT  (c)  1997 
// THE REGENTS OF THE UNIVERSITY OF MICHIGAN
// ALL RIGHTS RESERVED
// 
// PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS 
// AND REDISTRIBUTE THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR 
// ANY PURPOSE, SO LONG AS NO FEE IS CHARGED, AND SO LONG AS 
// THE COPYRIGHT NOTICE ABOVE, THIS GRANT OF PERMISSION, AND 
// THE DISCLAIMER BELOW APPEAR IN ALL COPIES MADE; AND SO LONG 
// AS THE NAME OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY 
// ADVERTISING OR PUBLICITY PERTAINING TO THE USE OR 
// DISTRIBUTION OF THIS SOFTWARE WITHOUT SPECIFIC, WRITTEN 
// PRIOR AUTHORIZATION.
// 
// THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 
// FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS 
// FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE 
// UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR 
// IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
// REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 
// FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 
// CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT 
// HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH 
// DAMAGES.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// File: utils.cc
//
// Purpose: General purpose utilities for printing out messages.
//
// Remarks: --
//
// History: 6/16/95 - JPMS - created -- adapted from other utils files.
//          3/18/97 - MAR - modified for use in cellsyn
//
// Copyright (c) 1996 Joao P. Marques Silva.
//
// RCS Version:
//     $Id: utils.cc,v 1.1.1.1 2002/05/01 14:23:27 mguthaus Exp $
//-----------------------------------------------------------------------------

#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include <time.h>
#include <map>
#include <list>
#include <vector>
using namespace std;

#ifdef TCL_WRAPPER
// Forward declaration
// Declare tcl_printf() to be a (plain) C source routine
extern "C" void tcl_printf(FILE *f, const char *format, ...);
#endif

//-----------------------------------------------------------------------------
// Functions for printing error/warn messages.
//-----------------------------------------------------------------------------

static char *trailer = NULL;

//
// Sets the traling keyword for each message. For example "GRASP"
//
void setTrailString( char *str )
{
    trailer = str;
}

#ifdef TCL_WRAPPER

//
// Abort: Exits the program if error conditions are detected.
//

// Note: This routine SHOULD NOT call exit()!  We need a graceful
// abort procedure that will return an error status to the calling
// routine.

void Abort( char *s )
{
    tcl_printf(stderr, "\n    %s Error: %s\n", trailer, s);
    tcl_printf(stderr, "\tContinuing SPICE load...\n\n");
    exit(1);
}


//
// Warn: Gives a warning on an unexpected condition.
//
void Warn( char *s )
{
    tcl_printf(stderr, "\n    %s Warning: %s\n", trailer, s);
    tcl_printf(stderr, "\tContinuing SPICE load...\n\n");
}


//
// Warn: Gives a run-time information message.
//
void Info( char *s )
{
    tcl_printf(stderr, "\n    %s Information: %s\n", trailer, s);
}

#else	/* !TCL_WRAPPER */

//
// Abort: Exits the program if error conditions are detected.
//
void Abort( char *s )
{
    cout << "\n    " << trailer << " Error: " << s << endl;
    cout << "\tAborting Execution....\n\n" << endl;
    exit(1);
}


//
// Warn: Gives a warning on an unexpected condition.
//
void Warn( char *s )
{
    cout << "\n    " << trailer << " Warning: " << s << endl;
    cout << "\tContinuing Execution....\n\n" << endl;
}


//
// Warn: Gives a run-time information message.
//
void Info( char *s )
{
    cout << "\n    " << trailer << " Information: " << s << endl;
}

#endif /* !TCL_WRAPPER */

//-----------------------------------------------------------------------------
//
// Functions for I/O interfacing and for printing general data.
//
//-----------------------------------------------------------------------------

#ifdef TCL_WRAPPER

//
// Formatted printing of string number pairs (version for use with TCL).
//
void printItem() { tcl_printf(stdout, "\n"); }

void printItem(char *str, int num)
{
    tcl_printf(stdout, "  %s %d\n", str, num);
}

void printItem(char *str, double rnum)
{
    tcl_printf(stdout, "  %s %0.3g\n", str, rnum);
}

//
// Prints timing information, either elapsed time or (optionally) the total
// time (version for use with TCL).
//
void printTime( char *msg, double time, char *tmsg )
{
    tcl_printf(stdout, "\t%s. %s time: %0.5g\n", msg, tmsg, time);
}

#else	/* !TCL_WRAPPER */

#define STR_COL_WIDTH 60
#define NUM_COL_WIDTH 10

//
// Formatted printing of string number pairs.
//
void printItem() { cout << endl; }

void printItem(char *str, int num)
{
    cout << "  ";
    cout.setf(ios::left,ios::adjustfield);
    cout.width(STR_COL_WIDTH);
    cout.fill(' ');
    cout << str;
    cout.setf(ios::right,ios::adjustfield);
    cout.width(NUM_COL_WIDTH);
    cout << num << endl;
}

void printItem(char *str, double rnum)
{
    cout << "  ";
    cout.setf(ios::left,ios::adjustfield);
    cout.width(STR_COL_WIDTH);
    cout.fill(' ');
    cout << str;
    cout.setf(ios::right,ios::adjustfield);
    cout.width(NUM_COL_WIDTH);
    cout.precision(3);
    cout << rnum << endl;
}

//
// Prints timing information, either elapsed time or (optionally) the total
// time.
//
void printTime( char *msg, double time, char *tmsg )
{
    cout.precision(5);
    cout << "\t" << msg << ". " << tmsg << " time: " << time << endl;
}

#endif /* !TCL_WRAPPER */

//
// Appends two strings, returns the resulting string.  If non-null, the
// supplied separator char is placed between the two strings.
//
char *strcat( char *str1, char *str2, char separator) {
    if (! (str1||str2)) return NULL;
    if (!str1) return strdup(str2);
    if (!str2) return strdup(str1);
    char *new_str = (char *) malloc(strlen(str1)+1+strlen(str2)+1);
    sprintf(new_str,"%s%c%s",str1,separator,str2);
    return new_str;
}

//
// Uses a (possibly system dependent) call to set a random number seed.
// If the supplied seed is negative, creates a seed from the current time.
//
long set_ranseed(long seed) {
    if (seed == -1)
        seed = (long)time(NULL);
    srand48(seed);
    return seed;
}    

//
// Return a random integer between 'low' and 'high'.  A call to
// set_ranseed() should proceed the first call to get_ranint().
//
long get_ranint(long low, long high) {
    long n = (lrand48() % (high-low+1)) + low;
    return n;
}

//
// Return a random double in the range [0.0, 1.0). A call to
// set_ranseed() should proceed the first call to get_ranfloat().
//
double get_ranfloat() {
    double n = drand48();
    return n;
}

/*****************************************************************************/
