/*****************************************************************************
* replacer for the MSDOS functions.					     *
*									     *
* Written by:  Gershon Elber				Ver 1.0, Aug. 1991   *
*****************************************************************************/

#include <math.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef OS2GCC
#define INCL_DOSPROCESS
#include <os2.h>
#endif /* OS2GCC */
#ifdef SGINAP
#include <limits.h>
#endif /* SGINAP */
#ifdef __WINNT__
#include <windows.h>
#else
#include <sys/types.h>
#if !(defined(AMIGA) && defined(__SASC))
#include <sys/times.h>
#include <sys/param.h>
#endif /* !(AMIGA && __SASC) */
#ifndef HZ
#define HZ 60
#endif /* HZ */
#endif /* __WINNT__ */

#include "irit_sm.h"
#include "imalloc.h"

/*****************************************************************************
*   Routine to duplicate a string. Exists in some implementations.	     *
*****************************************************************************/
char *IritStrdup(char *s)
{
    char
	*p = IritMalloc(strlen(s) + 1);

    if (p == NULL)
	return NULL;

    strcpy(p, s);

    return p;
}

/*****************************************************************************
*   Routine to force a process to sleep.				     *
*****************************************************************************/
void IritSleep(int MiliSeconds)
{
#ifdef USLEEP
    usleep(MiliSeconds * 1000);
#else
#ifdef SGINAP
    sginap((long) (MAX(CLK_TCK * MiliSeconds / 1000, 1)));
#else
#ifdef OS2GCC
    DosSleep(MiliSeconds);
#else
#ifdef __WINNT__
    Sleep(MiliSeconds);
#else
    int i;

    for (i = MiliSeconds * 1000; i > 0; i--);
#endif /* __WINNT__ */
#endif /* OS2GCC */
#endif /* SGINAP */
#endif /* USLEEP */
}

/*****************************************************************************
*   Routine to initialize the random number generator.			     *
*****************************************************************************/
void IritRandomInit(long Seed)
{
#ifdef RAND
    srand(Seed);
#else
#ifdef RAND48
    srand48(Seed);
#else
    srandom(Seed);
#endif /* RAND48 */
#endif /* RAND */
}

/*****************************************************************************
*   Routine to compute a random number in a specified range.		     *
*****************************************************************************/
RealType IritRandom(RealType Min, RealType Max)
{
    long R;

#ifdef RAND
    R = rand();
#else
#ifdef RAND48
    R = lrand48();
#else
    R = random();
#endif /* RAND48 */
#endif /* RAND */

#if defined(OS2GCC) || defined(sgi)
    return Min + (Max - Min) * (R & RAND_MAX) / ((double) RAND_MAX);
#else
    return Min + (Max - Min) * (R & 0x7fffffff) / ((double) 0x7fffffff);
#endif /* OS2GCC || sgi */
}

/*****************************************************************************
*   Routine to compute the cpu time of the running process.		     *
*   If Reset, then time count is cleared to zero.			     *
*****************************************************************************/
RealType IritCPUTime(int Reset)
{
    static RealType
	LastTime = 0.0;
    RealType Time;

    if (Reset) {
#ifdef TIMES
	struct tms tim;

	times(&tim);

	LastTime = (tim.tms_utime + tim.tms_stime) / ((RealType) HZ);
#else
	LastTime = time(NULL);                /* No real timing routines!? */
#endif /* __WINNT__ */

	return 0.0;
    }

#ifdef TIMES
    {
	struct tms tim;

	times(&tim);

	Time = (tim.tms_utime + tim.tms_stime) / ((RealType) HZ) - LastTime;
    }
#else
    Time = time(NULL) - LastTime;
#endif /* TIMES */

    return Time;
}

/*****************************************************************************
*   Routine to create and return a string describing current date and time.  *
*****************************************************************************/
char *IritRealTimeDate(void)
{
    static char StrTime[LINE_LEN];
    int i;
    long
	t = (long) time(NULL);

    strncpy(StrTime, ctime(&t), LINE_LEN - 1);

    /* Remove trailing EOL. */
    for (i = strlen(StrTime) - 1; StrTime[i] < ' ' && i >= 0; i--);
    StrTime[i + 1] = 0;

    return StrTime;
}

#ifndef AMIGA
/*****************************************************************************
*   Routine to move a block in memory. Unlike memcpy/bcopy, this routine     *
* should support overlaying blocks. This stupid implemetation will copy it   *
* twice - to a temporary block and back again. The temporary block size will *
* be allocated by demand.						     *
*****************************************************************************/
void movmem(VoidPtr Src, VoidPtr Dest, int Len)
{
    VoidPtr
	p = IritMalloc(Len);

    memcpy(p, Src, Len);
    memcpy(Dest, p, Len);

    IritFree(p);
}
#endif /* AMIGA */

/*****************************************************************************
*   Routine to concat a full path to a given name - used in non MSDOS        *
* environment only, and in that case assumes path is in IRIT_PATH variable.  *
*****************************************************************************/
char *searchpath(char *Name)
{
    static char FullPath[LINE_LEN_LONG];
    char *p;

    if ((p = getenv("IRIT_PATH")) != NULL) {
	strcpy(FullPath, p);
	strcat(FullPath, Name);
    }
    else {
	static int Printed = FALSE;
	
	strcpy(FullPath, Name);

	if (!Printed) {
	    fprintf(stderr,
		    "IRIT_PATH env. not set. Only current directory is being searched.\n");
	    Printed = TRUE;
	}
    }
    return FullPath;
}

#ifdef STRICMP
/*****************************************************************************
*   Routine to compare two strings, ignoring case, up to given length.       *
*****************************************************************************/
int strnicmp(char *s1, char *s2, int n)
{
    /* Use to be simply 'return strncasecmp(s1, s2, n);' but seems that some */
    /* unix systems (sun4?) does have it so here it is explicitly.	     */
    /* Written by Reiner Wilhelms <reiner@shs.ohio-state.edu>.		     */
    int i;
    char c1, c2;

    for (i = 0; i < n; i++) {
        if (islower(s1[i]))
	    c1 = toupper(s1[i]);
        else
	    c1 = s1[i];
        if (islower(s2[i]))
	    c2 = toupper(s2[i]);
        else
	    c2 = s2[i];

        if (c1 != c2) {
	    if (c1 > c2)
		return 1;
            if (c1 < c2)
		return -1;
	}
    }
    return 0;
}

/*****************************************************************************
*   Routine to compare two strings, ignoring their case.		     *
*****************************************************************************/
int stricmp(char *s1, char *s2)
{
    int i;
    char *u1, *u2;

    if (s1 == NULL)
	return s2 != NULL;
    else if (s2 == NULL)
	return 1;

    u1 = IritStrdup(s1);
    u2 = IritStrdup(s2);

    for (i = 0; i < (int) strlen(u1); i++)
	if (islower(u1[i]))
	    u1[i] = toupper(u1[i]);
    for (i = 0; i < (int) strlen(u2); i++)
	if (islower(u2[i]))
	    u2[i] = toupper(u2[i]);

    i = strcmp(u1, u2);

    IritFree(u1);
    IritFree(u2);

    return i;
}
#endif /* STRICMP */

#ifdef STRSTR
/*****************************************************************************
*   Routine to search for pattern (no regular expression) in s. Returns      *
* address in s of first occurance of patern, NULL if non found.		     *
*****************************************************************************/
char *strstr(char *s, char *Pattern)
{
    int Len = strlen(Pattern);
    char
	*p = (char *) s;

    while (p = strchr(p, Pattern[0]))
	if (strncmp(p, Pattern, Len) == 0)
	    return p;
	else
	    p++;

    return NULL;
}
#endif /* STRSTR */

#ifdef GETCWD
/*****************************************************************************
*   Get current working directory - BSD4.3.				     *
*****************************************************************************/
char *getcwd(char *s, int Len)
{
    getwd(s);

    return s;
}
#endif /* GETCWD */
