/** 
 * -- Words making sense in POSIX-like systems only.
 *
 *  Copyright (C) Tektronix, Inc. 1998 - 2001. All rights reserved.
 *
 *  @see     GNU LGPL
 *  @author  Tektronix CTE                %derived_by: guidod %
 *  @version %version: bln_mpt1!5.22 %
 *    (%date_modified: Tue Nov 13 17:07:02 2001 %)
 *
 *  @description
 *              This file exports a set of system words for 
 *              a posixish OS environment. So should do
 *              any alternative wordset you might create for your OS.
 */
/*@{*/
#if defined(__version_control__) && defined(__GNUC__)
static char* id __attribute__((unused)) = 
"@(#) $Id: %full_filespec:  posix-ext.c~bln_mpt1!5.22:csrc:bln_12xx!1 % $";
#endif

#define _P4_SOURCE 1

#include <pfe/pfe-base.h>
#include <pfe/def-xtra.h>

#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <time.h>

#ifdef VxWorks
#include <sysLib.h>
#endif

#if defined PFE_HAVE_WINBASE_H 
/* --target mingw32msvc */
# undef LP
# undef CONTEXT
# include <windows.h>
#endif

/* ntohl() */
#ifndef HOST_WIN32
/* FIXME: #ifdef PFE_HAVE_NETINET_IN_H */
#include <netinet/in.h>
/* FIXME: #endif */
#else
/* well, here's a highlevel copy... */
/* (btw, #include <winsock.h> ... would make a dependency on -lws32 !!!) */
# if PFE_BYTEORDER+0 == 4321
# define ntohl(x)        (x)
# define ntohs(x)        (x)
# define htonl(x)        (x)
# define htons(x)        (x)
# else
# define ntohl(x)       ((((x) & 0x000000ff) << 24) | \
                         (((x) & 0x0000ff00) <<  8) | \
                         (((x) & 0x00ff0000) >>  8) | \
                         (((x) & 0xff000000) >> 24))

# define htonl(x)       ((((x) & 0x000000ff) << 24) | \
                         (((x) & 0x0000ff00) <<  8) | \
                         (((x) & 0x00ff0000) >>  8) | \
                         (((x) & 0xff000000) >> 24))

# define ntohs(x)       ((((x) & 0x00ff) << 8) | \
                         (((x) & 0xff00) >> 8))

# define htons(x)       ((((x) & 0x00ff) << 8) | \
                         (((x) & 0xff00) >> 8))
# endif
#endif

#include <pfe/_nonansi.h>
#include <pfe/_missing.h>
#include <pfe/logging.h>

/** 
 * CLOCKS_PER_SEC - usually one million ticks, but can be
 * very different on a specific system. Exported
 * as a constant. see CLOCK
 */  /*"CLK_TCK"*/
#ifdef  CLOCKS_PER_SEC_BUG
#undef  CLOCKS_PER_SEC
#define CLOCKS_PER_SEC sysClkRateGet()
#endif


#if !(defined SYS_EMX || defined HOST_OS_WATCOM)

#define DEFINED_ignore_line
/** #! ( "..." -- ) 
 * ignores the rest of the line,
 * defining `#!' is used to support forth scripts 
 * executed by the unix kernel
 */
FCode (p4_ignore_line)
{
    p4_refill ();
}

#endif

/** CLOCK ( --- ticks ) 
 * return clock() 
 */
static
FCode (clock)                   
{
    FX_PUSH(clock());
}
/** 
 * helper function - both arg pointers MUST be given
 */
_export void
p4_gettimeofday (p4ucell* sec, p4ucell* usec)
{
# ifdef PFE_HAVE_VXWORKS_H
# define PFE_HAVE_CLOCK_GETTIME
# endif

# if defined PFE_HAVE_CLOCK_GETTIME
    struct timespec tv;
    clock_gettime (CLOCK_REALTIME, &tv);
    if (usec) *usec = tv.tv_nsec/1000;
    *sec  = tv.tv_sec;
# elif defined PFE_HAVE_WINBASE_H
    SYSTEMTIME stime;
    GetSystemTime (&stime);
    if (usec) *usec = stime.wMilliseconds*1000;
    *sec = time(0);
# elif defined PFE_HAVE_UNISTD_H || defined PFE_HAVE_GETTIMEOFDAY
    struct timeval tv;
    gettimeofday (&tv, 0);
    if (usec) *usec = tv.tv_usec;
    *sec = tv.tv_sec;
# else
    if (usec) *usec = 0;
    *sec = time(0);
# endif
};
/** GETTIMEOFDAY ( -- double-time )
 * returns SVR/BSD gettimeofday(2). 
 * Never defined on 16-bit systems, hence
 * TIMEDATE is more portable.
 */
static
FCode (gettimeofday)
{
    FX_2ROOM;
    p4_gettimeofday (&SP[0], &SP[1]);
}
/**  ENVIRONMENT CLK_TCK  ( -- HZ )
 * the system's scheduler heartbeat clock (a.k.a. jiffies a.k.a. HZ)
 * for every function that expects time-values in ticks.
 */
static FCode(p4__clk_tck)
{
# if defined CLOCKS_PER_SEC
    FX_PUSH (CLOCKS_PER_SEC);
# elif defined CLK_TCK
    FX_PUSH (CLK_TCK);
# else
    /* including HOST_OS_AIX1 */
    FX_PUSH (1000000); /* just a guess :-) */
# endif
}

#if 0
#define PFE_NTOHS_DIRECT 1
#endif

/** NTOHS ( w -- w' )
 * if current host-encoding is bigendian, this is a NOOP
 * otherwise byteswap the lower 16-bit bits of the topofstack.
 * see W@ and W!
 * (on some platforms, the upper bits are erased, on others not)
 */ 
FCode (p4_ntohs)
{
# ifdef PFE_NTOHS_DIRECT
    *(unsigned short**)SP = ntohs (*(unsigned short**)SP);
# else
    register p4ucell item = *SP;
    *SP = ntohs (item);
# endif
}
/** NTOHL ( l -- l' )
 * if current host-encoding is bigendian, this is a NOOP
 * otherwise byteswap the lower 32-bit bits of the topofstack.
 * see L@ and L! (being usually just @ and ! )
 * (on some platforms, the upper bits are erased, on others not)
 */ 
FCode (p4_ntohl)
{
# ifdef PFE_NTOHS_DIRECT
    *(unsigned long**)SP = ntohl (*(unsigned long**)SP);
# else
    register p4ucell item = *SP;
    *SP = ntohl (item);
# endif
}
P4_LISTWORDS (posix) =
{
     (, ),
# ifdef DEFINED_ignore_line
     (,		),
# endif
     (,		),
     (,	),

     (,                   ),
     (,                   ),
     (,                   ),
     (,                   ),

     (,  ),
     (,		),

};
P4_COUNTWORDS (posix, "POSIX'like words");
/*@}*/