1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2010 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 24 void _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 40 extern int atexit(void(*)(void)); 41 extern 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 62 typedef struct ______mallinfo Mallinfo_t; 63 #undef mallopt 64 #undef mstats 65 typedef 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 139 static Vmulong_t _Vmdbstart = 0; 140 static Vmulong_t _Vmdbcheck = 0; 141 static Vmulong_t _Vmdbtime = 0; 142 static 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 169 extern int _sigblock(void); 170 extern void _sigunblock(int); 171 extern 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 185 static char* 186 lcl_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 210 static 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 223 static int vmflinit(void) 224 #else 225 static 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 248 extern Void_t* calloc(reg size_t n_obj, reg size_t s_obj) 249 #else 250 extern Void_t* calloc(n_obj, s_obj) 251 reg size_t n_obj; 252 reg 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 260 extern Void_t* malloc(reg size_t size) 261 #else 262 extern Void_t* malloc(size) 263 reg size_t size; 264 #endif 265 { 266 VMFLINIT(); 267 return VMRECORD((*Vmregion->meth.allocf)(Vmregion,size)); 268 } 269 270 #if __STD_C 271 extern Void_t* realloc(reg Void_t* data, reg size_t size) 272 #else 273 extern Void_t* realloc(data,size) 274 reg Void_t* data; /* block to be reallocated */ 275 reg 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 319 extern void free(reg Void_t* data) 320 #else 321 extern void free(data) 322 reg 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 359 extern void cfree(reg Void_t* data) 360 #else 361 extern void cfree(data) 362 reg Void_t* data; 363 #endif 364 { 365 free(data); 366 } 367 368 #if __STD_C 369 extern Void_t* memalign(reg size_t align, reg size_t size) 370 #else 371 extern Void_t* memalign(align, size) 372 reg size_t align; 373 reg 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 386 extern int posix_memalign(reg Void_t **memptr, reg size_t align, reg size_t size) 387 #else 388 extern int posix_memalign(memptr, align, size) 389 reg Void_t** memptr; 390 reg size_t align; 391 reg 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 407 extern Void_t* valloc(reg size_t size) 408 #else 409 extern Void_t* valloc(size) 410 reg 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 419 extern Void_t* pvalloc(reg size_t size) 420 #else 421 extern Void_t* pvalloc(size) 422 reg 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 432 char* strdup(const char* s) 433 #else 434 char* strdup(s) 435 char* 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 456 typedef struct _alloca_s Alloca_t; 457 union _alloca_u 458 { struct 459 { char* addr; 460 Alloca_t* next; 461 } head; 462 char array[ALIGN]; 463 }; 464 struct _alloca_s 465 { union _alloca_u head; 466 Vmuchar_t data[1]; 467 }; 468 469 #if __STD_C 470 extern Void_t* alloca(size_t size) 471 #else 472 extern Void_t* alloca(size) 473 size_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 517 extern Void_t* F2(_calloc, size_t,n, size_t,m) { return calloc(n, m); } 518 extern Void_t F1(_cfree, Void_t*,p) { free(p); } 519 extern Void_t F1(_free, Void_t*,p) { free(p); } 520 extern Void_t* F1(_malloc, size_t,n) { return malloc(n); } 521 #if _lib_memalign 522 extern Void_t* F2(_memalign, size_t,a, size_t,n) { return memalign(a, n); } 523 #endif 524 #if _lib_pvalloc 525 extern Void_t* F1(_pvalloc, size_t,n) { return pvalloc(n); } 526 #endif 527 extern Void_t* F2(_realloc, Void_t*,p, size_t,n) { return realloc(p, n); } 528 #if _lib_valloc 529 extern Void_t* F1(_valloc, size_t,n) { return valloc(n); } 530 #endif 531 #endif 532 533 #if _lib___malloc 534 extern Void_t* F2(__calloc, size_t,n, size_t,m) { return calloc(n, m); } 535 extern Void_t F1(__cfree, Void_t*,p) { free(p); } 536 extern Void_t F1(__free, Void_t*,p) { free(p); } 537 extern Void_t* F1(__malloc, size_t,n) { return malloc(n); } 538 #if _lib_memalign 539 extern Void_t* F2(__memalign, size_t,a, size_t,n) { return memalign(a, n); } 540 #endif 541 #if _lib_pvalloc 542 extern Void_t* F1(__pvalloc, size_t,n) { return pvalloc(n); } 543 #endif 544 extern Void_t* F2(__realloc, Void_t*,p, size_t,n) { return realloc(p, n); } 545 #if _lib_valloc 546 extern Void_t* F1(__valloc, size_t,n) { return valloc(n); } 547 #endif 548 #endif 549 550 #if _lib___libc_malloc 551 extern Void_t* F2(__libc_calloc, size_t,n, size_t,m) { return calloc(n, m); } 552 extern Void_t F1(__libc_cfree, Void_t*,p) { free(p); } 553 extern Void_t F1(__libc_free, Void_t*,p) { free(p); } 554 extern Void_t* F1(__libc_malloc, size_t,n) { return malloc(n); } 555 #if _lib_memalign 556 extern Void_t* F2(__libc_memalign, size_t,a, size_t,n) { return memalign(a, n); } 557 #endif 558 #if _lib_pvalloc 559 extern Void_t* F1(__libc_pvalloc, size_t,n) { return pvalloc(n); } 560 #endif 561 extern Void_t* F2(__libc_realloc, Void_t*,p, size_t,n) { return realloc(p, n); } 562 #if _lib_valloc 563 extern 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 592 typedef struct mallinfo Mallinfo_t; 593 typedef 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 603 extern int mallopt(int cmd, int value) 604 #else 605 extern int mallopt(cmd, value) 606 int cmd; 607 int 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 617 extern Mallinfo_t mallinfo(void) 618 #else 619 extern 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 639 extern Mstats_t mstats(void) 640 #else 641 extern 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 672 extern Void_t* calloc _ARG_((size_t, size_t)); 673 674 #undef cfree 675 extern void cfree _ARG_((Void_t*)); 676 677 #undef free 678 extern void free _ARG_((Void_t*)); 679 680 #undef malloc 681 extern Void_t* malloc _ARG_((size_t)); 682 683 #if _lib_memalign 684 #undef memalign 685 extern Void_t* memalign _ARG_((size_t, size_t)); 686 #endif 687 688 #if _lib_pvalloc 689 #undef pvalloc 690 extern Void_t* pvalloc _ARG_((size_t)); 691 #endif 692 693 #undef realloc 694 extern Void_t* realloc _ARG_((Void_t*, size_t)); 695 696 #if _lib_valloc 697 #undef valloc 698 extern Void_t* valloc _ARG_((size_t)); 699 #endif 700 701 #if defined(__EXPORT__) 702 #define extern __EXPORT__ 703 #endif 704 705 extern Void_t* F2(_ast_calloc, size_t,n, size_t,m) { return calloc(n, m); } 706 extern Void_t F1(_ast_cfree, Void_t*,p) { free(p); } 707 extern Void_t F1(_ast_free, Void_t*,p) { free(p); } 708 extern Void_t* F1(_ast_malloc, size_t,n) { return malloc(n); } 709 #if _lib_memalign 710 extern Void_t* F2(_ast_memalign, size_t,a, size_t,n) { return memalign(a, n); } 711 #endif 712 #if _lib_pvalloc 713 extern Void_t* F1(_ast_pvalloc, size_t,n) { return pvalloc(n); } 714 #endif 715 extern Void_t* F2(_ast_realloc, Void_t*,p, size_t,n) { return realloc(p, n); } 716 #if _lib_valloc 717 extern 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 740 typedef struct mallinfo Mallinfo_t; 741 typedef struct mstats Mstats_t; 742 743 #endif 744 745 #if defined(__EXPORT__) 746 #define extern __EXPORT__ 747 #endif 748 749 #if _lib_mallopt 750 extern int F2(_ast_mallopt, int,cmd, int,value) { return mallopt(cmd, value); } 751 #endif 752 753 #if _lib_mallinfo && _mem_arena_mallinfo 754 extern Mallinfo_t F0(_ast_mallinfo, void) { return mallinfo(); } 755 #endif 756 757 #if _lib_mstats && _mem_bytes_total_mstats 758 extern 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 768 static Vmulong_t atou(char** sp) 769 #else 770 static Vmulong_t atou(sp) 771 char** 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 801 static char* insertpid(char* begs, char* ends) 802 #else 803 static char* insertpid(begs,ends) 804 char* begs; 805 char* 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 826 static int createfile(char* file) 827 #else 828 static int createfile(file) 829 char* 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 882 static void pfprint(void) 883 #else 884 static 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 898 void _vmoptions(void) 899 #else 900 void _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 1 /* backwards compatibility until 2011 */ 918 else 919 { 920 char* p; 921 922 if (s = getenv("VMDEBUG")) 923 { 924 switch (*s++) 925 { 926 case 0: 927 break; 928 case 'a': 929 p = " abort"; 930 COPY(t, v, p); 931 break; 932 case 'w': 933 p = " warn"; 934 COPY(t, v, p); 935 break; 936 case '0': 937 if (*s-- == 'x') 938 { 939 p = " watch="; 940 COPY(t, v, p); 941 COPY(t, v, s); 942 break; 943 } 944 /*FALLTHROUGH*/ 945 default: 946 p = " period="; 947 COPY(t, v, p); 948 COPY(t, v, s); 949 break; 950 } 951 } 952 if ((s = getenv("VMETHOD")) && *s) 953 { 954 p = " method="; 955 COPY(t, v, p); 956 COPY(t, v, s); 957 } 958 if ((s = getenv("VMPROFILE")) && *s) 959 { 960 p = " profile="; 961 COPY(t, v, p); 962 COPY(t, v, s); 963 } 964 if ((s = getenv("VMTRACE")) && *s) 965 { 966 p = " trace="; 967 COPY(t, v, p); 968 COPY(t, v, s); 969 } 970 } 971 #endif 972 if (t > buf) 973 { 974 *t = 0; 975 s = buf; 976 for (;;) 977 { 978 while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') 979 s++; 980 if (!*(t = s)) 981 break; 982 v = 0; 983 while (*s) 984 if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') 985 { 986 *s++ = 0; 987 break; 988 } 989 else if (!v && *s == '=') 990 { 991 *s++ = 0; 992 if (!*(v = s)) 993 v = 0; 994 } 995 else 996 s++; 997 if (t[0] == 'n' && t[1] == 'o') 998 continue; 999 switch (t[0]) 1000 { 1001 case 'a': /* abort */ 1002 if (!vm) 1003 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1004 if (vm && vm->meth.meth == VM_MTDEBUG) 1005 vmset(vm, VM_DBABORT, 1); 1006 else 1007 _Vmassert |= VM_abort; 1008 break; 1009 case 'c': /* check */ 1010 _Vmassert |= VM_check; 1011 break; 1012 case 'm': 1013 switch (t[1]) 1014 { 1015 case 'e': /* method=<method> */ 1016 if (v && !vm) 1017 { 1018 if ((v[0] == 'V' || v[0] == 'v') && (v[1] == 'M' || v[1] == 'm')) 1019 v += 2; 1020 if (strcmp(v, "debug") == 0) 1021 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1022 else if (strcmp(v, "profile") == 0) 1023 vm = vmopen(Vmdcsbrk, Vmprofile, 0); 1024 else if (strcmp(v, "last") == 0) 1025 vm = vmopen(Vmdcsbrk, Vmlast, 0); 1026 else if (strcmp(v, "best") == 0) 1027 vm = Vmheap; 1028 } 1029 break; 1030 case 'm': /* mmap */ 1031 #if _mem_mmap_anon || _mem_mmap_zero 1032 _Vmassert |= VM_mmap; 1033 #endif 1034 break; 1035 } 1036 break; 1037 case 'p': 1038 if (v) 1039 switch (t[1]) 1040 { 1041 case 'e': /* period=<count> */ 1042 if (!vm) 1043 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1044 if (vm && vm->meth.meth == VM_MTDEBUG) 1045 _Vmdbcheck = atou(&v); 1046 break; 1047 case 'r': /* profile=<path> */ 1048 if (!vm) 1049 vm = vmopen(Vmdcsbrk, Vmprofile, 0); 1050 if (v && vm && vm->meth.meth == VM_MTPROFILE) 1051 _Vmpffd = createfile(v); 1052 break; 1053 } 1054 break; 1055 case 'r': /* region */ 1056 _Vmassert |= VM_region; 1057 break; 1058 case 's': /* start=<count> */ 1059 if (!vm) 1060 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1061 if (v && vm && vm->meth.meth == VM_MTDEBUG) 1062 _Vmdbstart = atou(&v); 1063 break; 1064 case 't': /* trace=<path> */ 1065 trace = v; 1066 break; 1067 case 'w': 1068 if (t[1] == 'a') 1069 switch (t[2]) 1070 { 1071 case 'r': /* warn=<path> */ 1072 if (!vm) 1073 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1074 if (v && vm && vm->meth.meth == VM_MTDEBUG && (fd = createfile(v)) >= 0) 1075 vmdebug(fd); 1076 break; 1077 case 't': /* watch=<addr> */ 1078 if (!vm) 1079 vm = vmopen(Vmdcsbrk, Vmdebug, 0); 1080 if (v && vm && vm->meth.meth == VM_MTDEBUG && (n = atou(&v)) >= 0) 1081 vmdbwatch((Void_t*)n); 1082 break; 1083 } 1084 break; 1085 } 1086 } 1087 } 1088 1089 /* slip in the new region now so that malloc() will work fine */ 1090 1091 if (vm) 1092 { 1093 if (vm->meth.meth == VM_MTDEBUG) 1094 _Vmdbcheck = 1; 1095 Vmregion = vm; 1096 } 1097 1098 /* enable tracing */ 1099 1100 if (trace && (fd = createfile(trace)) >= 0) 1101 { 1102 vmset(Vmregion, VM_TRACE, 1); 1103 vmtrace(fd); 1104 } 1105 1106 /* make sure that profile data is output upon exiting */ 1107 1108 if (vm && vm->meth.meth == VM_MTPROFILE) 1109 { 1110 if (_Vmpffd < 0) 1111 _Vmpffd = 2; 1112 /* this may wind up calling malloc(), but region is ok now */ 1113 atexit(pfprint); 1114 } 1115 else if (_Vmpffd >= 0) 1116 { 1117 close(_Vmpffd); 1118 _Vmpffd = -1; 1119 } 1120 } 1121 1122 #endif /*_UWIN*/ 1123