/* tailor.c -- target dependent functions
 * Copyright (C) 1992-1993 Jean-loup Gailly
 * This is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License, see the file COPYING.
 */

/* tailor.c is a bunch of non portable routines.
 * It should be kept to a minimum.
 */

#include <config.h>
#include "tailor.h"
#include "gzip.h"

#ifdef __TURBOC__

/************************/
/*  Function fcalloc()  */
/************************/

/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
 * and farmalloc(64K) returns a pointer with an offset of 8, so we
 * must fix the pointer. Warning: the pointer must be put back to its
 * original form in order to free it, use fcfree().
 * For MSC, use halloc instead of this function (see tailor.h).
 */
static ush ptr_offset = 0;

void * fcalloc(items, size)
    unsigned items; /* number of items */
    unsigned size;  /* item size */
{
    void * buf = farmalloc((ulg)items*size + 16L);
    if (buf == NULL) return NULL;
    /* Normalize the pointer to seg:0 */
    if (ptr_offset == 0) {
	ptr_offset = (ush)((uch*)buf-0);
    } else if (ptr_offset != (ush)((uch*)buf-0)) {
	error("inconsistent ptr_offset");
    }
    *((ush*)&buf+1) += (ptr_offset + 15) >> 4;
    *(ush*)&buf = 0;
    return buf;
}

void fcfree(ptr)
    void *ptr; /* region allocated with fcalloc() */
{
    /* Put the pointer back to its original form: */
    *((ush*)&ptr+1) -= (ptr_offset + 15) >> 4;
    *(ush*)&ptr = ptr_offset;
    farfree(ptr);
 }

#endif /* __TURBOC__ */

#ifdef __DJGPP__

#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

/* ============================================================
 * Make a file name valid for file systems supported by DJGPP.
 * This includes replacing characters that aren't allowed in
 * file names, and renaming files whose names are reserved by
 * character device drivers.  Characters that aren't allowed
 * depend on the filesystem where the file resides.
 */
void make_valid_dosw32_name(name)
    char *name;
{
    /* The following characters aren't allowed in DOS file names.
       Some of them aren't allowed by Windows 9X; these begin at
       offset 7 (zero-based) in the string below.  */
    static char disallowed_chars[] = "+, ;=[]|<>\\\":?*";
    static char replacement_char[] = "x'_`_{}!()%'-^#";
    int long_names = HAVE_LONG_FILE_NAMES(ofname);
    struct stat st;
    register char *p = name;

    /* If the filesystem disallows multiple dots, remove
       all but the last one.  */
    if (!long_names)
      make_simple_name(name);

    /* If there are any more invalid characters, replace them.  */
    for ( ; *p != '\0'; p++)
    {
      register int i;

      for (i = long_names ? 7 : 0; i < sizeof(disallowed_chars); i++)
        if (*p == disallowed_chars[i])
        {
          *p = replacement_char[i];
          break;
        }
    }

    /* The list of character devices is not constant: it depends on
       what device drivers did they install in their CONFIG.SYS.
       `stat' will tell us if the file name is a character device.  */
    if (stat(name, &st) == 0 && S_ISCHR(st.st_mode))
    {
      /* If it's a reserved name, prepend a '_' to it.  */
      memmove(name + 1, name, strlen(name) + 1);
      name[0] = '_';
    }
}

#endif /* __DJGPP__ */
