/* ========================== C MeatAxe =============================
   os.c - OS dependent stuff

   (C) Copyright 1993 Michael Ringe, Lehrstuhl D fuer Mathematik,
   RWTH Aachen, Germany  <mringe@tiffy.math.rwth-aachen.de>
   This program is free software; see the file COPYING for details.
   ================================================================== */

/* $Id: os.c,v 1.3 1994/02/15 11:08:20 mringe Exp $
 *
 * $Log: os.c,v $
 * Revision 1.3  1994/02/15  11:08:20  mringe
 * *** empty log message ***
 *
 * Revision 1.1  1994/02/13  18:26:56  mringe
 * Initial revision
 *
 */
 


/* ------------------------------------------------------------------
   Include files
   ------------------------------------------------------------------ */

#include <string.h>
#include <stdlib.h>
#include "meataxe.h"

#if defined(OS_IBMVM)
#   include <ctype.h>
#endif

#if !(defined(OS_IBMVM))
#include <unistd.h>
#endif


/* ------------------------------------------------------------------
   Add some missing declarations
   ------------------------------------------------------------------ */

#if !defined(SIGFUNTYPE)
#define SIGFUNTYPE void
#endif

#if defined(OS_ULTRIX)
extern int setitimer(int which, void *new, void *old);
#endif



/* ------------------------------------------------------------------
   Global data
   ------------------------------------------------------------------ */

#ifdef OS_MSDOS_GCC
time_t zinittime = 0;
#endif


/* ------------------------------------------------------------------
   fopen() modes
   ------------------------------------------------------------------ */

#if defined(OS_IBMVM)

#define FMODES	"a, recfm=f, lrecl=80",\
	"r, recfm=f, lrecl=80",\
	"w, recfm=f, lrecl=80",\
	"ab, recfm=f, lrecl=256",\
	"rb, recfm=f, lrecl=256",\
	"wb, recfm=f, lrecl=256"

#else /* Default values */

#define FMODES "at","rt","wt","ab","rb","wb"

#endif

static char *fmodes[6] = { FMODES };



/* ------------------------------------------------------------------
   os_init() - Initialize OS dependent stuff. Called from mtxinit().
   ------------------------------------------------------------------ */

void os_init()

{
#if defined(OS_MSDOS_GCC)
    zinittime = time(NULL);
#endif
}



/* ------------------------------------------------------------------
   os_timeused() - Returns CPU time used in units of 1/10 sec.
   ------------------------------------------------------------------ */

/* Case 1: MS-DOS
   -------------- */

#if defined(OS_MSDOS_GCC)

long os_timeused()
{
    return (time(NULL) - zinittime);
}

/* Case 2: Systems with working getrusage
   -------------------------------------- */

#elif defined(OS_ULTRIX) || defined(OS_NETBSD) || defined(OS_SUNOS)

#include <sys/time.h>
#include <sys/resource.h>

long os_timeused()

{
    static struct rusage ru;
    getrusage(RUSAGE_SELF,&ru);
    return (ru.ru_utime.tv_sec);
}

/* Case 3: Use sysconf() and times() on other systems
   -------------------------------------------------- */

#else

#define _INCLUDE_HPUX_SOURCE	/* We neeed this for HP/UX */
#include <sys/times.h>

long os_timeused()

{
    struct tms t;
    static long clk_tck = 0;

    if (clk_tck == 0) clk_tck = sysconf(_SC_CLK_TCK);
    times(&t);
    return ((long)((t.tms_utime + t.tms_stime) / clk_tck ));
}

#endif



/* ------------------------------------------------------------------
   os_timelimit() - Set CPU time limit in seconds.
   ------------------------------------------------------------------ */

#if !(defined(OS_MSDOS_GCC))

#include <sys/time.h>
#include <signal.h>

SIGFUNTYPE vtalarm _PL((int i));
SIGFUNTYPE vtalarm(i)
int i;
{
    errexit(ERR_GAMEOVER,"I'm sorry, but");
#if (SIGFUNTYPE != void)
    return (SIGFUNTYPE)0;
#endif
}


void os_timelimit(nsecs)
long nsecs;

{
    struct itimerval tv;

    tv.it_interval.tv_sec = 0;
    tv.it_interval.tv_usec = 0;
    tv.it_value.tv_sec = nsecs;
    tv.it_value.tv_usec = 0;
    setitimer(ITIMER_VIRTUAL,&tv,NULL);
    signal(SIGVTALRM,vtalarm);
}

#else /* No interval timer, sorry... */

void os_timelimit(nsec)
long nsec;
{
}

#endif


/* ------------------------------------------------------------------
   os_mkfilename() - Convert any string into a valid file name.
   ------------------------------------------------------------------ */

char *os_mkfilename(name)
char *name;

{

#if defined(OD_MSDOS_GCC)

    static char buf[30];
    char *d;
    int i, dp, nd = 0;

    for (i = 0; name[i] != 0; ++i)
	if (name[i] == '.')
	    if (++nd == 1) dp = i;
    if (nd == 1 && dp <= 8 && i <= 12)
	return name;
    d = buf+12;
    *d = 0;
    for (--i; d != buf && i >= 0; --i)
    {
	if (name[i] != '.')
	{
	    if (d == buf+8) *--d = '.';
	    *--d = name[i];
	}
    }
    while (d != buf) *--d = 'x';
    return buf;

#elif defined(OS_IBMVM)

    static char buf[30];
    char *d = buf;
    int i;

    for (i = 0; name[i] != 0 && name[i] != '.'; ++i);
    if (i > 8) i -= 8; else i = 0;
    while (name[i] != 0 && name[i] != '.'; ++i)
    {
	if (isalnum(name[i]))
	    *d++ = name[i];
	else
	    *d++ = '-';
    }
    *d++ = ' ';
    if (name[i] == '.')
    {
	int i0 = i+1;
        for (i = i0; name[i] != 0; ++i);
        if (i > 8) i -= 8; else i = i0;
        while (name[i] != 0; ++i)
	{
	    if (isalnum(name[i]))
	        *d++ = name[i];
	    else
		*d++ = '-';
	}
    }
    else 
    {
	strcpy(d,"MTX");
	d += 3;
    }
    strcpy(d," A");
    return buf;

#else	/* Default: no translation */

    return name;

#endif

}


/* ------------------------------------------------------------------
   os_fopen() - OS independent fopen()
   ------------------------------------------------------------------ */

FILE *os_fopen(name, mode)
char *name;
int mode;

{
    char *canonical_name = os_mkfilename(name);
    char buf[200];
    int m;
    FILE *f;
    char *c;

    m = mode & 0x0F;			/* Append, read or create? */
    if ((mode & FM_TEXT) == 0) m += 3;	/* Binary mode */
    if (m < 0 || m >= 6)
	return NULL;			/* Invalid mode */
    f = fopen(canonical_name,fmodes[m]);
    if (f != NULL) return f;

    /* Search library directory
       ------------------------ */
    if ((mode & FM_LIB) == 0) return NULL;
    if ((c = getenv("MTXLIB")) != NULL)
    {	strcpy(buf,c);
	strcat(buf,canonical_name);
	if ((f = fopen(buf,fmodes[m])) != NULL)
	    return f;
    }
#if defined(MTXLIB)
    strcpy(buf,MTXLIB);
    strcat(buf,canonical_name);
    if ((f = fopen(buf,fmodes[m])) != NULL)
	return f;
#endif
    return NULL;
}


/* ------------------------------------------------------------------
   os_fseek() - OS independent fseek()
   pos >= 0: absolute seek
   pos < 0: seek to end of file
   ------------------------------------------------------------------ */

#if !defined(SEEK_SET)
#define SEEK_SET 0
#endif
#if !defined(SEEK_END)
#define SEEK_END 2
#endif

int os_fseek(file,pos)
FILE *file;
long pos;

{
    if (pos < 0)
	return fseek(file,(long) 0,SEEK_END);
    else
	return fseek(file,pos,SEEK_SET);
}



