1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1985-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Common Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.opensource.org/licenses/cpl1.0.txt * 11* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12* * 13* Information and Software Systems Research * 14* AT&T Research * 15* Florham Park NJ * 16* * 17* Glenn Fowler <gsf@research.att.com> * 18* David Korn <dgk@research.att.com> * 19* Phong Vo <kpv@research.att.com> * 20* * 21***********************************************************************/ 22#if defined(_UWIN) && defined(_BLD_ast) 23 24void _STUB_malloc(){} 25 26#else 27 28#if _UWIN 29 30#define calloc ______calloc 31#define _ast_free ______free 32#define malloc ______malloc 33#define mallinfo ______mallinfo 34#define mallopt ______mallopt 35#define mstats ______mstats 36#define realloc ______realloc 37 38#define _STDLIB_H_ 1 39 40extern int atexit(void(*)(void)); 41extern char* getenv(const char*); 42 43#endif 44 45#include "vmhdr.h" 46#include <errno.h> 47 48#if _UWIN 49 50#include <malloc.h> 51 52#define _map_malloc 1 53#define _mal_alloca 1 54 55#undef calloc 56#define calloc _ast_calloc 57#undef _ast_free 58#define free _ast_free 59#undef malloc 60#define malloc _ast_malloc 61#undef mallinfo 62typedef struct ______mallinfo Mallinfo_t; 63#undef mallopt 64#undef mstats 65typedef struct ______mstats Mstats_t; 66#undef realloc 67#define realloc _ast_realloc 68 69#endif 70 71#if __STD_C 72#define F0(f,t0) f(t0) 73#define F1(f,t1,a1) f(t1 a1) 74#define F2(f,t1,a1,t2,a2) f(t1 a1, t2 a2) 75#else 76#define F0(f,t0) f() 77#define F1(f,t1,a1) f(a1) t1 a1; 78#define F2(f,t1,a1,t2,a2) f(a1, a2) t1 a1; t2 a2; 79#endif 80 81/* 82 * define _AST_std_malloc=1 to force the standard malloc 83 * if _map_malloc is also defined then _ast_malloc etc. 84 * will simply call malloc etc. 85 */ 86 87#if !defined(_AST_std_malloc) && __CYGWIN__ 88#define _AST_std_malloc 1 89#endif 90 91/* malloc compatibility functions 92** 93** These are aware of debugging/profiling and are driven by the 94** VMALLOC_OPTIONS environment variable which is a space-separated 95** list of [no]name[=value] options: 96** 97** abort if Vmregion==Vmdebug then VM_DBABORT is set, 98** otherwise _BLD_debug enabled assertions abort() 99** on failure 100** check if Vmregion==Vmbest then the region is checked every op 101** method=m sets Vmregion=m if not defined, m (Vm prefix optional) 102** may be one of { best debug last profile } 103** mmap prefer mmap() over brk() for region allocation 104** period=n sets Vmregion=Vmdebug if not defined, if 105** Vmregion==Vmdebug the region is checked every n ops 106** profile=f sets Vmregion=Vmprofile if not set, if 107** Vmregion==Vmprofile then profile info printed to file f 108** region if Vmregion==Vmbest then block free verifies 109** that the block belongs to the region 110** start=n sets Vmregion=Vmdebug if not defined, if 111** Vmregion==Vmdebug region checking starts after n ops 112** trace=f enables tracing to file f 113** warn=f sets Vmregion=Vmdebug if not defined, if 114** Vmregion==Vmdebug then warnings printed to file f 115** watch=a sets Vmregion=Vmdebug if not defined, if 116** Vmregion==Vmdebug then address a is watched 117** 118** Output files are created if they don't exist. &n and /dev/fd/n name 119** the file descriptor n which must be open for writing. The pattern %p 120** in a file name is replaced by the process ID. 121** 122** VMALLOC_OPTIONS combines the features of these previously used env vars: 123** { VMDEBUG VMETHOD VMPROFILE VMTRACE } 124** 125** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94. 126*/ 127 128#if _sys_stat 129#include <sys/stat.h> 130#endif 131#include <fcntl.h> 132 133#ifdef S_IRUSR 134#define CREAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 135#else 136#define CREAT_MODE 0644 137#endif 138 139static Vmulong_t _Vmdbstart = 0; 140static Vmulong_t _Vmdbcheck = 0; 141static Vmulong_t _Vmdbtime = 0; 142static int _Vmpffd = -1; 143 144#if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc 145 146#if !_map_malloc 147#undef calloc 148#undef cfree 149#undef free 150#undef mallinfo 151#undef malloc 152#undef mallopt 153#undef memalign 154#undef mstats 155#undef realloc 156#undef valloc 157#endif 158 159#if _WINIX 160 161#include <ast_windows.h> 162 163#if _UWIN 164 165#define VMRECORD(p) _vmrecord(p) 166#define VMBLOCK { int _vmblock = _sigblock(); 167#define VMUNBLOCK _sigunblock(_vmblock); } 168 169extern int _sigblock(void); 170extern void _sigunblock(int); 171extern unsigned long _record[2048]; 172 173__inline Void_t* _vmrecord(Void_t* p) 174{ 175 register unsigned long v = ((unsigned long)p)>>16; 176 177 _record[v>>5] |= 1<<((v&0x1f)); 178 return p; 179} 180 181#else 182 183#define getenv(s) lcl_getenv(s) 184 185static char* 186lcl_getenv(const char* s) 187{ 188 int n; 189 static char buf[512]; 190 191 if (!(n = GetEnvironmentVariable(s, buf, sizeof(buf))) || n > sizeof(buf)) 192 return 0; 193 return buf; 194} 195 196#endif /* _UWIN */ 197 198#endif /* _WINIX */ 199 200#ifndef VMRECORD 201#define VMRECORD(p) (p) 202#define VMBLOCK 203#define VMUNBLOCK 204#endif 205 206#if defined(__EXPORT__) 207#define extern extern __EXPORT__ 208#endif 209 210static int _Vmflinit = 0; 211#define VMFLINIT() \ 212 { if(!_Vmflinit) vmflinit(); \ 213 if(_Vmdbcheck) \ 214 { if(_Vmdbtime < _Vmdbstart) _Vmdbtime += 1; \ 215 else if((_Vmdbtime += 1) < _Vmdbstart) _Vmdbtime = _Vmdbstart; \ 216 if(_Vmdbtime >= _Vmdbstart && (_Vmdbtime % _Vmdbcheck) == 0 && \ 217 Vmregion->meth.meth == VM_MTDEBUG) \ 218 vmdbcheck(Vmregion); \ 219 } \ 220 } 221 222#if __STD_C 223static int vmflinit(void) 224#else 225static int vmflinit() 226#endif 227{ 228 char* file; 229 int line; 230 Void_t* func; 231 232 /* this must be done now to avoid any inadvertent recursion (more below) */ 233 _Vmflinit = 1; 234 VMFLF(Vmregion,file,line,func); 235 236 /* if getenv() calls malloc(), the options may not affect the eventual region */ 237 VMOPTIONS(); 238 239 /* reset file and line number to correct values for the call */ 240 Vmregion->file = file; 241 Vmregion->line = line; 242 Vmregion->func = func; 243 244 return 0; 245} 246 247#if __STD_C 248extern Void_t* calloc(reg size_t n_obj, reg size_t s_obj) 249#else 250extern Void_t* calloc(n_obj, s_obj) 251reg size_t n_obj; 252reg size_t s_obj; 253#endif 254{ 255 VMFLINIT(); 256 return VMRECORD((*Vmregion->meth.resizef)(Vmregion,NIL(Void_t*),n_obj*s_obj,VM_RSZERO)); 257} 258 259#if __STD_C 260extern Void_t* malloc(reg size_t size) 261#else 262extern Void_t* malloc(size) 263reg size_t size; 264#endif 265{ 266 VMFLINIT(); 267 return VMRECORD((*Vmregion->meth.allocf)(Vmregion,size)); 268} 269 270#if __STD_C 271extern Void_t* realloc(reg Void_t* data, reg size_t size) 272#else 273extern Void_t* realloc(data,size) 274reg Void_t* data; /* block to be reallocated */ 275reg size_t size; /* new size */ 276#endif 277{ 278#if USE_NATIVE 279#undef realloc 280#if __STD_C 281 extern Void_t* realloc(Void_t*, size_t); 282#else 283 extern Void_t* realloc(); 284#endif 285#endif 286 287 VMFLINIT(); 288 289#if _PACKAGE_ast 290 if(data && Vmregion->meth.meth != VM_MTDEBUG && 291#if !USE_NATIVE 292 !(Vmregion->data->mode&VM_TRUST) && 293#endif 294 (*Vmregion->meth.addrf)(Vmregion,data) != 0 ) 295 { 296#if USE_NATIVE 297 return realloc(data, size); 298#else 299 Void_t* newdata; 300 if((newdata = (*Vmregion->meth.allocf)(Vmregion,size)) ) 301 memcpy(newdata,data,size); 302 return VMRECORD(newdata); 303#endif 304 } 305#endif 306 307#if USE_NATIVE 308 { Void_t* newdata; 309 if (newdata = (*Vmregion->meth.resizef)(Vmregion,data,size,VM_RSCOPY|VM_RSMOVE)) 310 return newdata; 311 return VMRECORD(realloc(data, size)); 312 } 313#else 314 return VMRECORD((*Vmregion->meth.resizef)(Vmregion,data,size,VM_RSCOPY|VM_RSMOVE)); 315#endif 316} 317 318#if __STD_C 319extern void free(reg Void_t* data) 320#else 321extern void free(data) 322reg Void_t* data; 323#endif 324{ 325#if USE_NATIVE 326#undef free 327#if __STD_C 328 extern void free(Void_t*); 329#else 330 extern void free(); 331#endif 332#endif 333 334 VMFLINIT(); 335 336#if _PACKAGE_ast 337 if(data && Vmregion->meth.meth != VM_MTDEBUG && 338#if !USE_NATIVE 339 !(Vmregion->data->mode&VM_TRUST) && 340#endif 341 (*Vmregion->meth.addrf)(Vmregion,data) != 0) 342 { 343#if USE_NATIVE 344 free(data); 345#endif 346 return; 347 } 348#endif 349 350#if USE_NATIVE 351 if ((*Vmregion->meth.freef)(Vmregion,data) != 0) 352 free(data); 353#else 354 (void)(*Vmregion->meth.freef)(Vmregion,data); 355#endif 356} 357 358#if __STD_C 359extern void cfree(reg Void_t* data) 360#else 361extern void cfree(data) 362reg Void_t* data; 363#endif 364{ 365 free(data); 366} 367 368#if __STD_C 369extern Void_t* memalign(reg size_t align, reg size_t size) 370#else 371extern Void_t* memalign(align, size) 372reg size_t align; 373reg size_t size; 374#endif 375{ 376 Void_t* addr; 377 378 VMFLINIT(); 379 VMBLOCK 380 addr = VMRECORD((*Vmregion->meth.alignf)(Vmregion,size,align)); 381 VMUNBLOCK 382 return addr; 383} 384 385#if __STD_C 386extern int posix_memalign(reg Void_t **memptr, reg size_t align, reg size_t size) 387#else 388extern int posix_memalign(memptr, align, size) 389reg Void_t** memptr; 390reg size_t align; 391reg size_t size; 392#endif 393{ 394 Void_t *mem; 395 396 if(align == 0 || (align%sizeof(Void_t*)) != 0 || ((align-1)&align) != 0 ) 397 return EINVAL; 398 399 if(!(mem = memalign(align, size)) ) 400 return ENOMEM; 401 402 *memptr = mem; 403 return 0; 404} 405 406#if __STD_C 407extern Void_t* valloc(reg size_t size) 408#else 409extern Void_t* valloc(size) 410reg size_t size; 411#endif 412{ 413 VMFLINIT(); 414 GETPAGESIZE(_Vmpagesize); 415 return VMRECORD((*Vmregion->meth.alignf)(Vmregion,size,_Vmpagesize)); 416} 417 418#if __STD_C 419extern Void_t* pvalloc(reg size_t size) 420#else 421extern Void_t* pvalloc(size) 422reg size_t size; 423#endif 424{ 425 VMFLINIT(); 426 GETPAGESIZE(_Vmpagesize); 427 return VMRECORD((*Vmregion->meth.alignf)(Vmregion,ROUND(size,_Vmpagesize),_Vmpagesize)); 428} 429 430#if !_PACKAGE_ast 431#if __STD_C 432char* strdup(const char* s) 433#else 434char* strdup(s) 435char* s; 436#endif 437{ 438 char *ns; 439 size_t n; 440 441 if(!s) 442 return NIL(char*); 443 else 444 { n = strlen(s); 445 if((ns = malloc(n+1)) ) 446 memcpy(ns,s,n+1); 447 return ns; 448 } 449} 450#endif /* _PACKAGE_ast */ 451 452#if !_lib_alloca || _mal_alloca 453#ifndef _stk_down 454#define _stk_down 0 455#endif 456typedef struct _alloca_s Alloca_t; 457union _alloca_u 458{ struct 459 { char* addr; 460 Alloca_t* next; 461 } head; 462 char array[ALIGN]; 463}; 464struct _alloca_s 465{ union _alloca_u head; 466 Vmuchar_t data[1]; 467}; 468 469#if __STD_C 470extern Void_t* alloca(size_t size) 471#else 472extern Void_t* alloca(size) 473size_t size; 474#endif 475{ char array[ALIGN]; 476 char* file; 477 int line; 478 Void_t* func; 479 reg Alloca_t* f; 480 static Alloca_t* Frame; 481 482 VMFLINIT(); 483 VMFLF(Vmregion,file,line,func); 484 while(Frame) 485 { if(( _stk_down && &array[0] > Frame->head.head.addr) || 486 (!_stk_down && &array[0] < Frame->head.head.addr) ) 487 { f = Frame; 488 Frame = f->head.head.next; 489 (void)(*Vmregion->meth.freef)(Vmregion,f); 490 } 491 else break; 492 } 493 494 Vmregion->file = file; 495 Vmregion->line = line; 496 Vmregion->func = func; 497 f = (Alloca_t*)(*Vmregion->meth.allocf)(Vmregion,size+sizeof(Alloca_t)-1); 498 499 f->head.head.addr = &array[0]; 500 f->head.head.next = Frame; 501 Frame = f; 502 503 return (Void_t*)f->data; 504} 505#endif /*!_lib_alloca || _mal_alloca*/ 506 507#if _map_malloc 508 509/* not sure of all the implications -- 0 is conservative for now */ 510#define USE_NATIVE 0 /* native free/realloc on non-vmalloc ptrs */ 511 512#else 513 514/* intercept _* __* __libc_* variants */ 515 516#if __lib__malloc 517extern Void_t* F2(_calloc, size_t,n, size_t,m) { return calloc(n, m); } 518extern Void_t F1(_cfree, Void_t*,p) { free(p); } 519extern Void_t F1(_free, Void_t*,p) { free(p); } 520extern Void_t* F1(_malloc, size_t,n) { return malloc(n); } 521#if _lib_memalign 522extern Void_t* F2(_memalign, size_t,a, size_t,n) { return memalign(a, n); } 523#endif 524#if _lib_pvalloc 525extern Void_t* F1(_pvalloc, size_t,n) { return pvalloc(n); } 526#endif 527extern Void_t* F2(_realloc, Void_t*,p, size_t,n) { return realloc(p, n); } 528#if _lib_valloc 529extern Void_t* F1(_valloc, size_t,n) { return valloc(n); } 530#endif 531#endif 532 533#if _lib___malloc 534extern Void_t* F2(__calloc, size_t,n, size_t,m) { return calloc(n, m); } 535extern Void_t F1(__cfree, Void_t*,p) { free(p); } 536extern Void_t F1(__free, Void_t*,p) { free(p); } 537extern Void_t* F1(__malloc, size_t,n) { return malloc(n); } 538#if _lib_memalign 539extern Void_t* F2(__memalign, size_t,a, size_t,n) { return memalign(a, n); } 540#endif 541#if _lib_pvalloc 542extern Void_t* F1(__pvalloc, size_t,n) { return pvalloc(n); } 543#endif 544extern Void_t* F2(__realloc, Void_t*,p, size_t,n) { return realloc(p, n); } 545#if _lib_valloc 546extern Void_t* F1(__valloc, size_t,n) { return valloc(n); } 547#endif 548#endif 549 550#if _lib___libc_malloc 551extern Void_t* F2(__libc_calloc, size_t,n, size_t,m) { return calloc(n, m); } 552extern Void_t F1(__libc_cfree, Void_t*,p) { free(p); } 553extern Void_t F1(__libc_free, Void_t*,p) { free(p); } 554extern Void_t* F1(__libc_malloc, size_t,n) { return malloc(n); } 555#if _lib_memalign 556extern Void_t* F2(__libc_memalign, size_t,a, size_t,n) { return memalign(a, n); } 557#endif 558#if _lib_pvalloc 559extern Void_t* F1(__libc_pvalloc, size_t,n) { return pvalloc(n); } 560#endif 561extern Void_t* F2(__libc_realloc, Void_t*,p, size_t,n) { return realloc(p, n); } 562#if _lib_valloc 563extern Void_t* F1(__libc_valloc, size_t,n) { return valloc(n); } 564#endif 565#endif 566 567#endif /* _map_malloc */ 568 569#undef extern 570 571#if _hdr_malloc /* need the mallint interface for statistics, etc. */ 572 573#undef calloc 574#define calloc ______calloc 575#undef cfree 576#define cfree ______cfree 577#undef free 578#define free ______free 579#undef malloc 580#define malloc ______malloc 581#undef pvalloc 582#define pvalloc ______pvalloc 583#undef realloc 584#define realloc ______realloc 585#undef valloc 586#define valloc ______valloc 587 588#if !_UWIN 589 590#include <malloc.h> 591 592typedef struct mallinfo Mallinfo_t; 593typedef struct mstats Mstats_t; 594 595#endif 596 597#if defined(__EXPORT__) 598#define extern __EXPORT__ 599#endif 600 601#if _lib_mallopt 602#if __STD_C 603extern int mallopt(int cmd, int value) 604#else 605extern int mallopt(cmd, value) 606int cmd; 607int value; 608#endif 609{ 610 VMFLINIT(); 611 return 0; 612} 613#endif /*_lib_mallopt*/ 614 615#if _lib_mallinfo && _mem_arena_mallinfo 616#if __STD_C 617extern Mallinfo_t mallinfo(void) 618#else 619extern Mallinfo_t mallinfo() 620#endif 621{ 622 Vmstat_t sb; 623 Mallinfo_t mi; 624 625 VMFLINIT(); 626 memset(&mi,0,sizeof(mi)); 627 if(vmstat(Vmregion,&sb) >= 0) 628 { mi.arena = sb.extent; 629 mi.ordblks = sb.n_busy+sb.n_free; 630 mi.uordblks = sb.s_busy; 631 mi.fordblks = sb.s_free; 632 } 633 return mi; 634} 635#endif /* _lib_mallinfo */ 636 637#if _lib_mstats && _mem_bytes_total_mstats 638#if __STD_C 639extern Mstats_t mstats(void) 640#else 641extern Mstats_t mstats() 642#endif 643{ 644 Vmstat_t sb; 645 Mstats_t ms; 646 647 VMFLINIT(); 648 memset(&ms,0,sizeof(ms)); 649 if(vmstat(Vmregion,&sb) >= 0) 650 { ms.bytes_total = sb.extent; 651 ms.chunks_used = sb.n_busy; 652 ms.bytes_used = sb.s_busy; 653 ms.chunks_free = sb.n_free; 654 ms.bytes_free = sb.s_free; 655 } 656 return ms; 657} 658#endif /*_lib_mstats*/ 659 660#undef extern 661 662#endif/*_hdr_malloc*/ 663 664#else 665 666/* 667 * even though there is no malloc override, still provide 668 * _ast_* counterparts for object compatibility 669 */ 670 671#undef calloc 672extern Void_t* calloc _ARG_((size_t, size_t)); 673 674#undef cfree 675extern void cfree _ARG_((Void_t*)); 676 677#undef free 678extern void free _ARG_((Void_t*)); 679 680#undef malloc 681extern Void_t* malloc _ARG_((size_t)); 682 683#if _lib_memalign 684#undef memalign 685extern Void_t* memalign _ARG_((size_t, size_t)); 686#endif 687 688#if _lib_pvalloc 689#undef pvalloc 690extern Void_t* pvalloc _ARG_((size_t)); 691#endif 692 693#undef realloc 694extern Void_t* realloc _ARG_((Void_t*, size_t)); 695 696#if _lib_valloc 697#undef valloc 698extern Void_t* valloc _ARG_((size_t)); 699#endif 700 701#if defined(__EXPORT__) 702#define extern __EXPORT__ 703#endif 704 705extern Void_t* F2(_ast_calloc, size_t,n, size_t,m) { return calloc(n, m); } 706extern Void_t F1(_ast_cfree, Void_t*,p) { free(p); } 707extern Void_t F1(_ast_free, Void_t*,p) { free(p); } 708extern Void_t* F1(_ast_malloc, size_t,n) { return malloc(n); } 709#if _lib_memalign 710extern Void_t* F2(_ast_memalign, size_t,a, size_t,n) { return memalign(a, n); } 711#endif 712#if _lib_pvalloc 713extern Void_t* F1(_ast_pvalloc, size_t,n) { return pvalloc(n); } 714#endif 715extern Void_t* F2(_ast_realloc, Void_t*,p, size_t,n) { return realloc(p, n); } 716#if _lib_valloc 717extern Void_t* F1(_ast_valloc, size_t,n) { return valloc(n); } 718#endif 719 720#undef extern 721 722#if _hdr_malloc 723 724#undef mallinfo 725#undef mallopt 726#undef mstats 727 728#define calloc ______calloc 729#define cfree ______cfree 730#define free ______free 731#define malloc ______malloc 732#define pvalloc ______pvalloc 733#define realloc ______realloc 734#define valloc ______valloc 735 736#if !_UWIN 737 738#include <malloc.h> 739 740typedef struct mallinfo Mallinfo_t; 741typedef struct mstats Mstats_t; 742 743#endif 744 745#if defined(__EXPORT__) 746#define extern __EXPORT__ 747#endif 748 749#if _lib_mallopt 750extern int F2(_ast_mallopt, int,cmd, int,value) { return mallopt(cmd, value); } 751#endif 752 753#if _lib_mallinfo && _mem_arena_mallinfo 754extern Mallinfo_t F0(_ast_mallinfo, void) { return mallinfo(); } 755#endif 756 757#if _lib_mstats && _mem_bytes_total_mstats 758extern Mstats_t F0(_ast_mstats, void) { return mstats(); } 759#endif 760 761#undef extern 762 763#endif /*_hdr_malloc*/ 764 765#endif /*!_std_malloc*/ 766 767#if __STD_C 768static Vmulong_t atou(char** sp) 769#else 770static Vmulong_t atou(sp) 771char** sp; 772#endif 773{ 774 char* s = *sp; 775 Vmulong_t v = 0; 776 777 if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') ) 778 { for(s += 2; *s; ++s) 779 { if(*s >= '0' && *s <= '9') 780 v = (v << 4) + (*s - '0'); 781 else if(*s >= 'a' && *s <= 'f') 782 v = (v << 4) + (*s - 'a') + 10; 783 else if(*s >= 'A' && *s <= 'F') 784 v = (v << 4) + (*s - 'A') + 10; 785 else break; 786 } 787 } 788 else 789 { for(; *s; ++s) 790 { if(*s >= '0' && *s <= '9') 791 v = v*10 + (*s - '0'); 792 else break; 793 } 794 } 795 796 *sp = s; 797 return v; 798} 799 800#if __STD_C 801static char* insertpid(char* begs, char* ends) 802#else 803static char* insertpid(begs,ends) 804char* begs; 805char* ends; 806#endif 807{ int pid; 808 char* s; 809 810 if((pid = getpid()) < 0) 811 return NIL(char*); 812 813 s = ends; 814 do 815 { if(s == begs) 816 return NIL(char*); 817 *--s = '0' + pid%10; 818 } while((pid /= 10) > 0); 819 while(s < ends) 820 *begs++ = *s++; 821 822 return begs; 823} 824 825#if __STD_C 826static int createfile(char* file) 827#else 828static int createfile(file) 829char* file; 830#endif 831{ 832 char buf[1024]; 833 char *next, *endb; 834 int fd; 835 836 next = buf; 837 endb = buf + sizeof(buf); 838 while(*file) 839 { if(*file == '%') 840 { switch(file[1]) 841 { 842 case 'p' : 843 if(!(next = insertpid(next,endb)) ) 844 return -1; 845 file += 2; 846 break; 847 default : 848 goto copy; 849 } 850 } 851 else 852 { copy: 853 *next++ = *file++; 854 } 855 856 if(next >= endb) 857 return -1; 858 } 859 860 *next = '\0'; 861 file = buf; 862 if (*file == '&' && *(file += 1) || strncmp(file, "/dev/fd/", 8) == 0 && *(file += 8)) 863 fd = dup((int)atou(&file)); 864 else if (*file) 865#if _PACKAGE_ast 866 fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, CREAT_MODE); 867#else 868 fd = creat(file, CREAT_MODE); 869#endif 870 else 871 return -1; 872#if _PACKAGE_ast 873#ifdef FD_CLOEXEC 874 if (fd >= 0) 875 fcntl(fd, F_SETFD, FD_CLOEXEC); 876#endif 877#endif 878 return fd; 879} 880 881#if __STD_C 882static void pfprint(void) 883#else 884static void pfprint() 885#endif 886{ 887 if(Vmregion->meth.meth == VM_MTPROFILE) 888 vmprofile(Vmregion,_Vmpffd); 889} 890 891/* 892 * initialize runtime options from the VMALLOC_OPTIONS env var 893 */ 894 895#define COPY(t,e,f) while ((*t = *f++) && t < e) t++ 896 897#if __STD_C 898void _vmoptions(void) 899#else 900void _vmoptions() 901#endif 902{ 903 Vmalloc_t* vm = 0; 904 char* trace = 0; 905 char* s; 906 char* t; 907 char* v; 908 Vmulong_t n; 909 int fd; 910 char buf[1024]; 911 912 _Vmoptions = 1; 913 t = buf; 914 v = &buf[sizeof(buf)-1]; 915 if (s = getenv("VMALLOC_OPTIONS")) 916 COPY(t, v, s); 917 if (t > buf) 918 { 919 *t = 0; 920 s = buf; 921 for (;;) 922 { 923 while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') 924 s++; 925 if (!*(t = s)) 926 break; 927 v = 0; 928 while (*s) 929 if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') 930 { 931 *s++ = 0; 932 break; 933 } 934 else if (!v && *s == '=') 935 { 936 *s++ = 0; 937 if (!*(v = s)) 938 v = 0; 939 } 940 else 941 s++; 942 if (t[0] == 'n' && t[1] == 'o') 943 continue; 944 switch (t[0]) 945 { 946 case 'a': /* abort */ 947 if (!vm) 948 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 949 if (vm && vm->meth.meth == VM_MTDEBUG) 950 vmset(vm, VM_DBABORT, 1); 951 else 952 _Vmassert |= VM_abort; 953 break; 954 case 'c': /* check */ 955 _Vmassert |= VM_check; 956 break; 957 case 'm': 958 switch (t[1]) 959 { 960 case 'e': /* method=<method> */ 961 if (v && !vm) 962 { 963 if ((v[0] == 'V' || v[0] == 'v') && (v[1] == 'M' || v[1] == 'm')) 964 v += 2; 965 if (strcmp(v, "debug") == 0) 966 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 967 else if (strcmp(v, "profile") == 0) 968 vm = vmopen(Vmdcsbrk, Vmprofile, 0); 969 else if (strcmp(v, "last") == 0) 970 vm = vmopen(Vmdcsbrk, Vmlast, 0); 971 else if (strcmp(v, "best") == 0) 972 vm = Vmheap; 973 } 974 break; 975 case 'm': /* mmap */ 976#if _mem_mmap_anon || _mem_mmap_zero 977 _Vmassert |= VM_mmap; 978#endif 979 break; 980 } 981 break; 982 case 'p': 983 if (v) 984 switch (t[1]) 985 { 986 case 'e': /* period=<count> */ 987 if (!vm) 988 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 989 if (vm && vm->meth.meth == VM_MTDEBUG) 990 _Vmdbcheck = atou(&v); 991 break; 992 case 'r': /* profile=<path> */ 993 if (!vm) 994 vm = vmopen(Vmdcsbrk, Vmprofile, 0); 995 if (v && vm && vm->meth.meth == VM_MTPROFILE) 996 _Vmpffd = createfile(v); 997 break; 998 } 999 break; 1000 case 'r': /* region */ 1001 _Vmassert |= VM_region; 1002 break; 1003 case 's': /* start=<count> */ 1004 if (!vm) 1005 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1006 if (v && vm && vm->meth.meth == VM_MTDEBUG) 1007 _Vmdbstart = atou(&v); 1008 break; 1009 case 't': /* trace=<path> */ 1010 trace = v; 1011 break; 1012 case 'w': 1013 if (t[1] == 'a') 1014 switch (t[2]) 1015 { 1016 case 'r': /* warn=<path> */ 1017 if (!vm) 1018 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1019 if (v && vm && vm->meth.meth == VM_MTDEBUG && (fd = createfile(v)) >= 0) 1020 vmdebug(fd); 1021 break; 1022 case 't': /* watch=<addr> */ 1023 if (!vm) 1024 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1025 if (v && vm && vm->meth.meth == VM_MTDEBUG && (n = atou(&v)) >= 0) 1026 vmdbwatch((Void_t*)n); 1027 break; 1028 } 1029 break; 1030 } 1031 } 1032 } 1033 1034 /* slip in the new region now so that malloc() will work fine */ 1035 1036 if (vm) 1037 { 1038 if (vm->meth.meth == VM_MTDEBUG) 1039 _Vmdbcheck = 1; 1040 Vmregion = vm; 1041 } 1042 1043 /* enable tracing */ 1044 1045 if (trace && (fd = createfile(trace)) >= 0) 1046 { 1047 vmset(Vmregion, VM_TRACE, 1); 1048 vmtrace(fd); 1049 } 1050 1051 /* make sure that profile data is output upon exiting */ 1052 1053 if (vm && vm->meth.meth == VM_MTPROFILE) 1054 { 1055 if (_Vmpffd < 0) 1056 _Vmpffd = 2; 1057 /* this may wind up calling malloc(), but region is ok now */ 1058 atexit(pfprint); 1059 } 1060 else if (_Vmpffd >= 0) 1061 { 1062 close(_Vmpffd); 1063 _Vmpffd = -1; 1064 } 1065} 1066 1067#endif /*_UWIN*/ 1068