#ifndef lint
static char *RCSid = "$Id: alloc.c,v 1.4 1995/05/09 12:23:25 drd Exp $";
#endif


/* GNUPLOT - alloc.c */
/*
 * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the modified code.  Modifications are to be distributed
 * as patches to released version.
 *
 * This software is provided "as is" without express or implied warranty.
 *
 *
 * AUTHORS
 *
 * Alexander Lehmann (collected functions from misc.c and binary.c)
 *
 */

#include "plot.h" /* includes "alloc.h" */

#if defined(MSDOS) && defined(__TURBOC__) && !defined(DOSX286)
#include <alloc.h>		/* for farmalloc, farrealloc */
#endif

#if defined(_Windows) && !defined(WIN32)
#include <windows.h>
#include <windowsx.h>
#define farmalloc(s) GlobalAllocPtr(GHND,s)
#define farrealloc(p,s) GlobalReAllocPtr(p,s,GHND)
#endif

#ifndef NO_GIH
#include "help.h"
#endif

/* alloc:
 * allocate memory 
 * This is a protected version of malloc. It causes an int_error 
 * if there is not enough memory, but first it tries FreeHelp() 
 * to make some room, and tries again. If message is NULL, we 
 * allow NULL return. Otherwise, we handle the error, using the
 * message to create the int_error string. Note cp/sp_extend uses realloc,
 * so it depends on this using malloc().
 */

char *
alloc(size, message)
	unsigned long size;		/* # of bytes */
	char *message;			/* description of what is being allocated */
{
    char *p;				/* the new allocation */
    char errbuf[100];		/* error message string */

#ifndef NO_GIH
#ifdef FARALLOC
    p = farmalloc(size);
#else
    p = malloc((size_t)size);
#endif
    if (p == (char *)NULL) {
	   FreeHelp();			/* out of memory, try to make some room */
#endif /* NO_GIH */
#ifdef FARALLOC
	   p = farmalloc(size);		/* try again */
#else
	   p = malloc((size_t)size);	/* try again */
#endif
	   if (p == (char *)NULL) {
		  /* really out of memory */
		  if (message != NULL) {
			 (void) sprintf(errbuf, "out of memory for %s", message);
			 int_error(errbuf, NO_CARET);
			 /* NOTREACHED */
		  }
		  /* else we return NULL */
	   }
#ifndef NO_GIH
    }
#endif
    return(p);
}

/*
 * note ralloc assumes that failed realloc calls leave the original mem block
 * allocated. If this is not the case with any C compiler, a substitue
 * realloc function has to be used.
 */

generic *
ralloc(p, size, message)
	generic *p;			/* old mem block */
	unsigned long size;		/* # of bytes */
	char *message;			/* description of what is being allocated */
{
    char *res;				/* the new allocation */
    char errbuf[100];		/* error message string */

    /* realloc(NULL,x) is meant to do malloc(x), but doesn't always */
    if (!p)
	return alloc(size,message);

#ifndef NO_GIH
#ifdef FARALLOC
    res = farrealloc(p, size);
#else
    res = realloc(p, (size_t)size);
#endif
    if (res == (char *)NULL) {
	   FreeHelp();			/* out of memory, try to make some room */
#endif /* NO_GIH */
#ifdef FARALLOC
	   res = farrealloc(p, size);		/* try again */
#else
	   res = realloc(p, (size_t)size);	/* try again */
#endif
	   if (res == (char *)NULL) {
		  /* really out of memory */
		  if (message != NULL) {
			 (void) sprintf(errbuf, "out of memory for %s", message);
			 int_error(errbuf, NO_CARET);
			 /* NOTREACHED */
		  }
		  /* else we return NULL */
	   }
#ifndef NO_GIH
    }
#endif
    return(res);
}

#ifdef FARALLOC
void gpfree(p)
generic *p;
{
#ifdef _Windows
HGLOBAL hGlobal = GlobalHandle(SELECTOROF(p));
	GlobalUnlock(hGlobal);
	GlobalFree(hGlobal);
#else
	farfree(p);
#endif
}
#endif
