#if defined(_UWIN) && defined(_BLD_ast)
void _STUB_malloc(){}
#else
#if _UWIN
#define calloc ______calloc
#define _ast_free ______free
#define malloc ______malloc
#define mallinfo ______mallinfo
#define mallopt ______mallopt
#define mstats ______mstats
#define realloc ______realloc
#define _STDLIB_H_ 1
extern int atexit(void(*)(void));
extern char* getenv(const char*);
#endif
#include "vmhdr.h"
#include <errno.h>
#if _UWIN
#include <malloc.h>
#define _map_malloc 1
#define _mal_alloca 1
#undef calloc
#define calloc _ast_calloc
#undef _ast_free
#define free _ast_free
#undef malloc
#define malloc _ast_malloc
#undef mallinfo
typedef struct ______mallinfo Mallinfo_t;
#undef mallopt
#undef mstats
typedef struct ______mstats Mstats_t;
#undef realloc
#define realloc _ast_realloc
#endif
#if __STD_C
#define F0(f,t0) f(t0)
#define F1(f,t1,a1) f(t1 a1)
#define F2(f,t1,a1,t2,a2) f(t1 a1, t2 a2)
#else
#define F0(f,t0) f()
#define F1(f,t1,a1) f(a1) t1 a1;
#define F2(f,t1,a1,t2,a2) f(a1, a2) t1 a1; t2 a2;
#endif
#if !defined(_AST_std_malloc) && __CYGWIN__
#define _AST_std_malloc 1
#endif
#if _sys_stat
#include <sys/stat.h>
#endif
#include <fcntl.h>
#ifdef S_IRUSR
#define CREAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
#else
#define CREAT_MODE 0644
#endif
static Vmulong_t _Vmdbstart = 0;
static Vmulong_t _Vmdbcheck = 0;
static Vmulong_t _Vmdbtime = 0;
static int _Vmpffd = -1;
#if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc
#if !_map_malloc
#undef calloc
#undef cfree
#undef free
#undef mallinfo
#undef malloc
#undef mallopt
#undef memalign
#undef mstats
#undef realloc
#undef valloc
#if _malloc_hook
#include <malloc.h>
#undef calloc
#undef cfree
#undef free
#undef malloc
#undef memalign
#undef realloc
#define calloc _ast_calloc
#define cfree _ast_cfree
#define free _ast_free
#define malloc _ast_malloc
#define memalign _ast_memalign
#define realloc _ast_realloc
#endif
#endif
#if _WINIX
#include <ast_windows.h>
#if _UWIN
#define VMRECORD(p) _vmrecord(p)
#define VMBLOCK { int _vmblock = _sigblock();
#define VMUNBLOCK _sigunblock(_vmblock); }
extern int _sigblock(void);
extern void _sigunblock(int);
extern unsigned long _record[2048];
__inline Void_t* _vmrecord(Void_t* p)
{
register unsigned long v = ((unsigned long)p)>>16;
_record[v>>5] |= 1<<((v&0x1f));
return p;
}
#else
#define getenv(s) lcl_getenv(s)
static char*
lcl_getenv(const char* s)
{
int n;
static char buf[512];
if (!(n = GetEnvironmentVariable(s, buf, sizeof(buf))) || n > sizeof(buf))
return 0;
return buf;
}
#endif
#endif
#ifndef VMRECORD
#define VMRECORD(p) (p)
#define VMBLOCK
#define VMUNBLOCK
#endif
#if defined(__EXPORT__)
#define extern extern __EXPORT__
#endif
static int _Vmflinit = 0;
#define VMFLINIT() \
{ if(!_Vmflinit) vmflinit(); \
if(_Vmdbcheck) \
{ if(_Vmdbtime < _Vmdbstart) _Vmdbtime += 1; \
else if((_Vmdbtime += 1) < _Vmdbstart) _Vmdbtime = _Vmdbstart; \
if(_Vmdbtime >= _Vmdbstart && (_Vmdbtime % _Vmdbcheck) == 0 && \
Vmregion->meth.meth == VM_MTDEBUG) \
vmdbcheck(Vmregion); \
} \
}
#if __STD_C
static int vmflinit(void)
#else
static int vmflinit()
#endif
{
char* file;
int line;
Void_t* func;
_Vmflinit = 1;
VMFLF(Vmregion,file,line,func);
VMOPTIONS();
Vmregion->file = file;
Vmregion->line = line;
Vmregion->func = func;
return 0;
}
#if _mem_mmap_anon || _mem_mmap_zero
static Vmalloc_t *Region[64];
static unsigned int Regmax = 64;
#else
static Vmalloc_t* Region[1];
static unsigned int Regmax = 0;
#endif
static unsigned int Regnum = 0;
static unsigned int Regopen = 0;
static unsigned int Reglock = 0;
static unsigned int Regprobe = 0;
int setregmax(int regmax)
{
int oldmax = Regmax;
if(regmax >= Regnum && regmax <= sizeof(Region)/sizeof(Region[0]))
Regmax = regmax;
return oldmax;
}
int _mallocstat(Vmstat_t* st)
{
Vmstat_t vmst;
int k;
if(vmstat(Vmregion, st) < 0)
return -1;
for(k = 0; k < Regnum; ++k)
{ if(!Region[k])
continue;
if(vmstat(Region[k], &vmst) < 0 )
return -1;
st->n_busy += vmst.n_busy;
st->n_free += vmst.n_free;
st->s_busy += vmst.s_busy;
st->s_free += vmst.s_free;
st->m_busy += vmst.m_busy;
st->m_free += vmst.m_free;
st->n_seg += vmst.n_seg;
st->extent += vmst.extent;
}
st->n_region = Regnum+1;
st->n_open = Regopen;
st->n_lock = Reglock;
st->n_probe = Regprobe;
return 0;
}
static Vmalloc_t* regionof(Void_t* addr)
{
int k;
#if USE_NATIVE
#define CAUTIOUS 1
#else
#define CAUTIOUS 0
#endif
if(CAUTIOUS || Vmregion->meth.meth != VM_MTBEST )
{
if(vmaddr(Vmregion,addr) == 0 )
return Vmregion;
for(k = 0; k < Regnum; ++k)
if(Region[k] && vmaddr(Region[k], addr) == 0 )
return Region[k];
return NIL(Vmalloc_t*);
}
else
{
Vmdata_t *vd = SEG(BLOCK(addr))->vmdt;
if(Vmregion->data == vd )
return Vmregion;
for(k = 0; k < Regnum; ++k)
if(Region[k] && Region[k]->data == vd)
return Region[k];
return NIL(Vmalloc_t*);
}
}
typedef struct _regfree_s
{ struct _regfree_s* next;
} Regfree_t;
static Regfree_t *Regfree;
static void addfreelist(Regfree_t* data)
{
unsigned int k;
Regfree_t *head;
for(k = 0;; ASOLOOP(k) )
{ data->next = head = Regfree;
if(asocasptr(&Regfree, head, data) == (Void_t*)head )
return;
}
}
static void clrfreelist()
{
Regfree_t *list, *next;
Vmalloc_t *vm;
if(!(list = Regfree) )
return;
if(asocasptr(&Regfree, list, NIL(Regfree_t*)) != list )
return;
for(; list; list = next)
{ next = list->next;
if(vm = regionof((Void_t*)list))
{ if(asocasint(&vm->data->lock, 0, 1) == 0)
{ (void)(*vm->meth.freef)(vm, (Void_t*)list, 1);
vm->data->lock = 0;
}
else addfreelist(list);
}
}
}
typedef struct _regdisc_s
{ Vmdisc_t disc;
char slop[64];
} Regdisc_t;
static int regexcept(Vmalloc_t* vm, int type, Void_t* data, Vmdisc_t* disc)
{
if(type == VM_OPEN)
{ if(data)
*(Void_t**)data = data;
return 0;
}
return 0;
}
static Vmalloc_t* getregion(int* local)
{
Vmalloc_t *vm;
int p, pos;
static unsigned int Rand = 0xdeadbeef;
#define RAND() (Rand = Rand*16777617 + 3)
clrfreelist();
if(Regmax <= 0 )
{
*local = 1;
Vmregion->data->lock = 1;
return Vmregion;
}
else if(asocasint(&Vmregion->data->lock, 0, 1) == 0 )
{
*local = 1;
asoincint(&Regopen);
return Vmregion;
}
asoincint(&Regprobe);
if(Regnum == 0)
pos = 0;
else for(pos = p = RAND()%Regnum;; )
{ if(Region[p] && asocasint(&Region[p]->data->lock, 0, 1) == 0 )
{ *local = 1;
asoincint(&Regopen);
return Region[p];
}
if((p = (p+1)%Regnum) == pos )
break;
}
while((p = Regnum) < Regmax)
if(asocasint(&Regnum, p, p+1) == p )
break;
if(p < Regmax)
{ static Regdisc_t Regdisc;
if(!Regdisc.disc.exceptf)
{ GETPAGESIZE(_Vmpagesize);
memcpy(&Regdisc, Vmdcsystem, Vmdcsystem->size);
Regdisc.disc.round = ROUND(_Vmpagesize, 64*1024);
Regdisc.disc.exceptf = regexcept;
}
ASSERT(Region[p] == NIL(Vmalloc_t*));
if((vm = vmopen(&Regdisc.disc, Vmbest, VM_SHARE)) != NIL(Vmalloc_t*) )
{ vm->data->lock = 1;
*local = 1;
asoincint(&Regopen);
return (Region[p] = vm);
}
else Region[p] = Vmregion;
}
vm = Region[pos] ? Region[pos] : Vmregion;
if(asocasint(&vm->data->lock, 0, 1) == 0)
{ *local = 1;
asoincint(&Regopen);
}
else
{ *local = 0;
asoincint(&Reglock);
}
return vm;
}
#if __STD_C
extern Void_t* calloc(reg size_t n_obj, reg size_t s_obj)
#else
extern Void_t* calloc(n_obj, s_obj)
reg size_t n_obj;
reg size_t s_obj;
#endif
{
Void_t *addr;
Vmalloc_t *vm;
int local = 0;
VMFLINIT();
vm = getregion(&local);
addr = (*vm->meth.resizef)(vm, NIL(Void_t*), n_obj*s_obj, VM_RSZERO, local);
if(local)
{ ASSERT(vm->data->lock == 1);
vm->data->lock = 0;
}
return VMRECORD(addr);
}
#if __STD_C
extern Void_t* malloc(reg size_t size)
#else
extern Void_t* malloc(size)
reg size_t size;
#endif
{
Void_t *addr;
Vmalloc_t *vm;
int local = 0;
VMFLINIT();
vm = getregion(&local);
addr = (*vm->meth.allocf)(vm, size, local);
if(local)
{ ASSERT(vm->data->lock == 1);
vm->data->lock = 0;
}
return VMRECORD(addr);
}
#if __STD_C
extern Void_t* realloc(reg Void_t* data, reg size_t size)
#else
extern Void_t* realloc(data,size)
reg Void_t* data;
reg size_t size;
#endif
{
ssize_t copy;
Void_t *addr;
Vmalloc_t *vm;
VMFLINIT();
if(!data)
return malloc(size);
else if((vm = regionof(data)) )
{ if(vm == Vmregion && vm != Vmheap)
{ addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 0);
return VMRECORD(addr);
}
if(asocasint(&vm->data->lock, 0, 1) == 0 )
{ addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 1);
vm->data->lock = 0;
return VMRECORD(addr);
}
else if(Regmax > 0 && Vmregion == Vmheap && (addr = malloc(size)) )
{ if((copy = SIZE(BLOCK(data))&~BITS) > size )
copy = size;
memcpy(addr, data, copy);
addfreelist((Regfree_t*)data);
return VMRECORD(addr);
}
else
{ addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 0);
return VMRECORD(addr);
}
}
else
{
#if USE_NATIVE
#undef realloc
#if __STD_C
extern Void_t* realloc(Void_t*, size_t);
#else
extern Void_t* realloc();
#endif
return realloc(data, size);
#else
return NIL(Void_t*);
#endif
}
}
#if __STD_C
extern void free(reg Void_t* data)
#else
extern void free(data)
reg Void_t* data;
#endif
{
Vmalloc_t *vm;
VMFLINIT();
if(!data || (_Vmassert & VM_keep))
return;
else if((vm = regionof(data)) )
{
if(vm == Vmregion && Vmregion != Vmheap || (_Vmassert & VM_free))
(void)(*vm->meth.freef)(vm, data, 0);
else addfreelist((Regfree_t*)data);
return;
}
else
{
#if USE_NATIVE
#undef free
#if __STD_C
extern void free(Void_t*);
#else
extern void free();
#endif
free(data);
#endif
return;
}
}
#if __STD_C
extern void cfree(reg Void_t* data)
#else
extern void cfree(data)
reg Void_t* data;
#endif
{
free(data);
}
#if __STD_C
extern Void_t* memalign(reg size_t align, reg size_t size)
#else
extern Void_t* memalign(align, size)
reg size_t align;
reg size_t size;
#endif
{
Void_t *addr;
Vmalloc_t *vm;
int local = 0;
VMFLINIT();
vm = getregion(&local);
VMBLOCK
addr = (*vm->meth.alignf)(vm, size, align, local);
if(local)
{ ASSERT(vm->data->lock == 1);
vm->data->lock = 0;
}
VMUNBLOCK
return VMRECORD(addr);
}
#if __STD_C
extern int posix_memalign(reg Void_t **memptr, reg size_t align, reg size_t size)
#else
extern int posix_memalign(memptr, align, size)
reg Void_t** memptr;
reg size_t align;
reg size_t size;
#endif
{
Void_t *mem;
if(align == 0 || (align%sizeof(Void_t*)) != 0 || ((align-1)&align) != 0 )
return EINVAL;
if(!(mem = memalign(align, size)) )
return ENOMEM;
*memptr = mem;
return 0;
}
#if __STD_C
extern Void_t* valloc(reg size_t size)
#else
extern Void_t* valloc(size)
reg size_t size;
#endif
{
VMFLINIT();
GETPAGESIZE(_Vmpagesize);
return VMRECORD(memalign(_Vmpagesize, size));
}
#if __STD_C
extern Void_t* pvalloc(reg size_t size)
#else
extern Void_t* pvalloc(size)
reg size_t size;
#endif
{
VMFLINIT();
GETPAGESIZE(_Vmpagesize);
return VMRECORD(memalign(_Vmpagesize, ROUND(size,_Vmpagesize)) );
}
#if !_PACKAGE_ast
#if __STD_C
char* strdup(const char* s)
#else
char* strdup(s)
char* s;
#endif
{
char *ns;
size_t n;
if(!s)
return NIL(char*);
else
{ n = strlen(s);
if((ns = malloc(n+1)) )
memcpy(ns,s,n+1);
return ns;
}
}
#endif
#if !_lib_alloca || _mal_alloca
#ifndef _stk_down
#define _stk_down 0
#endif
typedef struct _alloca_s Alloca_t;
union _alloca_u
{ struct
{ char* addr;
Alloca_t* next;
} head;
char array[ALIGN];
};
struct _alloca_s
{ union _alloca_u head;
Vmuchar_t data[1];
};
#if __STD_C
extern Void_t* alloca(size_t size)
#else
extern Void_t* alloca(size)
size_t size;
#endif
{ char array[ALIGN];
char* file;
int line;
Void_t* func;
Alloca_t* f;
Vmalloc_t *vm;
static Alloca_t* Frame;
VMFLINIT();
VMFLF(Vmregion,file,line,func);
while(Frame)
{ if(( _stk_down && &array[0] > Frame->head.head.addr) ||
(!_stk_down && &array[0] < Frame->head.head.addr) )
{ f = Frame; Frame = f->head.head.next;
if((vm = regionof(f)) )
(void)(*vm->meth.freef)(vm, f, 0);
}
else break;
}
Vmregion->file = file;
Vmregion->line = line;
Vmregion->func = func;
f = (Alloca_t*)(*Vmregion->meth.allocf)(Vmregion, size+sizeof(Alloca_t)-1, 0);
f->head.head.addr = &array[0];
f->head.head.next = Frame;
Frame = f;
return (Void_t*)f->data;
}
#endif
#if _map_malloc
#define USE_NATIVE 0
#else
#if _malloc_hook
static void vm_free_hook(void* ptr, const void* caller)
{
free(ptr);
}
static void* vm_malloc_hook(size_t size, const void* caller)
{
void* r;
r = malloc(size);
return r;
}
static void* vm_memalign_hook(size_t align, size_t size, const void* caller)
{
void* r;
r = memalign(align, size);
return r;
}
static void* vm_realloc_hook(void* ptr, size_t size, const void* caller)
{
void* r;
r = realloc(ptr, size);
return r;
}
static void vm_initialize_hook(void)
{
__free_hook = vm_free_hook;
__malloc_hook = vm_malloc_hook;
__memalign_hook = vm_memalign_hook;
__realloc_hook = vm_realloc_hook;
}
typeof (__malloc_initialize_hook) __malloc_initialize_hook = vm_initialize_hook;
#if 0
void __attribute__ ((constructor)) vm_initialize_initialize_hook(void)
{
vm_initialize_hook();
__malloc_initialize_hook = vm_initialize_hook;
}
#endif
#else
#if __lib__malloc
extern Void_t* F2(_calloc, size_t,n, size_t,m) { return calloc(n, m); }
extern Void_t F1(_cfree, Void_t*,p) { free(p); }
extern Void_t F1(_free, Void_t*,p) { free(p); }
extern Void_t* F1(_malloc, size_t,n) { return malloc(n); }
#if _lib_memalign
extern Void_t* F2(_memalign, size_t,a, size_t,n) { return memalign(a, n); }
#endif
#if _lib_pvalloc
extern Void_t* F1(_pvalloc, size_t,n) { return pvalloc(n); }
#endif
extern Void_t* F2(_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
#if _lib_valloc
extern Void_t* F1(_valloc, size_t,n) { return valloc(n); }
#endif
#endif
#if _lib___malloc
extern Void_t* F2(__calloc, size_t,n, size_t,m) { return calloc(n, m); }
extern Void_t F1(__cfree, Void_t*,p) { free(p); }
extern Void_t F1(__free, Void_t*,p) { free(p); }
extern Void_t* F1(__malloc, size_t,n) { return malloc(n); }
#if _lib_memalign
extern Void_t* F2(__memalign, size_t,a, size_t,n) { return memalign(a, n); }
#endif
#if _lib_pvalloc
extern Void_t* F1(__pvalloc, size_t,n) { return pvalloc(n); }
#endif
extern Void_t* F2(__realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
#if _lib_valloc
extern Void_t* F1(__valloc, size_t,n) { return valloc(n); }
#endif
#endif
#if _lib___libc_malloc
extern Void_t* F2(__libc_calloc, size_t,n, size_t,m) { return calloc(n, m); }
extern Void_t F1(__libc_cfree, Void_t*,p) { free(p); }
extern Void_t F1(__libc_free, Void_t*,p) { free(p); }
extern Void_t* F1(__libc_malloc, size_t,n) { return malloc(n); }
#if _lib_memalign
extern Void_t* F2(__libc_memalign, size_t,a, size_t,n) { return memalign(a, n); }
#endif
#if _lib_pvalloc
extern Void_t* F1(__libc_pvalloc, size_t,n) { return pvalloc(n); }
#endif
extern Void_t* F2(__libc_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
#if _lib_valloc
extern Void_t* F1(__libc_valloc, size_t,n) { return valloc(n); }
#endif
#endif
#endif
#endif
#undef extern
#if _hdr_malloc
#undef calloc
#define calloc ______calloc
#undef cfree
#define cfree ______cfree
#undef free
#define free ______free
#undef malloc
#define malloc ______malloc
#undef pvalloc
#define pvalloc ______pvalloc
#undef realloc
#define realloc ______realloc
#undef valloc
#define valloc ______valloc
#if !_UWIN
#include <malloc.h>
typedef struct mallinfo Mallinfo_t;
typedef struct mstats Mstats_t;
#endif
#if defined(__EXPORT__)
#define extern __EXPORT__
#endif
#if _lib_mallopt
#if __STD_C
extern int mallopt(int cmd, int value)
#else
extern int mallopt(cmd, value)
int cmd;
int value;
#endif
{
VMFLINIT();
return 0;
}
#endif
#if _lib_mallinfo && _mem_arena_mallinfo
#if __STD_C
extern Mallinfo_t mallinfo(void)
#else
extern Mallinfo_t mallinfo()
#endif
{
Vmstat_t sb;
Mallinfo_t mi;
VMFLINIT();
memset(&mi,0,sizeof(mi));
if(vmstat(Vmregion,&sb) >= 0)
{ mi.arena = sb.extent;
mi.ordblks = sb.n_busy+sb.n_free;
mi.uordblks = sb.s_busy;
mi.fordblks = sb.s_free;
}
return mi;
}
#endif
#if _lib_mstats && _mem_bytes_total_mstats
#if __STD_C
extern Mstats_t mstats(void)
#else
extern Mstats_t mstats()
#endif
{
Vmstat_t sb;
Mstats_t ms;
VMFLINIT();
memset(&ms,0,sizeof(ms));
if(vmstat(Vmregion,&sb) >= 0)
{ ms.bytes_total = sb.extent;
ms.chunks_used = sb.n_busy;
ms.bytes_used = sb.s_busy;
ms.chunks_free = sb.n_free;
ms.bytes_free = sb.s_free;
}
return ms;
}
#endif
#undef extern
#endif
#else
#define setregmax(n)
#undef calloc
extern Void_t* calloc _ARG_((size_t, size_t));
#undef cfree
extern void cfree _ARG_((Void_t*));
#undef free
extern void free _ARG_((Void_t*));
#undef malloc
extern Void_t* malloc _ARG_((size_t));
#if _lib_memalign
#undef memalign
extern Void_t* memalign _ARG_((size_t, size_t));
#endif
#if _lib_pvalloc
#undef pvalloc
extern Void_t* pvalloc _ARG_((size_t));
#endif
#undef realloc
extern Void_t* realloc _ARG_((Void_t*, size_t));
#if _lib_valloc
#undef valloc
extern Void_t* valloc _ARG_((size_t));
#endif
#if defined(__EXPORT__)
#define extern __EXPORT__
#endif
#if !_malloc_hook
extern Void_t F1(_ast_free, Void_t*,p) { free(p); }
extern Void_t* F1(_ast_malloc, size_t,n) { return malloc(n); }
#if _lib_memalign
extern Void_t* F2(_ast_memalign, size_t,a, size_t,n) { return memalign(a, n); }
#endif
extern Void_t* F2(_ast_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
#endif
extern Void_t* F2(_ast_calloc, size_t,n, size_t,m) { return calloc(n, m); }
extern Void_t F1(_ast_cfree, Void_t*,p) { free(p); }
#if _lib_pvalloc
extern Void_t* F1(_ast_pvalloc, size_t,n) { return pvalloc(n); }
#endif
#if _lib_valloc
extern Void_t* F1(_ast_valloc, size_t,n) { return valloc(n); }
#endif
#undef extern
#if _hdr_malloc
#undef mallinfo
#undef mallopt
#undef mstats
#define calloc ______calloc
#define cfree ______cfree
#define free ______free
#define malloc ______malloc
#define pvalloc ______pvalloc
#define realloc ______realloc
#define valloc ______valloc
#if !_UWIN
#if !_malloc_hook
#include <malloc.h>
#endif
typedef struct mallinfo Mallinfo_t;
typedef struct mstats Mstats_t;
#endif
#if defined(__EXPORT__)
#define extern __EXPORT__
#endif
#if _lib_mallopt
extern int F2(_ast_mallopt, int,cmd, int,value) { return mallopt(cmd, value); }
#endif
#if _lib_mallinfo && _mem_arena_mallinfo
extern Mallinfo_t F0(_ast_mallinfo, void) { return mallinfo(); }
#endif
#if _lib_mstats && _mem_bytes_total_mstats
extern Mstats_t F0(_ast_mstats, void) { return mstats(); }
#endif
#undef extern
#endif
#endif
#if __STD_C
static Vmulong_t atou(char** sp)
#else
static Vmulong_t atou(sp)
char** sp;
#endif
{
char* s = *sp;
Vmulong_t v = 0;
if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') )
{ for(s += 2; *s; ++s)
{ if(*s >= '0' && *s <= '9')
v = (v << 4) + (*s - '0');
else if(*s >= 'a' && *s <= 'f')
v = (v << 4) + (*s - 'a') + 10;
else if(*s >= 'A' && *s <= 'F')
v = (v << 4) + (*s - 'A') + 10;
else break;
}
}
else
{ for(; *s; ++s)
{ if(*s >= '0' && *s <= '9')
v = v*10 + (*s - '0');
else break;
}
}
*sp = s;
return v;
}
#if __STD_C
static char* insertpid(char* begs, char* ends)
#else
static char* insertpid(begs,ends)
char* begs;
char* ends;
#endif
{ int pid;
char* s;
if((pid = getpid()) < 0)
return NIL(char*);
s = ends;
do
{ if(s == begs)
return NIL(char*);
*--s = '0' + pid%10;
} while((pid /= 10) > 0);
while(s < ends)
*begs++ = *s++;
return begs;
}
#define FD_PRIVATE (3*OPEN_MAX/4)
#if __STD_C
int _vmfd(int fd)
#else
int _vmfd(fd)
int fd;
#endif
{
int pd;
if (fd >= 0)
{
if (fd < FD_PRIVATE && (pd = fcntl(fd, F_DUPFD, FD_PRIVATE)) >= 0)
{
close(fd);
fd = pd;
}
#ifdef FD_CLOEXEC
fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif
}
return fd;
}
#if __STD_C
static int createfile(char* file)
#else
static int createfile(file)
char* file;
#endif
{
char buf[1024];
char *next, *endb;
int fd;
next = buf;
endb = buf + sizeof(buf);
while(*file)
{ if(*file == '%')
{ switch(file[1])
{
case 'p' :
if(!(next = insertpid(next,endb)) )
return -1;
file += 2;
break;
default :
goto copy;
}
}
else
{ copy:
*next++ = *file++;
}
if(next >= endb)
return -1;
}
*next = '\0';
file = buf;
if (*file == '&' && *(file += 1) || strncmp(file, "/dev/fd/", 8) == 0 && *(file += 8))
fd = dup((int)atou(&file));
else if (*file)
{
#if _PACKAGE_ast
fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, CREAT_MODE);
#else
fd = creat(file, CREAT_MODE);
#endif
fd = _vmfd(fd);
}
else
return -1;
#if _PACKAGE_ast
#ifdef FD_CLOEXEC
if (fd >= 0)
fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif
#endif
return fd;
}
#if __STD_C
static void pfprint(void)
#else
static void pfprint()
#endif
{
if(Vmregion->meth.meth == VM_MTPROFILE)
vmprofile(Vmregion,_Vmpffd);
}
#define COPY(t,e,f) while ((*t = *f++) && t < e) t++
#if __STD_C
void _vmoptions(void)
#else
void _vmoptions()
#endif
{
Vmalloc_t* vm = 0;
char* trace = 0;
char* s;
char* t;
char* v;
Vmulong_t n;
int fd;
char buf[1024];
_Vmoptions = 1;
t = buf;
v = &buf[sizeof(buf)-1];
if (s = getenv("VMALLOC_OPTIONS"))
COPY(t, v, s);
if (t > buf)
{
*t = 0;
s = buf;
for (;;)
{
while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
s++;
if (!*(t = s))
break;
v = 0;
while (*s)
if (*s == ',' || *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
{
*s++ = 0;
break;
}
else if (!v && *s == '=')
{
*s++ = 0;
if (!*(v = s))
v = 0;
}
else
s++;
if (t[0] == 'n' && t[1] == 'o')
continue;
switch (t[0])
{
case 'a':
if (!vm)
vm = vmopen(Vmdcsystem, Vmdebug, 0);
if (vm && vm->meth.meth == VM_MTDEBUG)
vmset(vm, VM_DBABORT, 1);
else
_Vmassert |= VM_abort;
break;
case 'b':
_Vmassert |= VM_break;
break;
case 'c':
_Vmassert |= VM_check;
break;
case 'f':
_Vmassert |= VM_free;
break;
case 'k':
_Vmassert |= VM_keep;
break;
case 'm':
if (v)
switch (t[1])
{
case 'e':
if (!vm)
{
if ((v[0] == 'V' || v[0] == 'v') && (v[1] == 'M' || v[1] == 'm'))
v += 2;
if (strcmp(v, "debug") == 0)
vm = vmopen(Vmdcsystem, Vmdebug, 0);
else if (strcmp(v, "profile") == 0)
vm = vmopen(Vmdcsystem, Vmprofile, 0);
else if (strcmp(v, "last") == 0)
vm = vmopen(Vmdcsystem, Vmlast, 0);
else if (strcmp(v, "best") == 0)
vm = Vmheap;
}
break;
case 'm':
_Vmassert |= VM_mmap;
break;
}
break;
case 'p':
if (v)
switch (t[1])
{
case 'e':
if (!vm)
vm = vmopen(Vmdcsystem, Vmdebug, 0);
if (vm && vm->meth.meth == VM_MTDEBUG)
_Vmdbcheck = atou(&v);
break;
case 'r':
if (!vm)
vm = vmopen(Vmdcsystem, Vmprofile, 0);
if (v && vm && vm->meth.meth == VM_MTPROFILE)
_Vmpffd = createfile(v);
break;
}
break;
case 's':
if (!vm)
vm = vmopen(Vmdcsystem, Vmdebug, 0);
if (v && vm && vm->meth.meth == VM_MTDEBUG)
_Vmdbstart = atou(&v);
break;
case 't':
trace = v;
break;
case 'w':
if (t[1] == 'a')
switch (t[2])
{
case 'r':
if (!vm)
vm = vmopen(Vmdcsystem, Vmdebug, 0);
if (v && vm && vm->meth.meth == VM_MTDEBUG && (fd = createfile(v)) >= 0)
vmdebug(fd);
break;
case 't':
if (!vm)
vm = vmopen(Vmdcsystem, Vmdebug, 0);
if (v && vm && vm->meth.meth == VM_MTDEBUG && (n = atou(&v)) >= 0)
vmdbwatch((Void_t*)n);
break;
}
break;
}
}
}
if (vm)
{
if (vm->meth.meth == VM_MTDEBUG)
_Vmdbcheck = 1;
Vmregion = vm;
}
if (trace)
{
setregmax(0);
if ((fd = createfile(trace)) >= 0)
{
vmset(Vmregion, VM_TRACE, 1);
vmtrace(fd);
}
}
else if (Vmregion != Vmheap || asometh(0, 0)->type == ASO_SIGNAL)
setregmax(0);
if (vm && vm->meth.meth == VM_MTPROFILE)
{
if (_Vmpffd < 0)
_Vmpffd = 2;
atexit(pfprint);
}
else if (_Vmpffd >= 0)
{
close(_Vmpffd);
_Vmpffd = -1;
}
}
int
#if __STD_C
_vmkeep(int v)
#else
_vmkeep(v)
int v;
#endif
{
int r;
r = !!(_Vmassert & VM_keep);
if (v)
_Vmassert |= VM_keep;
else
_Vmassert &= ~VM_keep;
return r;
}
#endif