/*******************************************************************************
Copyright by Telesoft Europe AB 1990, 1991.
Copyright by Telelogic Malmoe AB 1991, 1992, 1993.
Copyright by Telelogic AB 1994 - 2001.
This Program is owned by Telelogic and is protected by national
copyright laws and international copyright treaties. Telelogic
grants you the right to use this Program on one computer or in
one local computer network at any one time.
Under this License you may only modify the source code for the purpose
of adapting it to your environment. You must reproduce and include
any copyright and trademark notices on all copies of the source code.
You may not use, copy, merge, modify or transfer the Program except as
provided in this License.
Telelogic does not warrant that the Program will meet your
requirements or that the operation of the Program will be
uninterrupted and error free. You are solely responsible that the
selection of the Program and the modification of the source code
will achieve your intended results and that the results are actually
obtained.
*******************************************************************************/

/*
# clearcase sctos.c@@/main/37 : 2001/06/25 ba
*/

/* 
FILE INDEX
00   Include Files
00   OS routines
*/

/****+***************************************************************
00   Include Files
********************************************************************/
#include "scttypes.h"


/****+***************************************************************
00   OS routines
********************************************************************/

#if !defined(XUSER_ALLOC_FUNC)
/*---+---------------------------------------------------------------
     xAlloc
-------------------------------------------------------------------*/
void * xAlloc(xptrint Size) 
{
#ifdef XPRINTALLOC
  static int Total = 0;
  static int TotalAllocs = 0;
#endif
  if ( Size > (xptrint)0 )
#ifdef XCHECKALLOC
  {
    void  *Temp;
    Temp = (void *)calloc((unsigned)1, (unsigned)Size);
#ifdef XPRINTALLOC
    Total = Total+Size;
    TotalAllocs++;
    printf("Total allocated memory : %d, in %d allocs\n", Total, TotalAllocs);
#endif
    if (Temp == (void *)0) {
      printf("Error in xAlloc: No more memory.  Exiting program\n");
      exit(1);
    }
    return Temp;
  }
#else
    return (void *)calloc((unsigned)1, (unsigned)Size);
#endif
  else
    return (void *)0;
}
#endif   /* XUSER_ALLOC_FUNC */


#if !defined(XUSER_FREE_FUNC)
/*---+---------------------------------------------------------------
     xFree
-------------------------------------------------------------------*/
void xFree(void** P) 
{
 free(*P);
 *P = (void *)0;
}
#endif   /* XUSER_FREE_FUNC */


#if !defined(XUSER_HALT_FUNC)
/*---+---------------------------------------------------------------
     xHalt
-------------------------------------------------------------------*/
void xHalt(void)
{
  exit(0);
}
#endif   /* XUSER_HALT_FUNC */


#if defined(XCLOCK) && !defined(XUSER_CLOCK_FUNC)
/*---+---------------------------------------------------------------
     SDL_Clock
-------------------------------------------------------------------*/

#if defined(SCT_WINDOWS) || defined(NUCLEUS_MNT)
#include <time.h>
#ifdef TC2
/* this is needed for TurboC v2.x */
#define CLOCKS_PER_SEC CLK_TCK
#endif

SDL_Time SDL_Clock(void)
{
  SDL_Time tmp;
  clock_t temp, temp1;
  const xint32 xT_SCALE = 1000000000/CLOCKS_PER_SEC;
  temp   = clock();	/* Process-time */
  temp1  = temp / CLOCKS_PER_SEC;
  tmp.s  = (xint32)temp1;
  tmp.ns = (xint32)( (temp - (temp1 * CLOCKS_PER_SEC)) * xT_SCALE);
  return tmp;

/* NOTE:  You should modify this function to use the Nucleus PLUS function  */
/* NU_Retrieve_Clock() when you port the system to your target processor.   */
}


#elif defined(SCT_POSIX)
#ifdef QNX4_CC
#include <sys/time.h>
#else
#include <time.h>
#endif

SDL_Time SDL_Clock(void)
{
  SDL_Time tmp;
  tmp.s = (xint32)time((time_t *)0);   /* C standard function time */
  tmp.ns = (xint32)0; 
  return tmp;
}

#elif defined(PSOS_C)
unsigned long Sys_Ticks = 0;
SDL_Time SDL_Clock(void)
{
  SDL_Time tmp;
  tmp.s = (xint32)Sys_Ticks;
  tmp.ns = (xint32)0;
  return tmp;
}

#elif defined(VRTX_C)
#include <time.h>
SDL_Time SDL_Clock(void)
{
  SDL_Time tmp;
  int Err;
  struct timespec time_s;
  unsigned long ns = 10000000;  
  /* ns per tick for VRTXsa clock */

  sc_gclock(&time_s,&ns,&Err);
  tmp.s = time_s.seconds;
  tmp.ns = time_s.nanoseconds;
  return tmp;
}

#else
/* If not known, always return 0 */
SDL_Time SDL_Clock(void)
{
  SDL_Time tmp;
  tmp.s = (xint32)0;
  tmp.ns = (xint32)0;
  return tmp;
}

#endif 
#endif  /* XCLOCK && !XUSER_CLOCK_FUNC */



#if defined(XCLOCK) && !defined(XENV) && !defined(XUSER_SLEEP_FUNC)
/*---+---------------------------------------------------------------
     xSleepUntil
-------------------------------------------------------------------*/

#if defined(SCT_POSIX)
#include <sys/time.h>

void xSleepUntil(SDL_Time  WakeUpTime) 
{
  struct timeval tv;
  SDL_Duration   wait;

  wait = xMinusT_SDL_Time(WakeUpTime, SDL_Now());
  tv.tv_sec  = wait.s;
  tv.tv_usec = wait.ns / 1000;

  (void)select(0, 0, 0, 0, &tv);
}

#elif defined(SCT_WINDOWS)
#include <time.h>

void xSleepUntil(SDL_Time  WakeUpTime) 
{
  SDL_Duration wait;
  clock_t temp, entry_time = clock();

  wait = xMinusD_SDL_Time(WakeUpTime, SDL_Now());
  temp = (wait.s * CLOCKS_PER_SEC) + 
          ((wait.ns / 1000000 ) * (CLOCKS_PER_SEC/100)/10) + entry_time;
  while ( temp >= clock() ){;}
}

#else
void xSleepUntil(SDL_Time  WakeUpTime)
{
  /* do nothing */
}
#endif
#endif   /*  XCLOCK && !XENV && !XUSER_SLEEP_FUNC */



#if defined(XPMCOMM) && !defined(XENV)
/*---+---------------------------------------------------------------
     xGlobalNodeNumber  extern
-------------------------------------------------------------------*/
#if defined(SCT_POSIX) || defined(SCT_WINDOWS)

#ifdef SCT_WINDOWS
#ifdef __cplusplus
extern "C" int getpid(void);
#else
extern int getpid (void);
#endif
#else
#include <unistd.h>
#endif

int xGlobalNodeNumber(void)
{
  static int GlobalNodeNumber = 0;
  if ( GlobalNodeNumber == 0 )
#ifdef SCT_WINDOWS
    return GlobalNodeNumber = abs (getpid());
#else
    return GlobalNodeNumber = getpid();
#endif
  return GlobalNodeNumber;
}

#else
int xGlobalNodeNumber(void)
{
  return 1;
}
#endif
#endif /* XPMCOMM && !XENV */



#if defined(XMONITOR) && !defined(XNOSELECT) && !defined(XUSER_KEYBOARD_FUNC)
/*---+---------------------------------------------------------------
     xCheckForKeyboardInput
-------------------------------------------------------------------*/

 /*----------------------------------------------------------------------*/
 /* Insert your own implementation of Test_for_any_keyboard_input here.  */
 /* The procedure should return TRUE ((xbool)1) if a character has been  */
 /* input from the keybord, else it should return FALSE ((xbool)0). If   */
 /* no keyboard is attached to your system, this procedure should        */
 /* return FALSE.                                                        */
 /* It is adviced that the timeout parameter should be used if possible. */
 /* xKeyboardTimeout is given in micro seconds.                          */
 /*----------------------------------------------------------------------*/

#if defined(SCT_POSIX)
#include <sys/time.h>

xbool xCheckForKeyboardInput (long xKeyboardTimeout)
{
 /*----------------------------------------------------------------------*/
 /* This is the standard UNIX version, using 'select()'                  */
 /*----------------------------------------------------------------------*/
  struct timeval tv;
  long readfds;  /* fd_set is struct with one long component */
  int rt;

  readfds = (long)1;
  tv.tv_sec =  0;
  tv.tv_usec = xKeyboardTimeout;
  rt = select(1, (fd_set *)&readfds, 0, 0, &tv);
  if (rt > 0) return (xbool)1;
#if defined(XDEBUGSELECT)
  if (rt < 0) printf("Error in select\n");
#endif
  return (xbool)0;
}

#elif defined(__BORLANDC__) && !defined(__CONSOLE__)
xbool xCheckForKeyboardInput (long xKeyboardTimeout)
{
  /* No implementation, always return 0 */
  return (xbool)0;
}


#elif defined(SCT_WINDOWS)
 /*----------------------------------------------------------------------*/  
 /* This is a version for executing on a IBM compatible PC, using        */
 /*  Borland C++ 3.x or Microsoft C v6.x.                                */
 /*----------------------------------------------------------------------*/  
#include <time.h>
#ifdef __BORLANDC__
#pragma argsused
#endif
#if !defined(XNO_BIOS_H) && !defined(_MSC_VER) && !defined(_Windows)
#include <bios.h>
#define KBHIT _bios_keybrd(_KEYBRD_READY)
#else
#include <conio.h>
#define KBHIT kbhit()
#endif

xbool xCheckForKeyboardInput (long xKeyboardTimeout)
{
  clock_t xTimeoutTime, xEntryTime;
  static clock_t xCSignBitMask;
  xbool xOverflow;

 if (xKeyboardTimeout == 0) {
    if ( KBHIT ) return (xbool)1;
    return (xbool)0;
  }

  xEntryTime = clock();

   /* cnvrt micro sec to DOS ticks and handle clock()-overflow */
  xTimeoutTime = xEntryTime + (clock_t)(xKeyboardTimeout / 10000);
  xOverflow = (xTimeoutTime < xEntryTime ? (xbool)1 : (xbool)0 );
  if ( xOverflow ) {
    xCSignBitMask = ~( (~((clock_t)0)) >> 1 );
                                   /* create a sign-bit mask for clock_t */
    while ( (xCSignBitMask & clock()) ) {
      if ( KBHIT ) return (xbool)1;
    }
  }

  do {
    if ( KBHIT ) return (xbool)1;
  } while ( xTimeoutTime > clock() );

  return (xbool)0;
}

#else
xbool xCheckForKeyboardInput (long xKeyboardTimeout)
{
  /* No implementation, always return 0 */
  return (xbool)0;
}
#endif

#endif   /* XMONITOR && !XNOSELECT && !XUSER_KEYBOARD_FUNC */



#if defined(XMONITOR) && !defined(USER_GETSET_WORKDIR)
/*---+---------------------------------------------------------------
     xGetWorkdir and xSetWorkdir
-------------------------------------------------------------------*/
#if defined(SCT_POSIX)

#include <unistd.h>
#include <errno.h>
char *xGetWorkdir(char **d)
{
  if ((*d = getcwd(NULL, 1024)) == 0)
    return strerror(errno);
  return 0;
}
char *xSetWorkdir(char *d)
{
  if (chdir(d) == -1)
    return strerror(errno);
  return 0;
}

#elif defined(SCT_WINDOWS)

#include <windows.h>
#include <errno.h>
static char ErrMsg[1024];
HANDLE hInstance;           /* Needed? when linking on BORLAND */
char *winstrerror(int E)
{
  if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                     0, E, 0, ErrMsg, sizeof(ErrMsg), 0))
    (void) sprintf(ErrMsg, "Error %d", E);
  return ErrMsg;
}
char *xGetWorkdir(char **d)
{
  *d = (char *)malloc(1024);
  if (GetCurrentDirectory(1024, *d) == 0)
    return winstrerror(GetLastError());
  return 0;
}
char *xSetWorkdir(char *d)
{
  if(SetCurrentDirectory((d)) == FALSE)
    return winstrerror(GetLastError());
  return 0;
}

#else

char *xGetWorkdir(char **d)
{
  return "Not implemented";
}
char *xSetWorkdir(char *d)
{
  return "Not implemented";
}

#endif    /* defined(XMONITOR) && !defined(USER_GETSET_WORKDIR) */

#endif    /* XMONITOR */
