#include <stdio.h>
#include "make.h"

#ifdef VAXVMS
#  include <rms.h>
#endif

extern DATE bigbang;
extern DATE endoftime;

char *printdate ();

/*
 * Get a file's creation date.
 *
 * First try for a normal file, then library, then archive.
 */

void getdate (f)
FILENODE *f;
{
    extern int isonlibrary ();
    extern int isanarchive ();
    
    DBUG_ENTER ("getdate");
    if (f -> fdate == (DATE) NULL) {
	if (filedate (f) != SUCCEED) {
	    if (isonlibrary (f) != SUCCEED) {
		if (isanarchive (f) != SUCCEED) {
		    if ((f -> fflag & ROOTP) == 0) {
			fprintf (stderr, "Can't get date for file '%s'\n",
				f -> fname);
			f -> fdate = endoftime;
		    } else {
			f -> fdate = bigbang;
		    }
		}
	    }
	}
    }
    DBUG_VOID_RETURN;
}


#ifdef VAXVMS
/*
 * filedate - return file's creation date (VAX/VMS only.)
 * Returns -1 if file cannot be found, 0 if succesful.
 */
filedate (fnd)
FILENODE *fnd;
{
    register unsigned *datetime;
    static DATE adate ();
    register struct FAB *fptr;
    register struct XABDAT *dptr;

    fptr = Calloc (1, sizeof (struct FAB));	/* allocate FAB and XABDAT */
    dptr = Calloc (1, sizeof (struct XABDAT));
    if (fptr == NULL || dptr == NULL) {
	allerr ();
    }
    *fptr = cc $ rms_fab;	/* initialize FAB and XABDAT */
    *dptr = cc $ rms_xabdat;
    fptr -> fab $ l_xab = (char *) dptr;/* FAB -> XABDAT */
    fptr -> fab $ l_fna = fnd -> fname;/* setup filename */
    fptr -> fab $ b_fns = strlen (fnd -> fname);
    if (sys$open (fptr) != RMS$_NORMAL ||	/* open the file */
	sys$display (fptr) != RMS$_NORMAL) {	/* get XABDAT info */
	return (-1)
    }
    datetime = &(dptr -> xab$q_cdt);	/* record 64-bit date */
    fnd -> fdate = adate (datetime[0], datetime[1]);
    sys$close (fptr);		/* close the file */
    free (dptr);		/* clean up and return */
    free (fptr);
    return (0);
}

/*
 * laterdt - compare two dates.
 * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2
 */

laterdt (date1, date2)
DATE date1, date2;
{
    if (date1 -> ds_high > date2 -> ds_high ||
	(date1 -> ds_high >= date2 -> ds_high &&
	date1 -> ds_low > date2 -> ds_low)) {
	return (1);
    } else if (date1 -> ds_high == date2 -> ds_high &&
		date1 -> ds_low == date2 -> ds_low)
	return (0);
    } else {
	return (-1);
    }
}


/*
 * adate - allocate a date with the given time
 */

DATE adate (time1, time2)
unsigned time1;
unsigned time2;
{
    auto DATE d;

    if ((d = (DATE) Calloc (1, sizeof (struct date_str))) == NULL) {
	allerr ();
    }
    d -> ds_low = time1;
    d -> ds_high = time2;
    return (d);
}

initrootdates ()
{
    bigbang = adate (0, 0);		/* init root dates */
    endoftime = adate (~0, ~0);
}

char *printdate (fdate)
DATE fdate;
{
    static char *buffer[64];

    sprintf (buffer, "( %u, %u )",
	    (f -> fdate != NULL) ? (f -> fdate) -> ds_high : 0,
	    (f -> fdate != NULL) ? (f -> fdate) -> ds_low : 0);
    return (buffer);
}
#endif


#ifdef MSDOS

/*
 * filedate - return file's creation date (MSDOS only.)
 * Returns -1 if file cannot be found, 0 if successful
 */

filedate (fnd)
FILENODE *fnd;
{
    extern DATE osdate ();
    auto DATE newdate;
    auto int success;

    success = FAILURE;
    newdate = osdate (fnd -> fname, &success);
    if (success == FAILURE) {
	return (FAILURE);
    }
    fnd -> fdate = newdate;
    fnd -> fflag |= EXTRACT;	/* don't extract this file again */
    return (SUCCEED);
}

/*
 * laterdt - compare two dates.
 * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2
 */

laterdt (date1, date2)
DATE date1;
DATE date2;
{
    if (date1 -> ft_year > date2 -> ft_year) {
	return (1);
    }
    if (date1 -> ft_year < date2 -> ft_year) {
	return (-1);
    }
    /* years are equal */
    if (date1 -> ft_month > date2 -> ft_month) {
	return (1);
    }
    if (date1 -> ft_month < date2 -> ft_month) {
	return (-1);
    }
    /* months are equal */
    if (date1 -> ft_day > date2 -> ft_day) {
	return (1);
    }
    if (date1 -> ft_day < date2 -> ft_day) {
	return (-1);
    }
    /* days are equal */
    if (date1 -> ft_hour > date2 -> ft_hour) {
	return (1);
    }
    if (date1 -> ft_hour < date2 -> ft_hour) {
	return (-1);
    }
    /* hours are equal */
    if (date1 -> ft_min > date2 -> ft_min) {
	return (1);
    }
    if (date1 -> ft_min < date2 -> ft_min) {
	return (-1);
    }
    /* minutes are equal */
    if (date1 -> ft_tsec > date2 -> ft_tsec) {
	return (1);
    }
    if (date1 -> ft_tsec < date2 -> ft_tsec) {
	return (-1);
    }
    /* everything is equal */
    return (0);
}

/*
 * adate - allocate a date struct to be filled out later.
 */

DATE adate ()
{
    auto DATE d;

    if ((d = (DATE) Calloc (1, sizeof (struct ftime))) == (DATE) NULL) {
	allerr ();
    }
    return (d);
}

initrootdates ()
{		/* init root dates */
    bigbang = adate ();
    bigbang -> ft_tsec = 0;
    bigbang -> ft_min = 0;
    bigbang -> ft_hour = 0;
    bigbang -> ft_day = 1;
    bigbang -> ft_month = 1;
    bigbang -> ft_year = 0;
    endoftime = adate ();
    endoftime- > ft_tsec = 29;
    endoftime- > ft_min = 59;
    endoftime- > ft_hour = 23;
    endoftime- > ft_day = 31;
    endoftime- > ft_month = 11;
    endoftime- > ft_year = 127;
}

char *printdate (fdate)
DATE fdate;
{
    auto char buf[10];

#ifdef NOTYETCONVERTED
    fputs ("( ", stdout);
    itoa (fdate- > ft_hour, buf);
    fputs (buf, stdout);
    fputc (':', stdout);
    itoa (fdate- > ft_min, buf);
    fputs (buf, stdout);
    fputc (':', stdout);
    itoa (fdate- > ft_tsec, buf);
    fputs (buf, stdout);
    fputs (", ", stdout);
    itoa (fdate- > ft_month, buf);
    fputs (buf, stdout);
    fputc ('-', stdout);
    itoa (fdate- > ft_day, buf);
    fputs (buf, stdout);
    fputc ('-', stdout);
    itoa (fdate- > ft_year + 80, buf);
    fputs (buf, stdout);
    puts (" )");
#else
    return ("<not available>");
#endif
}
#endif

#ifdef unix

/*
 * filedate - return file's creation date (unix only.)
 * Returns -1 if file cannot be found, 0 if successful
 */

filedate (fnd)
FILENODE *fnd;
{
    extern DATE osdate ();
    auto DATE newdate;
    auto int success = FAILURE;

    DBUG_ENTER ("filedate");
    DBUG_3 ("date", "find date for '%s'", fnd -> fname);
    newdate = osdate (fnd -> fname, &success);
    DBUG_3 ("date", "has date %s", printdate (newdate));
    if (success != FAILURE) {
	fnd -> fdate = newdate;
	fnd -> fflag |= EXTRACT;	/* do not extract this file again */
	success = SUCCEED;
    }
    DBUG_RETURN (success);
}

/*
 * laterdt - compare two dates.
 * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2
 */

laterdt (date1, date2)
DATE date1;
DATE date2;
{
    int result;
    
    DBUG_ENTER ("laterdt");
    DBUG_4 ("dcmp", "compare %lu vs %lu", *date1, *date2);
    if (*date1 > *date2) {
	result = 1;
    } else if (*date1 < *date2) {
	result = -1;
    } else {
	result = 0;
    }
    DBUG_3 ("dcmp", "result is %d", result);
    DBUG_RETURN (result);
}

/*
 * adate - allocate a date struct to be filled out later.
 */

DATE adate ()
{
    auto DATE d;

    DBUG_ENTER ("adate");
    if ((d = (DATE) Calloc (1, sizeof (long))) == (DATE) NULL) {
	allerr ();
    }
    DBUG_RETURN (d);
}

void initrootdates ()
{		/* init root dates */
    DBUG_ENTER ("initrootdates");
    bigbang = adate ();
    *bigbang = 0;
    endoftime = adate ();
    *endoftime = ~0;
    DBUG_VOID_RETURN;
}

char *printdate (fdate)
DATE fdate;
{
    static char datebuf[64];

    if (fdate == NULL) {
	sprintf (datebuf, "<null date>");
    } else {
	sprintf (datebuf, "%lu", *fdate);
    }
    return (datebuf);
}

#endif

#ifdef AMIGA

/*
 * filedate - return file's creation date (Amiga only.)
 * Returns -1 if file cannot be found, 0 if successful
 */

filedate (fnd)
FILENODE *fnd;
{
    extern DATE osdate ();
    auto DATE newdate;
    auto int success = FAILURE;

    DBUG_ENTER ("filedate");
    newdate = osdate (fnd -> fname, &success);
    if (success == SUCCEED) {
	DBUG_3 ("fdate", "found date for '%s'", fnd -> fname);
	fnd -> fdate = newdate;
	fnd -> fflag |= EXTRACT;	/* don't extract this file again */
    }
    DBUG_RETURN (success);
}

/*
 * laterdt - compare two dates.
 * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2
 */

int laterdt (date1, date2)
DATE date1;
DATE date2;
{
    register int result;
    
    DBUG_ENTER ("laterdt");
    DBUG_3 ("dcmp", "compare date1 %s", printdate (date1));
    DBUG_3 ("dcmp", "with    date2 %s", printdate (date2));
    if (date1 -> ds_Days > date2 -> ds_Days) {
	result = 1;
    } else if (date1 -> ds_Days < date2 -> ds_Days) {
	result = -1;
    } else {
	if (date1 -> ds_Minute > date2 -> ds_Minute) {
	    result = 1;
	} else if (date1 -> ds_Minute < date2 -> ds_Minute) {
	    result = -1;
	} else {
	    if (date1 -> ds_Tick > date2 -> ds_Tick) {
		result = 1;
	    } if (date1 -> ds_Tick < date2 -> ds_Tick) {
		result = -1;
	    } else {
		result = 0;
	    }
	}
    }
    DBUG_3 ("dcmp", "result is %d", result);
    DBUG_RETURN (result);
}

/*
 * adate - allocate a date struct to be filled out later.
 */

DATE adate ()
{
    auto DATE d;

    DBUG_ENTER ("adate");
    if ((d = (DATE) Calloc (1, sizeof (struct DateStamp))) == (DATE) NULL) {
	allerr ();
    }
    DBUG_RETURN (d);
}

void initrootdates ()
{		/* init root dates */
    DBUG_ENTER ("initrootdates");
    bigbang = adate ();
    bigbang -> ds_Days = 0;
    bigbang -> ds_Minute = 0;
    bigbang -> ds_Tick = 0;
    endoftime = adate ();
    endoftime -> ds_Days = ~0;
    endoftime -> ds_Minute = ~0;
    endoftime -> ds_Tick = ~0;
    DBUG_VOID_RETURN;
}

char *printdate (fdate)
DATE fdate;
{
    static char datebuf[64];

    if (fdate == NULL) {
	sprintf (datebuf, "<null date>");
    } else {
	sprintf (datebuf, "days:%lu min:%lu ticks:%lu", fdate -> ds_Days,
    			fdate -> ds_Minute, fdate -> ds_Tick);
    }
    return (datebuf);
}
#endif
