/*
 * miscellaneous functions
 *
 * Revision 1.14 99/03/17 MU
 * Also capitilised the hexadecimal output strings.
 *
 * $Header: misc.c 1.12 95/08/01 $
 * $Log:	misc.c,v $
 * Revision 1.13  95/08/01  xx:xx:xx  BB
 * Fixed for Borland C/C++
 * Made inlist() case insensitive (DOS only) because DOS filenames are case
 * insensitive.
 * Made basename safe for null-strings.
 *
 * Revision 1.12  92/12/22  09:54:29  duplain
 * Changed #include <malloc.h> to #include <stdlib.h> .
 *
 * Revision 1.11  92/12/09  09:42:36  duplain
 * Simplified append_type().  Changed append_type() to append lowercase types.
 *
 * Revision 1.10  92/12/08  10:20:07  duplain
 * Added append_type().
 *
 * Revision 1.9  92/12/07  17:18:58  duplain
 * reformatted source.
 *
 * Revision 1.8  92/11/12  09:03:30  duplain
 * Fixed bug with realloc() size in uplevel().
 *
 * Revision 1.7  92/11/06  12:42:28  duplain
 * Changed print_details() so it supports PC archive headers correctly.
 *
 * Revision 1.6  92/11/04  16:56:14  duplain
 * Added check for PC archive header in print_header().
 *
 * Revision 1.5  92/10/09  18:06:58  duplain
 * Added "+1" to malloc() call in riscos_path()... SCO UNIX was quiet right
 * to core dump :-)
 *
 * Revision 1.4  92/10/07  10:56:39  duplain
 * Added check for SYSV2 when including <malloc.h>.  Made riscos_path() compile
 * for non-RISCOS systems only.
 *
 * Revision 1.3  92/10/06  12:12:29  duplain
 * Removed reference to date->csecond in print_details().
 *
 * Revision 1.2  92/09/30  10:26:58  duplain
 * Fixed basename().  Added riscos_path().
 *
 * Revision 1.1  92/09/29  18:02:21  duplain
 * Initial revision
 *
 */

#include <stdio.h>
#include "spark.h"
#include "cproto.h"
#include "main.h"

#ifdef BSD42
#include <strings.h>
#else /* not 4.2BSD */
#include <string.h>
#endif /* 4.2BSD */

#if defined(BSD42) || defined(SYSV2)
extern char *malloc P__((unsigned len));
extern char *realloc P__((char *ptr, unsigned len));
#else /* not 4.2BSD or SysV.2 */
#include <string.h>
#include <stdlib.h>
#endif /* 4.2BSD or SysV.2 */

#include "date.h"
#include "misc.h"

#ifdef UNIX
static char rcsid[] = "$Header: misc.c 1.14 99/03/17 $";
#endif /* UNIX */

/*
 * return last element in pathname
 */
char *
basename(s)
    char *s;
{
    /* BB changed next line to cope with null-pointers.
       (IRIX's strlen() produces a coredump when s == NULL). */
    /* char *cptr = s + strlen(s); */
    char *cptr;
    if (!s) return NULL;
    cptr = s + strlen(s);
    while (cptr > s) {
	if (*cptr == PATHSEP)
	    return(++cptr);
	cptr--;
    }
    return (s);
}

#if defined(RISCOS)
#define DOTARC	"_arc"
#define DOT	'_'
#else /* not RISCOS */
#define DOTARC	".arc"
#define DOT	'.'
#endif /* RISCOS */

/*
 * append ".arc" ("_arc" in RISCOS) to a string, if an extension doesn't
 * already exist, and return the new string.
 */
char *
name_dot_arc(s)
    char *s;
{
    static char *newname = NULL;

    /*
     * check that there's room for the extension
     */
    if (strlen(basename(s)) + sizeof(DOTARC)-1 > FILENAMELEN)
	return (s);

    /*
     * free previous allocation (hope it's finished with :-/)
     */
    if (newname)
	free(newname);
    newname = malloc(strlen(s) + sizeof(DOTARC));
    if (!newname)
	return (s);	/* don't complain */
    strcpy(newname, s);
    strcat(newname, DOTARC);
    return (newname);
}

/*
 * turn a local-host pathname into a RISC OS path
 */

#ifndef RISCOS
char *
riscos_path(s)
    register char *s;
{
    static char *riscosname = NULL;
    register char *cptr;

    if (riscosname)
	free(riscosname);

    riscosname = malloc(strlen(s)+1);
    if (!riscosname)
	return (NULL);
    for (cptr = riscosname; *s; s++, cptr++)
	if (*s == PATHSEP)
	    *cptr = '.';
	else
	    *cptr = *s;
    *cptr = '\0';
    return (riscosname);
}
#endif /* RISC OS */

static char *pathname = NULL;
/*
 * uplevel() and downlevel() maintain the pathname as directories are found
 * within the archive
 */
char *
uplevel()
{
    register char *cptr;
    register olen, nlen;

    if (!pathname)
	return (NULL);
		
    olen = strlen(pathname);
    cptr = pathname + olen-1;
    while (cptr > pathname)
	if (*cptr == PATHSEP) {
	    *cptr = '\0';
	    break;
	} else
	    cptr--;

    if (cptr == pathname) {
	free(pathname);
	pathname = NULL;
    } else {
	nlen = strlen(pathname);
	if (nlen < olen)
	    pathname = realloc(pathname, nlen+1);
    }
    return (pathname);
}

char *
downlevel(filename)
    char *filename;
{
    register len, flen;

    if (!pathname)
	len = 0;
    else
	len = strlen(pathname);

    flen = strlen(filename);
    if (!len) {
	pathname = malloc(flen+1);
	if (pathname)
	    strcpy(pathname, filename);
    } else {
	pathname = realloc(pathname, len + flen + 2);
	if (pathname) {
	    strcat(pathname, PATHSEPSTR);
	    strcat(pathname, filename);
	}
    }
    return (pathname);
}
	     
/*
 * print archive file details (size, data and time)
 */
void
print_details(header)
    Header *header;
{	  							       
    Date *date;

    if (!header)
	return;

    if (header->comptype & ARCHPACK) {
	/* Archimedes archive header */

        /* BB changed constants in next line to long */
	if ((header->load & (Word)0xfff00000l) == (Word)0xfff00000l) {
	    /* time stamp valid */
	    date = makedate(header);
	/*  MU changed next line to capitilise hex output*/
	/*	printf("%8ld %02d-%s-%02d %02d:%02d:%02d  &%03x",
		   header->origlen, date->day,
		   monthname(date->month), date->year,
		   date->hour, date->minute, date->second,
		   (header->load >> 8) & 0xfff); */
		printf("%8ld %02d-%s-%02d %02d:%02d:%02d  &%03X",
		   header->origlen, date->day,
		   monthname(date->month), date->year,
		   date->hour, date->minute, date->second,
		   (header->load >> 8) & 0xfff);
	
	} else {
	    /* load/exec only */
            /* BB added long to first format in next line.
               Header.origlen is a Word (i.e. a long) */
	    /* printf("%8d &%08lx &%08lx ----", header->origlen, */
            #ifdef __MSDOS__
	/*  MU changed next line to capitilise hex output*/
	/*  printf("%8ld &%08lx &%08lx ----", header->origlen, */
	    printf("%8ld &%08lX &%08lX ----", header->origlen,
            #else
	/*  MU changed next line to capitilise hex output*/
	/*  printf("%8d &%08lx &%08lx ----", header->origlen, */
	    printf("%8d &%08lX &%08lX ----", header->origlen,
            #endif /* __MSDOS__ */
		   header->load, header->exec);
	}
    } else {
	/* PC archive header */
	date = makedate(header);
	printf("%8ld %02d-%s-%02d %02d:%02d:%02d  ----",
	       header->origlen, date->day, monthname(date->month),
	       date->year, date->hour, date->minute, date->second);
    }
}

/*
 * Test if the given filename matches any of the names specified in the 
 * command line "files list".  This function is also used to test if a given
 * pathname is contained in the any of the names given in the "files list".
 *
 * Returns non-zero if filename matches, or no "files list" exists.
 */
int
inlist(filename)
    char *filename;
{
    register len = strlen(filename);
    register char **filelist = files;

    if (!*filelist)
	return (1);		/* no "files list" */

    while (*filelist)
        /* BB changed next line */
	/* if (strncmp(filename, *filelist++, len) == 0) */
#ifdef __MSDOS__
	if (strnicmp(filename, *filelist++, len) == 0)
#else
	if (strncmp(filename, *filelist++, len) == 0)
#endif /* __MSDOS__ */
	    return (1);
    return (0);
}

/*
 * append the file's type to the end if it's name
 * (this function assumes that enough storage is available in the argument
 *  "filename" to store the additional characters ",XXX")
 */
/* BB: For DOS, a comma is of no use. So changed that into a dot. */
int
append_type(header, filename)
    Header *header;
    char *filename;
{
    char append[sizeof(",xxx")];

    /* BB changed constants in next line to long. */
    if ((header->load & (Word)0xfff00000l) == (Word)0xfff00000l) {
	/* valid time-stamp */
        /* BB changed next line */
	/* sprintf(append, ",%03x", (header->load >> 8) & 0xfff); */
        #ifdef __MSDOS__
/*  MU changed next line to capitilise hex output*/
/*	sprintf(append, ".%03x", (header->load >> 8) & 0xfff); */
	sprintf(append, ".%03X", (header->load >> 8) & 0xfff);
        #else
/*  MU changed next line to capitilise hex output*/
/*	sprintf(append, ",%03x", (header->load >> 8) & 0xfff); */
	sprintf(append, ",%03X", (header->load >> 8) & 0xfff);
        #endif /* __MSDOS__ */
	strcat(filename, append);
	return (0);
    }
    return (-1);
}

#ifdef DEBUGGING
/*
 * print archive file header info
 */
void
print_header(header)
    Header *header;
{
    if (!header)
	return;

	/*  MU changed next line to capitilise hex output*/

/*    printf("comptype=0x%x name=%s complen=%lu date=0x%x time=0x%x\n",
	   header->comptype, header->name, header->complen, header->date,
	   header->time);
    printf("crc=0x%x origlen=%lu load=0x%lx exec=0x%lx attr=0x%lx\n",
	   header->crc, header->origlen, header->load, header->exec,
	   header->attr);
*/
    printf("comptype=0X%X name=%s complen=%lu date=0X%X time=0X%X\n",
	   header->comptype, header->name, header->complen, header->date,
	   header->time);
    printf("crc=0X%X origlen=%lu load=0X%lX exec=0X%lX attr=0x%lX\n",
	   header->crc, header->origlen, header->load, header->exec,
	   header->attr);

}
#endif /* DEBUGGING */
