dmalloc-5.5.2000755 001751 001751 00000000000 10622115666 013034 5ustar00graygray000000 000000 dmalloc-5.5.2/contrib000755 001751 001751 00000000000 10622115666 014474 5ustar00graygray000000 000000 dmalloc-5.5.2/docs000755 001751 001751 00000000000 10622115666 013764 5ustar00graygray000000 000000 dmalloc-5.5.2/conf.h.in000640 001751 001751 00000020255 10622115666 014616 0ustar00graygray000000 000000 /* * Automatic configuration flags * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for any * purpose and without fee is hereby granted, provided * that the above copyright notice and this permission notice appear * in all copies, and that the name of Gray Watson not be used in * advertising or publicity pertaining to distribution of the document * or software without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: conf.h.in,v 1.99 2005/12/21 13:40:27 gray Exp $ */ #ifndef __CONF_H__ #define __CONF_H__ /* please see settings.h for manual configuration options */ /* * NOTE: The following settings should not need to be tuned by hand. */ /* * Set to 1 if the mprotect function was found and the PROT_NONE, * PROT_READ, and PROT_WRITE defines were found in sys/mman.h. This * is so that we can restrict access to certain blocks of memory. */ #define PROTECT_ALLOWED 0 /* * (char *)sbrk(const int incr) is the main heap-memory allocation * routine that most systems employ. This extends the program's data * space by INCR number of bytes. * * NOTE: If configure generates a 0 for this and HAVE_MMAP on your * system, you should see the INTERNAL_MEMORY_SPACE setting in the * settings.h file which is created from the settings.dist file. */ #define HAVE_SBRK 0 /* * (void *)mmap(...) is another heap-memory allocation routine that * systems employ. On newer systems it is often preferable over sbrk. * It allocates a block of memory in the virtual-memory system. The * USE_MMAP define is set if the standard mmap call works. * * NOTE: If configure generates a 0 for this and HAVE_SBRK on your * system, you should see the INTERNAL_MEMORY_SPACE setting in the * settings.h file which is created from the settings.dist file. */ #define HAVE_MMAP 0 #define USE_MMAP 0 /* * This is the basic block size in bits. If possible, the configure * script will set this to be the value returned by the getpagesize() * function. If not then some sort of best guess will be necessary. * 15 (meaning basic block size of 32k) will probably be good. * * NOTE: some sbrk functions round to the correct page-size. No * problems aside from a possible small increase in the administration * overhead should happen if this value is too high. */ #define BASIC_BLOCK 15 /* * The alignment value of all allocations in number of bytes for * loading admin information before an allocation. If possible, the * configure script will set this to be the value returned by * sizeof(long) which in most systems is the register width. * * NOTE: the value will never be auto-configured to be less than 8 * because some system (like sparc for instance) report the sizeof(long) * == 4 while the register size is 8 bytes. Certain memory needs to be of * the same base as the register size (stack frames, code, etc.). Any * ideas how I can determine the register size in a better (and portable) * fashion? * * NOTE: larger the number the more memory may be wasted by certain * debugging settings like fence-post checking. */ #define ALLOCATION_ALIGNMENT 8 /* * This checks to see if the abort routine does extensive cleaning up * before halting a program. If so then it may call malloc functions * making the library go recursive. If abort is set to not okay then * you should tune the KILL_PROCESS and SIGNAL_INCLUDE options in * settings.h if you want the library to be able to dump core. */ #define ABORT_OKAY 0 /* * This checks to see if we can include signal.h and get SIGHUP, * SIGINT, and SIGTERM for the catch-signals token. With this token, * you can have the library do an automatic shutdown if we see the * above signals. */ #define SIGNAL_OKAY 0 #define RETSIGTYPE void /* * This checks to see if we can include return.h and use the assembly * macros there to call the callers address for logging. If you do * not want this behavior, then set the USE_RETURN_MACROS to 0 in the * settings.h file. */ #define RETURN_MACROS_WORK 0 /* * Why can't the compiler folks agree about this. I really hate Unix * sometimes for its blatant disregard for anything approaching a * standard. */ #define IDENT_WORKS 0 /* * Which pthread include file to use. */ #define HAVE_PTHREAD_H 0 #define HAVE_PTHREADS_H 0 /* * What pthread functions do we have? */ #define HAVE_PTHREAD_MUTEX_INIT 0 #define HAVE_PTHREAD_MUTEX_LOCK 0 #define HAVE_PTHREAD_MUTEX_UNLOCK 0 /* * What is the pthread mutex type? Usually (always?) it is * pthread_mutex_t. */ #define THREAD_MUTEX_T pthread_mutex_t /* * On some systems, you initialize mutex variables with NULL. Others * require various stupid non-portable incantations. The OSF 3.2 guys * should be ashamed of themselves. This only is used if the * LOCK_THREADS setting is enabled in the settings.h. */ #define THREAD_LOCK_INIT_VAL 0L /* * Under the Cygwin environment, when malloc calls getenv, it core * dumps. This is because Cygwin, as far as I know, is loading the * shared libraries for the various system functions and goes * recursive with a call to getenv. Ugh. * * So we have to delay the getenv call. This sets when we can do the * getenv call so the environmental processing is delayed. */ #define GETENV_SAFE 0 /* * See whether support exists for the constructor attribute which * allows the library to run code before main() is called. I know * that later versions of gcc have support for this and maybe other * compilers do as well. */ #define CONSTRUCTOR_WORKS 0 /* * See whether support exists for the destructor attribute which * allows the library to run code after main() is exited. I know * that later versions of gcc have support for this and maybe other * compilers do as well. */ #define DESTRUCTOR_WORKS 0 /* * See if we have the GetEnvironmentVariableA Cygwin function. This * is used as a getenv replacement. */ #define HAVE_GETENVIRONMENTVARIABLEA 0 /* * LIBRARY DEFINES: */ /* * Whether the compiler and OS has standard C headers. */ #undef STDC_HEADERS /* * Some systems have functions which can register routines to be * called by exit(3) (or when the program returns from main). This * functionality allows the dmalloc_shutdown() routine to be called * automatically upon program completion so that the library can log * statistics. Use the AUTO_SHUTDOWN define above to disable this. * Please send me mail if this functionality exists on your system but * in another name. * * NOTE: If neither is available, take a look at atexit.c in the * contrib directory which may provide this useful functionality for * your system. */ #define HAVE_ATEXIT 0 #define HAVE_ON_EXIT 0 /* Is the DMALLOC_SIZE type unsigned? */ #define DMALLOC_SIZE_UNSIGNED 0 /* * The dmalloc library provides its own versions of the following * functions, or knows how to work around their absence. */ /* bells and whistles */ #define HAVE_FORK 0 #define HAVE_GETHOSTNAME 0 #define HAVE_GETPID 0 #define HAVE_GETUID 0 #define HAVE_TIME 0 #define HAVE_CTIME 0 #define HAVE_VPRINTF 0 #define HAVE_SNPRINTF 0 #define HAVE_VSNPRINTF 0 #define HAVE_RECALLOC 0 #define HAVE_MEMALIGN 0 #define HAVE_VALLOC 0 /* various functions for arg checking and/or internal use */ #define HAVE_ATOI 0 #define HAVE_ATOL 0 #define HAVE_BCMP 0 #define HAVE_BCOPY 0 #define HAVE_BZERO 0 #define HAVE_INDEX 0 #define HAVE_MEMCCPY 0 #define HAVE_MEMCHR 0 #define HAVE_MEMCMP 0 #define HAVE_MEMCPY 0 #define HAVE_MEMMOVE 0 #define HAVE_MEMSET 0 #define HAVE_RINDEX 0 #define HAVE_STRCASECMP 0 #define HAVE_STRCAT 0 #define HAVE_STRCHR 0 #define HAVE_STRCMP 0 #define HAVE_STRCPY 0 #define HAVE_STRCSPN 0 #define HAVE_STRDUP 0 #define HAVE_STRLEN 0 #define HAVE_STRNCASECMP 0 #define HAVE_STRNCAT 0 #define HAVE_STRNCMP 0 #define HAVE_STRNCPY 0 #define HAVE_STRNDUP 0 #define HAVE_STRPBRK 0 #define HAVE_STRRCHR 0 #define HAVE_STRSEP 0 #define HAVE_STRSPN 0 #define HAVE_STRSTR 0 #define HAVE_STRTOK 0 /* manual settings */ #include "settings.h" #endif /* ! __CONF_H__ */ dmalloc-5.5.2/configure000755 001751 001751 00001174422 10622115666 015035 0ustar00graygray000000 000000 #! /bin/sh # From configure.ac Revision: 1.37 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for dmalloc 5.5.2. # # Report bugs to . # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME='dmalloc' PACKAGE_TARNAME='dmalloc' PACKAGE_VERSION='5.5.2' PACKAGE_STRING='dmalloc 5.5.2' PACKAGE_BUGREPORT='http://dmalloc.com/' ac_unique_file="dmalloc.c" # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB CPP EGREP HAVE_STDARG_H HAVE_STDLIB_H HAVE_STRING_H HAVE_UNISTD_H HAVE_SYS_TYPES_H HAVE_SYS_MMAN_H shlibdir shlinkargs shlibext CXX_ON CXX_OFF TH_ON TH_OFF SL_ON SL_OFF HAVE_SIGNAL_H HAVE_SYS_CYGWIN_H HAVE_W32API_WINDEF_H HAVE_W32API_WINBASE_H HAVE_PTHREAD_H HAVE_PTHREADS_H LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CXX_set=${CXX+set} ac_env_CXX_value=$CXX ac_cv_env_CXX_set=${CXX+set} ac_cv_env_CXX_value=$CXX ac_env_CXXFLAGS_set=${CXXFLAGS+set} ac_env_CXXFLAGS_value=$CXXFLAGS ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} ac_cv_env_CXXFLAGS_value=$CXXFLAGS ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures dmalloc 5.5.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of dmalloc 5.5.2:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-cxx do not build in C++ support (enabled by default) --enable-threads build in thread support (disabled by default) --enable-shlib build shared libraries (disabled by default) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF dmalloc configure 5.5.2 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by dmalloc $as_me 5.5.2, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers conf.h" { echo "$as_me:$LINENO: configurations for the dmalloc library" >&5 echo "$as_me: configurations for the dmalloc library" >&6;} ############################################################################## # arguments # Check whether --enable-cxx or --disable-cxx was given. if test "${enable_cxx+set}" = set; then enableval="$enable_cxx" # enable_cxx set by default else enable_cxx=yes fi; # Check whether --enable-threads or --disable-threads was given. if test "${enable_threads+set}" = set; then enableval="$enable_threads" # enable_threads set by default else enable_threads=no fi; # Check whether --enable-shlib or --disable-shlib was given. if test "${enable_shlib+set}" = set; then enableval="$enable_shlib" # enable_shlib set by default else enable_shlib=no fi; ############################################################################## { echo "$as_me:$LINENO: build utilities" >&5 echo "$as_me: build utilities" >&6;} ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then echo "$as_me:$LINENO: result: $CXX" >&5 echo "${ECHO_T}$CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 echo "${ECHO_T}$ac_ct_CXX" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CXX" && break done test -n "$ac_ct_CXX" || ac_ct_CXX="g++" CXX=$ac_ct_CXX fi # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C++ compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 GXX=`test $ac_compiler_gnu = yes && echo yes` ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS CXXFLAGS="-g" echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cxx_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # see if we actually have a CXX program if test "$ac_cv_prog_CXX" = "" -o ! -x "$ac_cv_prog_CXX"; then { echo "$as_me:$LINENO: WARNING: could not find C++ compiler $ac_cv_prog_CXX" >&5 echo "$as_me: WARNING: could not find C++ compiler $ac_cv_prog_CXX" >&2;} enable_cxx=no fi # hopefully we have a stdc c-compiler if test "$ac_cv_prog_cc_stdc" = "no" ; then { echo "$as_me:$LINENO: WARNING: " >&5 echo "$as_me: WARNING: " >&2;} { echo "$as_me:$LINENO: WARNING: no ansi compiler. this build may fail." >&5 echo "$as_me: WARNING: no ansi compiler. this build may fail." >&2;} { echo "$as_me:$LINENO: WARNING: " >&5 echo "$as_me: WARNING: " >&2;} fi ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 if test "${ac_cv_c_const+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset x; /* SunOS 4.1.1 cc rejects this. */ char const *const *ccp; char **p; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; ccp = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++ccp; p = (char**) ccp; ccp = (char const *const *) p; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_const=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 echo "${ECHO_T}$ac_cv_c_const" >&6 if test $ac_cv_c_const = no; then cat >>confdefs.h <<\_ACEOF #define const _ACEOF fi # we need this for various settings ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "${ac_cv_header_stdarg_h+set}" = set; then echo "$as_me:$LINENO: checking for stdarg.h" >&5 echo $ECHO_N "checking for stdarg.h... $ECHO_C" >&6 if test "${ac_cv_header_stdarg_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_stdarg_h" >&5 echo "${ECHO_T}$ac_cv_header_stdarg_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking stdarg.h usability" >&5 echo $ECHO_N "checking stdarg.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking stdarg.h presence" >&5 echo $ECHO_N "checking stdarg.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: stdarg.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: stdarg.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: stdarg.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: stdarg.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: stdarg.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: stdarg.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: stdarg.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: stdarg.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: stdarg.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: stdarg.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: stdarg.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for stdarg.h" >&5 echo $ECHO_N "checking for stdarg.h... $ECHO_C" >&6 if test "${ac_cv_header_stdarg_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_stdarg_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_stdarg_h" >&5 echo "${ECHO_T}$ac_cv_header_stdarg_h" >&6 fi if test $ac_cv_header_stdarg_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_STDARG_H 1 _ACEOF HAVE_STDARG_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_STDARG_H 0 _ACEOF HAVE_STDARG_H=0 fi if test "${ac_cv_header_stdlib_h+set}" = set; then echo "$as_me:$LINENO: checking for stdlib.h" >&5 echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6 if test "${ac_cv_header_stdlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking stdlib.h usability" >&5 echo $ECHO_N "checking stdlib.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking stdlib.h presence" >&5 echo $ECHO_N "checking stdlib.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: stdlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: stdlib.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: stdlib.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: stdlib.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: stdlib.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: stdlib.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: stdlib.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: stdlib.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: stdlib.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: stdlib.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for stdlib.h" >&5 echo $ECHO_N "checking for stdlib.h... $ECHO_C" >&6 if test "${ac_cv_header_stdlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_stdlib_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_stdlib_h" >&5 echo "${ECHO_T}$ac_cv_header_stdlib_h" >&6 fi if test $ac_cv_header_stdlib_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_STDLIB_H 1 _ACEOF HAVE_STDLIB_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_STDLIB_H 0 _ACEOF HAVE_STDLIB_H=0 fi if test "${ac_cv_header_string_h+set}" = set; then echo "$as_me:$LINENO: checking for string.h" >&5 echo $ECHO_N "checking for string.h... $ECHO_C" >&6 if test "${ac_cv_header_string_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 echo "${ECHO_T}$ac_cv_header_string_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking string.h usability" >&5 echo $ECHO_N "checking string.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking string.h presence" >&5 echo $ECHO_N "checking string.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: string.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: string.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: string.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: string.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: string.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: string.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: string.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: string.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: string.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: string.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for string.h" >&5 echo $ECHO_N "checking for string.h... $ECHO_C" >&6 if test "${ac_cv_header_string_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_string_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_string_h" >&5 echo "${ECHO_T}$ac_cv_header_string_h" >&6 fi if test $ac_cv_header_string_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_STRING_H 1 _ACEOF HAVE_STRING_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_STRING_H 0 _ACEOF HAVE_STRING_H=0 fi if test "${ac_cv_header_unistd_h+set}" = set; then echo "$as_me:$LINENO: checking for unistd.h" >&5 echo $ECHO_N "checking for unistd.h... $ECHO_C" >&6 if test "${ac_cv_header_unistd_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_unistd_h" >&5 echo "${ECHO_T}$ac_cv_header_unistd_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking unistd.h usability" >&5 echo $ECHO_N "checking unistd.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking unistd.h presence" >&5 echo $ECHO_N "checking unistd.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: unistd.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: unistd.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: unistd.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: unistd.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: unistd.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: unistd.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: unistd.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: unistd.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: unistd.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: unistd.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: unistd.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for unistd.h" >&5 echo $ECHO_N "checking for unistd.h... $ECHO_C" >&6 if test "${ac_cv_header_unistd_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_unistd_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_unistd_h" >&5 echo "${ECHO_T}$ac_cv_header_unistd_h" >&6 fi if test $ac_cv_header_unistd_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_UNISTD_H 1 _ACEOF HAVE_UNISTD_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_UNISTD_H 0 _ACEOF HAVE_UNISTD_H=0 fi if test "${ac_cv_header_sys_types_h+set}" = set; then echo "$as_me:$LINENO: checking for sys/types.h" >&5 echo $ECHO_N "checking for sys/types.h... $ECHO_C" >&6 if test "${ac_cv_header_sys_types_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_sys_types_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_types_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking sys/types.h usability" >&5 echo $ECHO_N "checking sys/types.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking sys/types.h presence" >&5 echo $ECHO_N "checking sys/types.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/types.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/types.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/types.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/types.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/types.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/types.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/types.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/types.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/types.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/types.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/types.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for sys/types.h" >&5 echo $ECHO_N "checking for sys/types.h... $ECHO_C" >&6 if test "${ac_cv_header_sys_types_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_types_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_sys_types_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_types_h" >&6 fi if test $ac_cv_header_sys_types_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_TYPES_H 1 _ACEOF HAVE_SYS_TYPES_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_TYPES_H 0 _ACEOF HAVE_SYS_TYPES_H=0 fi if test "${ac_cv_header_sys_mman_h+set}" = set; then echo "$as_me:$LINENO: checking for sys/mman.h" >&5 echo $ECHO_N "checking for sys/mman.h... $ECHO_C" >&6 if test "${ac_cv_header_sys_mman_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_sys_mman_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_mman_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking sys/mman.h usability" >&5 echo $ECHO_N "checking sys/mman.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking sys/mman.h presence" >&5 echo $ECHO_N "checking sys/mman.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/mman.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/mman.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/mman.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/mman.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/mman.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/mman.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/mman.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/mman.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/mman.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/mman.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for sys/mman.h" >&5 echo $ECHO_N "checking for sys/mman.h... $ECHO_C" >&6 if test "${ac_cv_header_sys_mman_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_mman_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_sys_mman_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_mman_h" >&6 fi if test $ac_cv_header_sys_mman_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_MMAN_H 1 _ACEOF HAVE_SYS_MMAN_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_MMAN_H 0 _ACEOF HAVE_SYS_MMAN_H=0 fi ############################################################################### # shared library handling # # check to see where we should install our shared libraries # DONT CACHE in case the change the --prefix # # This is pretty tricky here and should be handled by autoconf # automatically. I try to see if there is a shlib directory # to install by shlibs there. If not I use the $libdir. Some # of the variables have values of '${exec_prefix}' and the like # so the quoting is very important. # # We first try and find the true directory where we are # installing. # if test "x$exec_prefix" = xNONE; then if test "x$prefix" = xNONE; then shlibprefix="$ac_default_prefix" else shlibprefix="$prefix" fi else shlibprefix="$exec_prefix" fi # # Then we see if there is a special shlib directory to use. # if test -d $shlibprefix/shlib; then shlibdir='${exec_prefix}/shlib' else shlibdir="$libdir" fi # see how the local system builds shared libraries echo "$as_me:$LINENO: checking shared library link args" >&5 echo $ECHO_N "checking shared library link args... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF int foo(int val) { return val + 1; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then # so now we try to create an archive from the compiled .o file (ar cr conftest.a conftest.o) 2>&5 # see which shared-library ld commands work # # Darwin/Mac OS X - Terry Teague # username terry_teague at domain users.sourceforge.net ac_cv_shared_lib_link_objs=no if test `uname` = "Darwin"; then if (ld -dylib -o conftest.so.t -lc conftest.a) 2>&5; then # By convention on some platforms # libLLL.so, libLLL.X.so are symlinks to libLLL.X.Y.Z.so # where X.Y.Z is version # (major.minor.increment) of the library # (API) # For the moment set the Mac OS X dylib compatibility version # to # 1.0 and don't create any symlinks or versioned library names. # Perhaps this could be the version of the dmalloc library # (e.g. 5.4.0) ac_cv_shared_link_args='$(CXX) -dynamiclib -install_name $@ -compatibility_version 1 -current_version 1 -o $@.t' # linking static archives into a dynamic lib doesn't seem to work # explicitly link the object files ac_cv_shared_lib_link_objs=yes else # oh well, toss an error ac_cv_shared_link_args='# Could not configure shlib linking' enable_shlib=no fi elif (ld -shared --whole-archive -soname conftest.so -o conftest.so.t conftest.a) 2>&5; then ac_cv_shared_link_args='ld -shared --whole-archive -soname $@ -o $@.t' elif (ld -shared -o conftest.so.t -all -soname conftest.so.t -none -lc -all conftest.a) 2>&5; then ac_cv_shared_link_args='ld -shared -o $@.t -all -soname $@ -none -lc -all' elif (ld -G -o conftest.so.t conftest.a) 2>&5; then ac_cv_shared_link_args='ld -G -o $@.t' else # oh well, toss an error ac_cv_shared_link_args='# Could not configure shlib linking' enable_shlib=no fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # oh well, toss an error ac_cv_shared_link_args='# Could not configure shlib linking' enable_shlib=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext shlinkargs="$ac_cv_shared_link_args" if test "$ac_cv_shared_lib_link_objs" = "yes"; then echo "$as_me:$LINENO: result: $ac_cv_shared_link_args objectfiles..." >&5 echo "${ECHO_T}$ac_cv_shared_link_args objectfiles..." >&6 else echo "$as_me:$LINENO: result: $ac_cv_shared_link_args" >&5 echo "${ECHO_T}$ac_cv_shared_link_args" >&6 fi ############################################################################### echo "$as_me:$LINENO: checking shared library extension" >&5 echo $ECHO_N "checking shared library extension... $ECHO_C" >&6 if test `uname` = "Darwin"; then # Darwin/Mac OS X - Terry Teague # username terry_teague at domain users.sourceforge.net ac_cv_shared_lib_suffix=dylib else ac_cv_shared_lib_suffix=so fi shlibext="$ac_cv_shared_lib_suffix" echo "$as_me:$LINENO: result: $ac_cv_shared_lib_suffix" >&5 echo "${ECHO_T}$ac_cv_shared_lib_suffix" >&6 ############################################################################### echo "$as_me:$LINENO: checking C++ support" >&5 echo $ECHO_N "checking C++ support... $ECHO_C" >&6 if test "$enable_cxx" = "yes"; then CXX_OFF=# echo "$as_me:$LINENO: result: enabled" >&5 echo "${ECHO_T}enabled" >&6 else CXX_ON=# echo "$as_me:$LINENO: result: disabled" >&5 echo "${ECHO_T}disabled" >&6 fi echo "$as_me:$LINENO: checking thread support" >&5 echo $ECHO_N "checking thread support... $ECHO_C" >&6 if test "$enable_threads" = "yes"; then TH_OFF=# echo "$as_me:$LINENO: result: enabled" >&5 echo "${ECHO_T}enabled" >&6 else TH_ON=# echo "$as_me:$LINENO: result: disabled" >&5 echo "${ECHO_T}disabled" >&6 fi # shlib support echo "$as_me:$LINENO: checking shlib support" >&5 echo $ECHO_N "checking shlib support... $ECHO_C" >&6 if test "$enable_shlib" = "yes"; then SL_OFF=# echo "$as_me:$LINENO: result: enabled" >&5 echo "${ECHO_T}enabled" >&6 else SL_ON=# echo "$as_me:$LINENO: result: disabled" >&5 echo "${ECHO_T}disabled" >&6 fi ############################################################################### # # check for size_t # echo "$as_me:$LINENO: checking for size_t" >&5 echo $ECHO_N "checking for size_t... $ECHO_C" >&6 if test "${ac_cv_type_size_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((size_t *) 0) return 0; if (sizeof (size_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_size_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_size_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 echo "${ECHO_T}$ac_cv_type_size_t" >&6 if test $ac_cv_type_size_t = yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned _ACEOF fi if test "$ac_cv_type_size_t" = "yes"; then cat >>confdefs.h <<\_ACEOF #define DMALLOC_SIZE size_t _ACEOF else cat >>confdefs.h <<\_ACEOF #define DMALLOC_SIZE unsigned long _ACEOF fi # # check for unsigned-ness # echo "$as_me:$LINENO: checking dmalloc size unsigned" >&5 echo $ECHO_N "checking dmalloc size unsigned... $ECHO_C" >&6 if test "$cross_compiling" = yes; then cat >>confdefs.h <<\_ACEOF #define DMALLOC_SIZE_UNSIGNED 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_STDLIB_H # include #endif main() { DMALLOC_SIZE x = -1; if (x >= 0) exit(0); else exit(1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define DMALLOC_SIZE_UNSIGNED 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) cat >>confdefs.h <<\_ACEOF #define DMALLOC_SIZE_UNSIGNED 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi # # check for strdup macro (linux) # echo "$as_me:$LINENO: checking strdup macro" >&5 echo $ECHO_N "checking strdup macro... $ECHO_C" >&6 if test "$cross_compiling" = yes; then ac_cv_strdup_macro=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_STDLIB_H # include #endif #ifdef strdup main() { exit(0); } #else main() { exit(1); } #endif _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_strdup_macro=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_strdup_macro=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_strdup_macro" >&5 echo "${ECHO_T}$ac_cv_strdup_macro" >&6 # # check for existance of mprotect and associated defines # for ac_func in mprotect do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking mprotect works" >&5 echo $ECHO_N "checking mprotect works... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_MMAN_H # include #endif int main () { int prot = PROT_NONE | PROT_READ | PROT_WRITE; (void)mprotect(0, 0, prot); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define PROTECT_ALLOWED 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >>confdefs.h <<\_ACEOF #define PROTECT_ALLOWED 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ############################################################################## { echo "$as_me:$LINENO: important functionality" >&5 echo "$as_me: important functionality" >&6;} for ac_func in mmap do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in sbrk do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test x$ac_cv_func_mmap != xyes && x$ac_cv_func_sbrk != xyes; then { echo "$as_me:$LINENO: WARNING: " >&5 echo "$as_me: WARNING: " >&2;} { echo "$as_me:$LINENO: WARNING: no mmap nor sbrk function. See INTERNAL_MEMORY_SPACE in settings.dist." >&5 echo "$as_me: WARNING: no mmap nor sbrk function. See INTERNAL_MEMORY_SPACE in settings.dist." >&2;} { echo "$as_me:$LINENO: WARNING: " >&5 echo "$as_me: WARNING: " >&2;} fi echo "$as_me:$LINENO: checking mmap usage" >&5 echo $ECHO_N "checking mmap usage... $ECHO_C" >&6 if test "$cross_compiling" = yes; then cat >>confdefs.h <<\_ACEOF #define USE_MMAP 0 _ACEOF ac_cv_use_mmap=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_MMAN_H # include #endif main() { /* we could open /dev/zero and map to that but I did not want the library to open another file-descriptor */ char *dest, *src, *src_p, *dest_p; src = "0123456789"; dest = (char *)mmap(0L, 10, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1 /* no fd */, 0 /* no offset */); src_p = src; dest_p = dest; while (src_p < src + 10) { *dest_p++ = *src_p++; } src_p = src; dest_p = dest; while (src_p < src + 10) { if (*src_p++ != *dest_p++) { exit(1); } } exit(0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define USE_MMAP 1 _ACEOF ac_cv_use_mmap=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) cat >>confdefs.h <<\_ACEOF #define USE_MMAP 0 _ACEOF ac_cv_use_mmap=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_use_mmap" >&5 echo "${ECHO_T}$ac_cv_use_mmap" >&6 # # check for basic block size # for ac_func in getpagesize do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking basic-block size" >&5 echo $ECHO_N "checking basic-block size... $ECHO_C" >&6 ac_cv_page_size=0 if test $ac_cv_page_size = 0; then if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF main() { if (getpagesize()<=2048) exit(0); else exit(1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_page_size=11 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi if test $ac_cv_page_size = 0; then if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF main() { if (getpagesize()<=4096) exit(0); else exit(1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_page_size=12 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi if test $ac_cv_page_size = 0; then if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF main() { if (getpagesize()<=8192) exit(0); else exit(1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_page_size=13 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi if test $ac_cv_page_size = 0; then if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF main() { if (getpagesize()<=16384) exit(0); else exit(1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_page_size=14 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi if test $ac_cv_page_size = 0; then ac_cv_page_size=15 fi cat >>confdefs.h <<_ACEOF #define BASIC_BLOCK $ac_cv_page_size _ACEOF echo "$as_me:$LINENO: result: $ac_cv_page_size" >&5 echo "${ECHO_T}$ac_cv_page_size" >&6 # # data-alignment size... # echo "$as_me:$LINENO: checking for long" >&5 echo $ECHO_N "checking for long... $ECHO_C" >&6 if test "${ac_cv_type_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((long *) 0) return 0; if (sizeof (long)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 echo "${ECHO_T}$ac_cv_type_long" >&6 echo "$as_me:$LINENO: checking size of long" >&5 echo $ECHO_N "checking size of long... $ECHO_C" >&6 if test "${ac_cv_sizeof_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_long" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default long longval () { return (long) (sizeof (long)); } unsigned long ulongval () { return (long) (sizeof (long)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (long))) < 0) { long i = longval (); if (i != ((long) (sizeof (long)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (long)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_long=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF echo "$as_me:$LINENO: checking data-alignment size" >&5 echo $ECHO_N "checking data-alignment size... $ECHO_C" >&6 if test $ac_cv_sizeof_long = 4; then # we have to make a special case for sun sparc idiocy ac_cv_data_align=8 else ac_cv_data_align=$ac_cv_sizeof_long fi cat >>confdefs.h <<_ACEOF #define ALLOCATION_ALIGNMENT $ac_cv_data_align _ACEOF echo "$as_me:$LINENO: result: $ac_cv_data_align" >&5 echo "${ECHO_T}$ac_cv_data_align" >&6 # # check the safety of the abort function # for ac_func in abort do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking abort safe" >&5 echo $ECHO_N "checking abort safe... $ECHO_C" >&6 if test "$cross_compiling" = yes; then cat >>confdefs.h <<\_ACEOF #define ABORT_OKAY 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 else cat >conftest.$ac_ext <<_ACEOF static int main_b = 0; static char heap_mem[102400], *heap_p = heap_mem; free () { if (main_b) _exit(0); } char *malloc (int size) { char *pnt; if (main_b) _exit(0); pnt = heap_p; heap_p += size; return pnt; } char *calloc (int number, int size) { char *start, *pnt, *end; if (main_b) _exit(0); /* it should be already 0s */ start = malloc (number * size); pnt = start; end = start + size; while (pnt < end) { *pnt++ = '\0'; } return start; } char *realloc (char *old_pnt, int new_size) { char *start, *pnt, *end; if (main_b) _exit(0); start = malloc (new_size); pnt = start; end = start + new_size; while (pnt < end) { *pnt++ = *old_pnt++; } return start; } main() { main_b = 1; abort(); _exit(1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then # NOTE: this is reversed because abort core dumps and doesn't exit with # 0 which means that it should fail cat >>confdefs.h <<\_ACEOF #define ABORT_OKAY 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) # if it succeeds then something called free on the way out cat >>confdefs.h <<\_ACEOF #define ABORT_OKAY 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: checking return type of signal handlers" >&5 echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6 if test "${ac_cv_type_signal+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #ifdef signal # undef signal #endif #ifdef __cplusplus extern "C" void (*signal (int, void (*)(int)))(int); #else void (*signal ()) (); #endif int main () { int i; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_signal=void else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_signal=int fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 echo "${ECHO_T}$ac_cv_type_signal" >&6 cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF echo "$as_me:$LINENO: checking signal works" >&5 echo $ECHO_N "checking signal works... $ECHO_C" >&6 if test "${ac_cv_header_signal_h+set}" = set; then echo "$as_me:$LINENO: checking for signal.h" >&5 echo $ECHO_N "checking for signal.h... $ECHO_C" >&6 if test "${ac_cv_header_signal_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_signal_h" >&5 echo "${ECHO_T}$ac_cv_header_signal_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking signal.h usability" >&5 echo $ECHO_N "checking signal.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking signal.h presence" >&5 echo $ECHO_N "checking signal.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: signal.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: signal.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: signal.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: signal.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: signal.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: signal.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: signal.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: signal.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: signal.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: signal.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: signal.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: signal.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: signal.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: signal.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: signal.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: signal.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for signal.h" >&5 echo $ECHO_N "checking for signal.h... $ECHO_C" >&6 if test "${ac_cv_header_signal_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_signal_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_signal_h" >&5 echo "${ECHO_T}$ac_cv_header_signal_h" >&6 fi if test $ac_cv_header_signal_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SIGNAL_H 1 _ACEOF HAVE_SIGNAL_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_SIGNAL_H 0 _ACEOF HAVE_SIGNAL_H=0 fi cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SIGNAL_H #include #endif int main () { (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGTERM, SIG_IGN); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define SIGNAL_OKAY 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >>confdefs.h <<\_ACEOF #define SIGNAL_OKAY 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # # check the safety of the getenv function # for ac_func in getenv do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking getenv safe" >&5 echo $ECHO_N "checking getenv safe... $ECHO_C" >&6 if test "$cross_compiling" = yes; then cat >>confdefs.h <<\_ACEOF #define GETENV_SAFE 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 getenv_safe=yes else cat >conftest.$ac_ext <<_ACEOF static char heap_mem[102400], *heap_p = heap_mem; free (char *pnt) { } char *malloc (int size) { char *pnt; getenv("PATH"); pnt = heap_p; heap_p += size; return pnt; } char *calloc (int number, int size) { char *start, *pnt, *end; getenv("PATH"); /* it should be already 0s */ start = malloc (number * size); pnt = start; end = start + size; while (pnt < end) { *pnt++ = '\0'; } return start; } char *realloc (char *old_pnt, int new_size) { char *start, *pnt, *end; getenv("PATH"); start = malloc (new_size); pnt = start; end = start + new_size; while (pnt < end) { *pnt++ = *old_pnt++; } return start; } main() { malloc(10); _exit(0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define GETENV_SAFE 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 getenv_safe=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) # if it succeeds then something called free on the way out cat >>confdefs.h <<\_ACEOF #define GETENV_SAFE 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 getenv_safe=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi # now check to see if we can replace getenv with GetEnvironmentVariableA if test "${ac_cv_header_sys_cygwin_h+set}" = set; then echo "$as_me:$LINENO: checking for sys/cygwin.h" >&5 echo $ECHO_N "checking for sys/cygwin.h... $ECHO_C" >&6 if test "${ac_cv_header_sys_cygwin_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_sys_cygwin_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_cygwin_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking sys/cygwin.h usability" >&5 echo $ECHO_N "checking sys/cygwin.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking sys/cygwin.h presence" >&5 echo $ECHO_N "checking sys/cygwin.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/cygwin.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/cygwin.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/cygwin.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/cygwin.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/cygwin.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/cygwin.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/cygwin.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/cygwin.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/cygwin.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/cygwin.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/cygwin.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/cygwin.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/cygwin.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/cygwin.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/cygwin.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/cygwin.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for sys/cygwin.h" >&5 echo $ECHO_N "checking for sys/cygwin.h... $ECHO_C" >&6 if test "${ac_cv_header_sys_cygwin_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_cygwin_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_sys_cygwin_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_cygwin_h" >&6 fi if test $ac_cv_header_sys_cygwin_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_CYGWIN_H 1 _ACEOF HAVE_SYS_CYGWIN_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_CYGWIN_H 0 _ACEOF HAVE_SYS_CYGWIN_H=0 fi if test "${ac_cv_header_w32api_windef_h+set}" = set; then echo "$as_me:$LINENO: checking for w32api/windef.h" >&5 echo $ECHO_N "checking for w32api/windef.h... $ECHO_C" >&6 if test "${ac_cv_header_w32api_windef_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_w32api_windef_h" >&5 echo "${ECHO_T}$ac_cv_header_w32api_windef_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking w32api/windef.h usability" >&5 echo $ECHO_N "checking w32api/windef.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking w32api/windef.h presence" >&5 echo $ECHO_N "checking w32api/windef.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: w32api/windef.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: w32api/windef.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: w32api/windef.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: w32api/windef.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: w32api/windef.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: w32api/windef.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: w32api/windef.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: w32api/windef.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: w32api/windef.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: w32api/windef.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: w32api/windef.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: w32api/windef.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: w32api/windef.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: w32api/windef.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: w32api/windef.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: w32api/windef.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for w32api/windef.h" >&5 echo $ECHO_N "checking for w32api/windef.h... $ECHO_C" >&6 if test "${ac_cv_header_w32api_windef_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_w32api_windef_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_w32api_windef_h" >&5 echo "${ECHO_T}$ac_cv_header_w32api_windef_h" >&6 fi if test $ac_cv_header_w32api_windef_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_W32API_WINDEF_H 1 _ACEOF HAVE_W32API_WINDEF_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_W32API_WINDEF_H 0 _ACEOF HAVE_W32API_WINDEF_H=0 fi echo "$as_me:$LINENO: checking for w32api/winbase.h" >&5 echo $ECHO_N "checking for w32api/winbase.h... $ECHO_C" >&6 if test "${ac_cv_header_w32api_winbase_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_W32API_WINDEF_H # include #endif #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_w32api_winbase_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_w32api_winbase_h=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_header_w32api_winbase_h" >&5 echo "${ECHO_T}$ac_cv_header_w32api_winbase_h" >&6 if test $ac_cv_header_w32api_winbase_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_W32API_WINBASE_H 1 _ACEOF HAVE_W32API_WINBASE_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_W32API_WINBASE_H 0 _ACEOF HAVE_W32API_WINBASE_H=0 fi echo "$as_me:$LINENO: checking for GetEnvironmentVariableA" >&5 echo $ECHO_N "checking for GetEnvironmentVariableA... $ECHO_C" >&6 if test "$cross_compiling" = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_GETENVIRONMENTVARIABLEA 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 have_getenvironmentvariablea=yes else cat >conftest.$ac_ext <<_ACEOF #if HAVE_SYS_CYGWIN_H # include #endif #if HAVE_STDARG_H # include #endif #if HAVE_W32API_WINDEF_H # include #endif #if HAVE_W32API_WINBASE_H # include #endif main() { char env_buf[256]; GetEnvironmentVariableA("PATH", env_buf, sizeof(env_buf)); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define HAVE_GETENVIRONMENTVARIABLEA 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 have_getenvironmentvariablea=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) cat >>confdefs.h <<\_ACEOF #define HAVE_GETENVIRONMENTVARIABLEA 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 have_getenvironmentvariablea=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi if test x$getenv_safe != xyes && x$have_getenvironmentvariablea != xyes ; then { echo "$as_me:$LINENO: WARNING: Since getenv is not safe, you MUST add the following" >&5 echo "$as_me: WARNING: Since getenv is not safe, you MUST add the following" >&2;} { echo "$as_me:$LINENO: WARNING: code to the front of main():" >&5 echo "$as_me: WARNING: code to the front of main():" >&2;} { echo "$as_me:$LINENO: WARNING: #ifdef DMALLOC" >&5 echo "$as_me: WARNING: #ifdef DMALLOC" >&2;} { echo "$as_me:$LINENO: WARNING: dmalloc_debug_setup(getenv(\"DMALLOC_OPTIONS\"));" >&5 echo "$as_me: WARNING: dmalloc_debug_setup(getenv(\"DMALLOC_OPTIONS\"));" >&2;} { echo "$as_me:$LINENO: WARNING: #endif" >&5 echo "$as_me: WARNING: #endif" >&2;} { echo "$as_me:$LINENO: WARNING: You will need to compile your program with: -DDMALLOC" >&5 echo "$as_me: WARNING: You will need to compile your program with: -DDMALLOC" >&2;} fi ############ # # check for constructor attribute support # echo "$as_me:$LINENO: checking constructor attribute" >&5 echo $ECHO_N "checking constructor attribute... $ECHO_C" >&6 if test "$cross_compiling" = yes; then cat >>confdefs.h <<\_ACEOF #define CONSTRUCTOR_WORKS 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else cat >conftest.$ac_ext <<_ACEOF /* if we call the loc_con constructor then exit with error code 0 */ static void loc_con() __attribute__((constructor)); static void loc_con() { exit(0); } int main() { exit(1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define CONSTRUCTOR_WORKS 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) cat >>confdefs.h <<\_ACEOF #define CONSTRUCTOR_WORKS 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi # # check for destructor attribute support # echo "$as_me:$LINENO: checking destructor attribute" >&5 echo $ECHO_N "checking destructor attribute... $ECHO_C" >&6 if test "$cross_compiling" = yes; then cat >>confdefs.h <<\_ACEOF #define DESTRUCTOR_WORKS 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 destructor_works=yes else cat >conftest.$ac_ext <<_ACEOF /* if we call the loc_decon destructor then exit with error code 0 */ static void loc_decon() __attribute__((destructor)); static void loc_decon() { exit(0); } int main() { return 1; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define DESTRUCTOR_WORKS 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 destructor_works=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) cat >>confdefs.h <<\_ACEOF #define DESTRUCTOR_WORKS 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 destructor_works=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi ############################################################################## # # check if the return.h macros work # echo "$as_me:$LINENO: checking return.h macros work" >&5 echo $ECHO_N "checking return.h macros work... $ECHO_C" >&6 if test "$cross_compiling" = yes; then cat >>confdefs.h <<\_ACEOF #define RETURN_MACROS_WORK 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 else cat >conftest.$ac_ext <<_ACEOF #define __CONF_H__ #define USE_RETURN_MACROS 1 #define RETURN_MACROS_WORK 1 #include "return.h" static void foo (void) { char *ret_addr; GET_RET_ADDR(ret_addr); } main() { foo(); exit(0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define RETURN_MACROS_WORK 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) cat >>confdefs.h <<\_ACEOF #define RETURN_MACROS_WORK 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi ############################################################################## # # check to see if ident workds # echo "$as_me:$LINENO: checking if ident works" >&5 echo $ECHO_N "checking if ident works... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF #ident "$Id: configure.ac,v 1.37 2007/05/14 17:23:37 gray Exp $" static void foo (void) { } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define IDENT_WORKS 1 _ACEOF echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >>confdefs.h <<\_ACEOF #define IDENT_WORKS 0 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ############################################################################## { echo "$as_me:$LINENO: pthread particulars" >&5 echo "$as_me: pthread particulars" >&6;} XX_OLD_LIBS=$LIBS echo "$as_me:$LINENO: checking for library containing pthread_mutex_init" >&5 echo $ECHO_N "checking for library containing pthread_mutex_init... $ECHO_C" >&6 if test "${ac_cv_search_pthread_mutex_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_pthread_mutex_init=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char pthread_mutex_init (); int main () { pthread_mutex_init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_pthread_mutex_init="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_pthread_mutex_init" = no; then for ac_lib in pthread pthreads c_r; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char pthread_mutex_init (); int main () { pthread_mutex_init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_pthread_mutex_init="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_pthread_mutex_init" >&5 echo "${ECHO_T}$ac_cv_search_pthread_mutex_init" >&6 if test "$ac_cv_search_pthread_mutex_init" != no; then test "$ac_cv_search_pthread_mutex_init" = "none required" || LIBS="$ac_cv_search_pthread_mutex_init $LIBS" fi if test "${ac_cv_header_pthread_h+set}" = set; then echo "$as_me:$LINENO: checking for pthread.h" >&5 echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6 if test "${ac_cv_header_pthread_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 echo "${ECHO_T}$ac_cv_header_pthread_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking pthread.h usability" >&5 echo $ECHO_N "checking pthread.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking pthread.h presence" >&5 echo $ECHO_N "checking pthread.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: pthread.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: pthread.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: pthread.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: pthread.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: pthread.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: pthread.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: pthread.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for pthread.h" >&5 echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6 if test "${ac_cv_header_pthread_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_pthread_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 echo "${ECHO_T}$ac_cv_header_pthread_h" >&6 fi if test $ac_cv_header_pthread_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_PTHREAD_H 1 _ACEOF HAVE_PTHREAD_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_PTHREAD_H 0 _ACEOF HAVE_PTHREAD_H=0 fi if test "${ac_cv_header_pthreads_h+set}" = set; then echo "$as_me:$LINENO: checking for pthreads.h" >&5 echo $ECHO_N "checking for pthreads.h... $ECHO_C" >&6 if test "${ac_cv_header_pthreads_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_pthreads_h" >&5 echo "${ECHO_T}$ac_cv_header_pthreads_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking pthreads.h usability" >&5 echo $ECHO_N "checking pthreads.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking pthreads.h presence" >&5 echo $ECHO_N "checking pthreads.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: pthreads.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: pthreads.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: pthreads.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: pthreads.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: pthreads.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: pthreads.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: pthreads.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: pthreads.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: pthreads.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: pthreads.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: pthreads.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: pthreads.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: pthreads.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: pthreads.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: pthreads.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: pthreads.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ---------------------------------- ## ## Report this to http://dmalloc.com/ ## ## ---------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for pthreads.h" >&5 echo $ECHO_N "checking for pthreads.h... $ECHO_C" >&6 if test "${ac_cv_header_pthreads_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_pthreads_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_pthreads_h" >&5 echo "${ECHO_T}$ac_cv_header_pthreads_h" >&6 fi if test $ac_cv_header_pthreads_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_PTHREADS_H 1 _ACEOF HAVE_PTHREADS_H=1 else cat >>confdefs.h <<\_ACEOF #define HAVE_PTHREADS_H 0 _ACEOF HAVE_PTHREADS_H=0 fi for ac_func in pthread_mutex_init pthread_mutex_lock pthread_mutex_unlock do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking pthread mutex type" >&5 echo $ECHO_N "checking pthread mutex type... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_PTHREAD_H # include #endif #if HAVE_PTHREADS_H # include #endif int main () { pthread_mutex_t dmalloc_mutex; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define THREAD_MUTEX_T pthread_mutex_t _ACEOF echo "$as_me:$LINENO: result: pthread_mutex_t" >&5 echo "${ECHO_T}pthread_mutex_t" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: unknown" >&5 echo "${ECHO_T}unknown" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext echo "$as_me:$LINENO: checking pthread attribute initialization" >&5 echo $ECHO_N "checking pthread attribute initialization... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_PTHREAD_H # include #endif #if HAVE_PTHREADS_H # include #endif int main () { THREAD_MUTEX_T dmalloc_mutex; pthread_mutex_init(&dmalloc_mutex, pthread_mutexattr_default); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define THREAD_LOCK_INIT_VAL pthread_mutexattr_default _ACEOF echo "$as_me:$LINENO: result: pthread_mutexattr_default" >&5 echo "${ECHO_T}pthread_mutexattr_default" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >>confdefs.h <<\_ACEOF #define THREAD_LOCK_INIT_VAL 0 _ACEOF echo "$as_me:$LINENO: result: 0" >&5 echo "${ECHO_T}0" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$XX_OLD_LIBS ############################################################################## { echo "$as_me:$LINENO: functions" >&5 echo "$as_me: functions" >&6;} # auto-shutdown functions for ac_func in atexit on_exit do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test $ac_cv_func_atexit = no \ && test $ac_cv_func_on_exit = no \ && test $destructor_works = no; then { echo "$as_me:$LINENO: WARNING: " >&5 echo "$as_me: WARNING: " >&2;} { echo "$as_me:$LINENO: WARNING: The library cannot automatically shut itself down without" >&5 echo "$as_me: WARNING: The library cannot automatically shut itself down without" >&2;} { echo "$as_me:$LINENO: WARNING: atexit" >&5 echo "$as_me: WARNING: atexit" >&2;} { echo "$as_me:$LINENO: WARNING: call dmalloc_shutdown directly before exit to get get the" >&5 echo "$as_me: WARNING: call dmalloc_shutdown directly before exit to get get the" >&2;} { echo "$as_me:$LINENO: WARNING: final statistics and unfreed memory information." >&5 echo "$as_me: WARNING: final statistics and unfreed memory information." >&2;} { echo "$as_me:$LINENO: WARNING: " >&5 echo "$as_me: WARNING: " >&2;} fi # other bells and whistles for ac_func in fork gethostname getpid getuid time ctime do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in vprintf snprintf vsnprintf do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in recalloc memalign valloc do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # required although we have code for them in compat.c for ac_func in memcmp memcpy memmove memset do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strchr strrchr do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strlen strcmp strcpy strsep do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ############################################################################## { echo "$as_me:$LINENO: various functions for argv files" >&5 echo "$as_me: various functions for argv files" >&6;} # NOTE: some duplicated from above for ac_func in atoi atol getenv do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strchr strcmp strcpy strlen strncmp strncpy strsep do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ############################################################################## { echo "$as_me:$LINENO: various functions for argument checking" >&5 echo "$as_me: various functions for argument checking" >&6;} # NOTE: some duplicated from above for ac_func in atoi atol do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in bcmp bcopy bzero do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in index do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in memccpy memchr memcmp memcpy memmove memset do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in rindex do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strcasecmp strcat strchr strcmp strcpy strcspn strlen do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strncasecmp strncat strncmp strncpy do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strpbrk strrchr strspn strstr strtok do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_config_files="$ac_config_files Makefile" ac_config_commands="$ac_config_commands dmalloc.h.2" ac_config_commands="$ac_config_commands settings.h" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by dmalloc $as_me 5.5.2, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ dmalloc config.status 5.5.2 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS section. # # initialization commands ac_cv_c_const=$ac_cv_c_const ac_cv_strdup_macro=$ac_cv_strdup_macro ac_cv_type_size_t=$ac_cv_type_size_t ac_cv_header_stdarg_h=$ac_cv_header_stdarg_h _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "dmalloc.h.2" ) CONFIG_COMMANDS="$CONFIG_COMMANDS dmalloc.h.2" ;; "settings.h" ) CONFIG_COMMANDS="$CONFIG_COMMANDS settings.h" ;; "conf.h" ) CONFIG_HEADERS="$CONFIG_HEADERS conf.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@CXX@,$CXX,;t t s,@CXXFLAGS@,$CXXFLAGS,;t t s,@ac_ct_CXX@,$ac_ct_CXX,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@HAVE_STDARG_H@,$HAVE_STDARG_H,;t t s,@HAVE_STDLIB_H@,$HAVE_STDLIB_H,;t t s,@HAVE_STRING_H@,$HAVE_STRING_H,;t t s,@HAVE_UNISTD_H@,$HAVE_UNISTD_H,;t t s,@HAVE_SYS_TYPES_H@,$HAVE_SYS_TYPES_H,;t t s,@HAVE_SYS_MMAN_H@,$HAVE_SYS_MMAN_H,;t t s,@shlibdir@,$shlibdir,;t t s,@shlinkargs@,$shlinkargs,;t t s,@shlibext@,$shlibext,;t t s,@CXX_ON@,$CXX_ON,;t t s,@CXX_OFF@,$CXX_OFF,;t t s,@TH_ON@,$TH_ON,;t t s,@TH_OFF@,$TH_OFF,;t t s,@SL_ON@,$SL_ON,;t t s,@SL_OFF@,$SL_OFF,;t t s,@HAVE_SIGNAL_H@,$HAVE_SIGNAL_H,;t t s,@HAVE_SYS_CYGWIN_H@,$HAVE_SYS_CYGWIN_H,;t t s,@HAVE_W32API_WINDEF_H@,$HAVE_W32API_WINDEF_H,;t t s,@HAVE_W32API_WINBASE_H@,$HAVE_W32API_WINBASE_H,;t t s,@HAVE_PTHREAD_H@,$HAVE_PTHREAD_H,;t t s,@HAVE_PTHREADS_H@,$HAVE_PTHREADS_H,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } # Do quote $f, to prevent DOS paths from being IFS'd. echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_COMMANDS section. # for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue ac_dest=`echo "$ac_file" | sed 's,:.*,,'` ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_dir=`(dirname "$ac_dest") 2>/dev/null || $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_dest" : 'X\(//\)[^/]' \| \ X"$ac_dest" : 'X\(//\)$' \| \ X"$ac_dest" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_dest" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 echo "$as_me: executing $ac_dest commands" >&6;} case $ac_dest in dmalloc.h.2 ) newfile=dmalloc.h.2 rm -f $newfile.t echo '/* this is dmalloc.h.2 */' > $newfile.t echo '/* produced by configure, inserted into dmalloc.h */' >> $newfile.t echo '' >> $newfile.t if test "$ac_cv_c_const" = "yes"; then echo '/* const is available */' >> $newfile.t else echo '/* const is not available */' >> $newfile.t echo '#ifndef const' >> $newfile.t echo '#define const' >> $newfile.t echo '#endif' >> $newfile.t fi if test "$ac_cv_strdup_macro" = "yes"; then echo '/* strdup is a macro */' >> $newfile.t echo '#define DMALLOC_STRDUP_MACRO' >> $newfile.t else echo '/* strdup is not a macro */' >> $newfile.t echo '#undef DMALLOC_STRDUP_MACRO' >> $newfile.t fi echo '' >> $newfile.t echo '/*' >> $newfile.t echo ' * the definition of DMALLOC_SIZE' >> $newfile.t echo ' *' >> $newfile.t echo ' * NOTE: some architectures have malloc, realloc, etc.' >> $newfile.t echo ' * using unsigned instead of unsigned long. You may' >> $newfile.t echo ' * have to edit this by hand to fix any compilation' >> $newfile.t echo ' * warnings or errors.' >> $newfile.t echo ' */' >> $newfile.t if test "$ac_cv_type_size_t" = "yes"; then echo "#include " >> $newfile.t echo "#define DMALLOC_SIZE size_t" >> $newfile.t else echo "/* no include file needed */" >> $newfile.t echo "#define DMALLOC_SIZE unsigned long" >> $newfile.t fi echo '' >> $newfile.t echo '/*' >> $newfile.t echo ' * We use stdarg.h for the dmalloc_message and' >> $newfile.t echo ' * dmalloc_vmessage functions.' >> $newfile.t echo ' */' >> $newfile.t if test "$ac_cv_header_stdarg_h" = "yes"; then echo "#include " >> $newfile.t echo "#define DMALLOC_STDARG 1" >> $newfile.t else echo "/* no stdarg.h available */" >> $newfile.t echo "#define DMALLOC_STDARG 0" >> $newfile.t fi echo '' >> $newfile.t if cmp -s $newfile $newfile.t 2>/dev/null; then { echo "$as_me:$LINENO: $newfile is unchanged" >&5 echo "$as_me: $newfile is unchanged" >&6;} rm -f $newfile.t else rm -f $newfile mv $newfile.t $newfile fi ;; settings.h ) newfile=settings.h rm -f $newfile.t echo '/*' > $newfile.t echo ' * WARNING: this file was produced from settings.dist' >> $newfile.t echo ' * by the configure program. The configure script, when' >> $newfile.t echo ' * run again, will overwrite changed made here.' >> $newfile.t echo ' */' >> $newfile.t echo '' >> $newfile.t cat $srcdir/settings.dist >> $newfile.t if cmp -s $newfile.t $newfile 2>/dev/null; then { echo "$as_me:$LINENO: $newfile is unchanged" >&5 echo "$as_me: $newfile is unchanged" >&6;} rm -f $newfile.t else rm -f $newfile mv $newfile.t $newfile fi ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi { echo "$as_me:$LINENO: " >&5 echo "$as_me: " >&6;} { echo "$as_me:$LINENO: Please check-out Makefile and conf.h to make sure that" >&5 echo "$as_me: Please check-out Makefile and conf.h to make sure that" >&6;} { echo "$as_me:$LINENO: sane configuration values were a result." >&5 echo "$as_me: sane configuration values were a result." >&6;} { echo "$as_me:$LINENO: " >&5 echo "$as_me: " >&6;} { echo "$as_me:$LINENO: You may want to change values in settings.h before" >&5 echo "$as_me: You may want to change values in settings.h before" >&6;} { echo "$as_me:$LINENO: running 'make'." >&5 echo "$as_me: running 'make'." >&6;} { echo "$as_me:$LINENO: " >&5 echo "$as_me: " >&6;} { echo "$as_me:$LINENO: To run the basic library tests, you can execute:" >&5 echo "$as_me: To run the basic library tests, you can execute:" >&6;} { echo "$as_me:$LINENO: make light" >&5 echo "$as_me: make light" >&6;} { echo "$as_me:$LINENO: or" >&5 echo "$as_me: or" >&6;} { echo "$as_me:$LINENO: make heavy" >&5 echo "$as_me: make heavy" >&6;} { echo "$as_me:$LINENO: " >&5 echo "$as_me: " >&6;} dmalloc-5.5.2/dmalloc.spec000640 001751 001751 00000003025 10622115666 015376 0ustar00graygray000000 000000 # # Dmalloc RPM file for building of .rpm files for Redhat Linux systems. # # $Id: dmalloc.spec,v 1.37 2007/05/14 17:23:37 gray Exp $ # Summary: Debug Malloc (Dmalloc) Name: dmalloc Version: 5.5.2 Release: 1 Group: Development/Libraries Copyright: public domain URL: http://dmalloc.com/ Source: http://dmalloc.com/releases/%{name}-%{version}.tgz BuildRoot: /var/tmp/%{name}-buildroot Prefix: /usr %description The debug memory allocation or "dmalloc" library has been designed as a drop in replacement for the system's `malloc', `realloc', `calloc', `free' and other memory management routines while providing powerful debugging facilities configurable at runtime. These facilities include such things as memory-leak tracking, fence-post write detection, file/line number reporting, and general logging of statistics. It also provides support for the debugging of threaded programs. Releases and documentation available online. http://dmalloc.com/ %prep %setup %build CFLAGS="${RPM_OPT_FLAGS}" ./configure --prefix=${RPM_BUILD_ROOT}/usr --enable-threads --enable-shlib --enable-cxx # NOTE: we make the test program first because otherwise it screws up # and tried to use the .so instead of the .a for some stupid reason make dmalloc_t all light %install #make install installcxx installth installsl make install %clean rm -rf ${RPM_BUILD_ROOT} %files %defattr(444,root,root,755) %doc INSTALL README NEWS %doc docs/dmalloc.info docs/dmalloc.html docs/dmalloc.texi %attr(755,root,root) /usr/bin/dmalloc /usr/include/dmalloc.h /usr/lib/libdmalloc* dmalloc-5.5.2/mkinstalldirs000750 001751 001751 00000001243 10622115666 015714 0ustar00graygray000000 000000 #! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Last modified: 1995-03-05 # Public domain errstatus=0 for file in ${1+"$@"} ; do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d in ${1+"$@"} ; do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" 1>&2 mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$? fi if test ! -d "$pathcomp"; then errstatus=$lasterr fi pathcomp="$pathcomp/" done done exit $errstatus dmalloc-5.5.2/install-sh000750 001751 001751 00000012721 10622115666 015115 0ustar00graygray000000 000000 #! /bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 dmalloc-5.5.2/dmallocc.cc000640 001751 001751 00000004267 10622115666 015205 0ustar00graygray000000 000000 /* * File that facilitates C++ program debugging. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmallocc.cc,v 1.3 2003/05/15 20:08:46 gray Exp $ */ /* * This file is used to effectively redirect new to the more familiar * malloc and delete to the more familiar free so they can be debugged * with the debug malloc library.. They also give the known error * behavior, too. * * Compile and link this in with the C++ program you want to debug. * * NOTE: I am not a C++ hacker so feedback in the form of other hints * and ideas for C++ users would be much appreciated. */ extern "C" { #include #define DMALLOC_DISABLE #include "dmalloc.h" #include "return.h" } /* * An overload function for the C++ new. */ void * operator new(size_t size) { char *file; GET_RET_ADDR(file); return dmalloc_malloc(file, 0, size, DMALLOC_FUNC_NEW, 0 /* no alignment */, 0 /* no xalloc messages */); } /* * An overload function for the C++ new[]. */ void * operator new[](size_t size) { char *file; GET_RET_ADDR(file); return dmalloc_malloc(file, 0, size, DMALLOC_FUNC_NEW_ARRAY, 0 /* no alignment */, 0 /* no xalloc messages */); } /* * An overload function for the C++ delete. */ void operator delete(void *pnt) { char *file; GET_RET_ADDR(file); dmalloc_free(file, 0, pnt, DMALLOC_FUNC_DELETE); } /* * An overload function for the C++ delete[]. Thanks to Jens Krinke. */ void operator delete[](void *pnt) { char *file; GET_RET_ADDR(file); dmalloc_free(file, 0, pnt, DMALLOC_FUNC_DELETE_ARRAY); } dmalloc-5.5.2/dmalloc_argv_loc.h000640 001751 001751 00000016706 10622115666 016561 0ustar00graygray000000 000000 /* * Local defines for the argv module * * Copyright 1995 by Gray Watson * * This file is part of the argv library. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_argv_loc.h,v 1.10 2003/05/15 02:42:21 gray Exp $ */ #ifndef __ARGV_LOC_H__ #define __ARGV_LOC_H__ #include "dmalloc_argv.h" /* to get the types */ /* * some compilation options */ /* * generic constants */ /* special consideration for NULL. some compilers bitch if I redefine it */ #ifndef NULL #define NULL 0L #endif #undef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #undef NOERROR #define NOERROR 0 #undef ERROR #define ERROR (-1) #undef STDIN #define STDIN 0 /* * local argv defines */ #define ERROR_STREAM_INIT (FILE *)0x1 /* hack to init stderr FILE* */ #define NO_VALUE (-1) /* no mandatory args value */ #define ARRAY_INCR 10 /* increment by 10 every 10 */ #define SCREEN_WIDTH 79 /* width of screen till wrap */ #define BITS_IN_BYTE 8 /* bits in a byte */ #define SPECIAL_CHARS "e\033^^\"\"''\\\\n\nr\rt\tb\bf\fa\007" #define DUMP_SPACE_BUF 128 /* space for memory dump */ #define ARG_MALLOC_INCR 20 /* alloc in 10 increments */ #define FILE_LINE_SIZE 1024 /* max size of file lines */ /* internal flags set in the ar_type field */ /* NOTE: other external flags defined in argv.h */ #define ARGV_FLAG_USED (1 << 12) /* if arg has been specified */ /* error messages */ #define USAGE_ERROR_NAME "usage problem" #define INTERNAL_ERROR_NAME "internal argv error" /* * settings to vary the output of the argument routines */ #define PROGRAM_NAME 256 /* max size of program name */ #define EXIT_CODE 1 /* argv exit code for errors */ /* global env settings */ #define GLOBAL_NAME "GLOBAL_ARGV" /* global argv env name */ #define GLOBAL_CLOSE "close=" /* close arg setting */ #define GLOBAL_ENV "env=" /* env setting */ #define GLOBAL_ERROR "error=" /* error setting */ #define GLOBAL_MULTI "multi=" /* multi setting */ #define GLOBAL_USAGE "usage=" /* usage setting */ #define GLOBAL_LASTTOG "lasttog=" /* last-arg toggle */ /* special argument definitions */ #define LAST_ARG "--" /* arg to mark end of args */ #define LONG_PREFIX "--" /* prefix for long args */ #define SHORT_PREFIX "-" /* prefix for short args */ #define UNKNOWN_ARG "??" /* unknown argument output */ #define ARG_EQUALS '=' /* to assign value to option */ #define NUMBER_ARG_CHARS "0123456789+-." /* characters in numbers */ /* how to produce the env var using sprintf and the argv_program variable */ #define ENVIRON_FORMAT "ARGV_%s" /* special short-argument strings */ #define USAGE_CHAR_ARG '?' /* default short-opt usage */ /* special long-argument strings */ #define DISPLAY_ARG "argv-display" /* display arg variable vals */ #define FILE_ARG "argv-file" /* read args from file */ #define HELP_ARG "help" /* default help option */ #define USAGE_ARG "usage" /* default usage option */ #define USAGE_SHORT_ARG "usage-short" /* default usage-short opt */ #define USAGE_LONG_ARG "usage-long" /* default usage-long opt */ #define USAGE_ALL_ARG "usage-all" /* default usage-all opt */ #define VERSION_ARG "version" /* default version option */ /* spacing on line for usage messages */ #define SHORT_COLUMN 2 /* spaces to indent for short-args */ #define LONG_COLUMN 20 /* column for long options */ #define COMMENT_COLUMN 45 /* column for comments */ /* some in-line "labels" for comments */ #define USAGE_LABEL "Usage: " /* usage message start */ #define VERSION_LABEL "= " /* default:no version prefix */ #define LONG_LABEL "or " /* put before long-option */ #define COMMENT_LABEL "" /* put before comments */ #define ARRAY_LABEL " array" /* put after displayed type */ #define BOOL_ARG_LABEL "yes|no" /* label for bool-arg arg */ /* some sizeof defines */ #define SHORT_PREFIX_LENGTH (sizeof(SHORT_PREFIX) - 1) #define LONG_PREFIX_LENGTH (sizeof(LONG_PREFIX) - 1) #define USAGE_LABEL_LENGTH (sizeof(USAGE_LABEL) - 1) #define COMMENT_LABEL_LENGTH (sizeof(COMMENT_LABEL) - 1) #define LONG_LABEL_LENGTH (sizeof(LONG_LABEL) - 1) #define UNKNOWN_ARG_LENGTH (sizeof(UNKNOWN_ARG) - 1) #define BOOL_ARG_LENGTH (sizeof(BOOL_ARG_LABEL) - 1) #define HAS_ARG(type) (! (ARGV_TYPE(type) == ARGV_BOOL \ || ARGV_TYPE(type) == ARGV_BOOL_NEG \ || ARGV_TYPE(type) == ARGV_INCR \ || ARGV_TYPE(type) == ARGV_BOOL_INT \ || ARGV_TYPE(type) == ARGV_BOOL_INT_NEG)) /******************************** argv types *********************************/ /* strcture defining argv types */ typedef struct { unsigned int at_value; /* value of the type */ const char *at_name; /* name of the type */ unsigned int at_size; /* size of type */ const char *at_desc; /* description of the type */ } argv_type_t; static argv_type_t argv_types[] = { { ARGV_BOOL, "flag", sizeof(char), "if option used, set variable to 1" }, { ARGV_BOOL_NEG, "negative flag", sizeof(int), "if option used, set variable to 0" }, { ARGV_BOOL_ARG, "flag with arg", sizeof(char), "like boolean but with an argument, true/yes/1 sets var to 1" }, { ARGV_CHAR, "character", sizeof(char), "single character" }, { ARGV_CHAR_P, "string", sizeof(char *), "multiple characters terminated with a '\\0'" }, { ARGV_SHORT, "short integer", sizeof(short), "decimal short-sized integer value" }, { ARGV_U_SHORT, "unsigned short integer", sizeof(unsigned short), "decimal unsigned short-sized integer value" }, { ARGV_INT, "integer", sizeof(int), "decimal integer value" }, { ARGV_U_INT, "unsigned integer", sizeof(unsigned int), "decimal unsigned integer value" }, { ARGV_LONG, "long integer", sizeof(long), "decimal long-sized integer value" }, { ARGV_U_LONG, "unsigned long", sizeof(unsigned long), "decimal unsigned long-sized integer value" }, { ARGV_FLOAT, "floating point", sizeof(float), "real number with decimal point" }, { ARGV_DOUBLE, "double floating point", sizeof(double), "double precision real number with decimal point" }, { ARGV_BIN, "binary", sizeof(int), "base 2 value with digits of 0 or 1" }, { ARGV_OCT, "octal", sizeof(int), "base 8 value with digits from 0-7" }, { ARGV_HEX, "hexadecimal", sizeof(int), "base 16 value with digits from 0-9, A-F" }, { ARGV_INCR, "increment", sizeof(int), "increment variable each time option used" }, { ARGV_SIZE, "long size", sizeof(long), "size as long int + [bkmg] b=byte,k=kilo,m=meg,g=gig" }, { ARGV_U_SIZE, "unsigned long size", sizeof(unsigned long), "size as unsigned long int + [bkmg] b=byte,k=kilo,m=meg,g=gig" }, { ARGV_BOOL_INT, "integer boolean", sizeof(int), "if option used, set integer variable to 1" }, { ARGV_BOOL_INT_NEG, "integer boolean", sizeof(int), "if option used, set integer variable to 0" }, { ARGV_BOOL_INT_ARG, "integer boolean", sizeof(int), "like boolean but with an argument, true/yes/1 sets integer var to 1" }, { 0 } }; #endif /* ! __ARGV_LOC_H__ */ dmalloc-5.5.2/dmalloc_argv.h000640 001751 001751 00000035373 10622115666 015725 0ustar00graygray000000 000000 /* * Defines for a generic argv and argc processor... * * Copyright 1995 by Gray Watson * * This file is part of the argv library. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_argv.h,v 1.12 2005/12/18 14:47:02 gray Exp $ */ #ifndef __ARGV_H__ #define __ARGV_H__ /* * Version string for the library * * NOTE to gray: whenever this is changed, corresponding Changlog and * NEWS entries *must* be entered and 2 entries in argv.texi must be * updated. * * ARGV LIBRARY VERSION -- 2.5.0 */ /* produced by configure, inserted into argv.h */ /* used to handle the const operator */ /* const is available */ /* NOTE: start of $Id: dmalloc_argv.h,v 1.12 2005/12/18 14:47:02 gray Exp $ */ /* * Generic and standardized argument processor. You describe the arguments * that you are looking for along with their types and these routines do the * work to convert them into values. * * These routines also provide standardized error and usage messages as well * as good usage documentation and long and short options. */ #include /* have to for FILE * below */ /* this defines what type the standard void memory-pointer is */ #if (defined(__STDC__) && __STDC__ == 1) || defined(__cplusplus) #define ARGV_PNT void * #else #define ARGV_PNT char * #endif /* * argument information structure. this specifies the allowable options * and some information about each one. * * { 'O', "optimize", ARGV_BOOL, &optimize, NULL, "turn on optimization" } * { 'c', "config", ARGV_CHAR_P, &config, "file", "configuration file" } */ typedef struct { char ar_short_arg; /* short argument, 'd' if '-d' */ char *ar_long_arg; /* long version of arg, '--delete' */ unsigned int ar_type; /* type of option, see values below */ ARGV_PNT ar_variable; /* address of associated variable */ char *ar_var_label; /* label for variable description */ char *ar_comment; /* comment for usage message */ } argv_t; /* * Argument array type. when ARGV_FLAG_ARRAY is |'d with the ar_type * in the above structure then multiple instances of the option are * allowed and each instance is stored into the following structure * that MUST be in ar_variable in the above arg_t structure. * * NOTE: after the arguments have been processed, if aa_entryn is > 0 * then aa_entries needs to be free'd by user. argv_cleanup() can be * used for this */ typedef struct { int aa_entry_n; /* number of elements in aa_entrees */ ARGV_PNT aa_entries; /* entry list specified */ } argv_array_t; /* extract the count of the elements from an argv ARRAY */ #define ARGV_ARRAY_COUNT(array) ((array).aa_entry_n) /* extract WHICH entry of TYPE from an argv ARRAY */ #define ARGV_ARRAY_ENTRY(array, type, which) \ (((type *)(array).aa_entries)[which]) /* extract a pointer to WHICH entry of TYPE from an argv ARRAY */ #define ARGV_ARRAY_ENTRY_P(array, type, which) \ (((type *)(array).aa_entries) + which) /* special ar_short_arg value to mark the last entry in the argument array */ #define ARGV_LAST ((char)255) /* * special ar_short_arg value to mark mandatory arguments (i.e. arguments that * *must* be specified. for arguments that are not optional like [-b]. * to have a variable number of mandatory args then make the last MAND * entry be a ARG_ARRAY type. */ #define ARGV_MAND ((char)254) /* * special ar_short_arg value to mark that there is the possibility of * a mandatory argument here if one is specified. */ #define ARGV_MAYBE ((char)253) /* * special ar_short_arg value to say that the previous and next arguments in * the list should not be used together. * {'a'...}, {ARG_OR}, {'b'...}, {ARG_OR}, {'c'...} means * the user should only specific -a or -b or -c but not 2 or more. */ #define ARGV_OR ((char)252) /* * special ar_short_arg value that is the same as ARGV_OR but one of the args * must be used. * {'a'...}, {ARG_ONE_OF}, {'b'...}, {ARG_ONE_OF}, {'c'...} means * the user must specify one of -a or -b or -c but not 2 or more. * ARGV_XOR is there for compatibility with older versions. */ #define ARGV_ONE_OF ((char)251) #define ARGV_XOR ((char)251) /* * ar_type values of arg_t * NOTE: if this list is changed, some defines in argv_loc need to be changed */ #define ARGV_BOOL 1 /* boolean type, sets to ARGV_TRUE */ #define ARGV_BOOL_NEG 2 /* like bool but sets to ARGV_FALSE */ #define ARGV_BOOL_ARG 3 /* like bool but takes a yes/no arg */ #define ARGV_CHAR 4 /* single character */ #define ARGV_CHAR_P 5 /* same as STRING */ #define ARGV_SHORT 6 /* short integer number */ #define ARGV_U_SHORT 7 /* unsigned short integer number */ #define ARGV_INT 8 /* integer number */ #define ARGV_U_INT 9 /* unsigned integer number */ #define ARGV_LONG 10 /* long integer number */ #define ARGV_U_LONG 11 /* unsinged long integer number */ #define ARGV_FLOAT 12 /* floating pointer number */ #define ARGV_DOUBLE 13 /* double floating pointer number */ #define ARGV_BIN 14 /* binary number (0s and 1s) */ #define ARGV_OCT 15 /* octal number, (base 8) */ #define ARGV_HEX 16 /* hexadecimal number, (base 16) */ #define ARGV_INCR 17 /* int arg which gets ++ each time */ #define ARGV_SIZE 18 /* long arg which knows mMbBkKgG */ #define ARGV_U_SIZE 19 /* u_long arg which knows mMbBkKgG */ #define ARGV_BOOL_INT 20 /* like bool but takes an integer var*/ #define ARGV_BOOL_INT_NEG 21 /* like bool-neg but with an integer */ #define ARGV_BOOL_INT_ARG 22 /* like bool-arg but with an integer */ #define ARGV_TYPE(t) ((t) & 0x3F) /* strip off all but the var type */ #define ARGV_FLAG_ARRAY (1 << 14) /* OR with type to indicate array */ #define ARGV_FLAG_MAND (1 << 13) /* OR with type to mark mandatory */ /* NOTE: other internal flags defined in argv_loc.h */ /* argv_usage which argument values */ #define ARGV_USAGE_NONE 0 /* no usage messages -- special */ #define ARGV_USAGE_SHORT 1 /* print short usage messages */ #define ARGV_USAGE_LONG 2 /* print long-format usage messages */ #define ARGV_USAGE_DEFAULT 3 /* default usage messages */ #define ARGV_USAGE_SEE 4 /* say see --usage for more info */ #define ARGV_USAGE_SHORT_REM 5 /* short + reminder how to get long */ #define ARGV_USAGE_ALL 6 /* all usage information */ /* boolean type settings */ #define ARGV_FALSE 0 #define ARGV_TRUE 1 /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ /* This is a processed version of argv[0], pre-path removed: /bin/ls -> ls */ extern char argv_program[/* PROGRAM_NAME + 1 */]; /* A global value of argv from main after argv_process has been called */ extern char **argv_argv; /* A global value of argc from main after argv_process has been called */ extern int argv_argc; /* This should be set externally to provide general program help to user */ extern char *argv_help_string; /* This should be set externally to provide version information to the user */ extern char *argv_version_string; /* * Are we running interactively? This will exit on errors. Set to * false to return error codes instead. */ extern int argv_interactive; /* * The FILE stream that argv out_puts all its errors. Set to NULL to * not dump any error messages. Default is stderr. */ extern FILE *argv_error_stream; /* * This is the error code to exit with when we have a usage error and * we are in interactive mode. */ extern int argv_error_code; /* * Set to 1 (the default) to enable the handling of -l=foo or * --logfile=foo type of arguments. Set to 0 to disable. This allows * you to specifically assign a value to an argument. */ extern int argv_close_enable_b; /* * If the library sees a "--" argument, it will turn off further * argument process. Set to 1 to enable the ability of specifying * additional "--" arguments to reenable (basically toggle on then * off) argument processing. Set to 0 (the default) to disable this * behavior. */ extern int argv_last_toggle_b; /* * Set to 1 (the default) to have the library accept multiple usage of * the same argument. Set to 0 to have the library generate an error * if you use an argument twice. */ extern int argv_multi_accept_b; /* * Set to one of the ARGV_USAGE_ defines in the argv.h file. This * tell the library what usage information to display when --usage is * specified by the user. Default is ARGV_USAGE_LONG. */ extern int argv_usage_type; /* * Set to one of the ARGV_USAGE_ defines in the argv.h file. This * tell the library what usage information to display when an error is * encountered. The usage information accompanies the error message. * Default is ARGV_USAGE_SEE. */ extern int argv_error_type; /* * Set to 1 (the default) if you want the library look for associated * arguments from the associated program's environmental variable. If * set the 0 then no environmental variable will be used. If you are * running program foo then the library will look for the * environmental variable ARGV_foo and will add those to the argument * list specified on the command line. By default they will be * inserted in front of those on the command line unless the * argv_env_after_b is set to 1. * * NOTE: this is set by argv_process automatically. If you do not * want this behavior, you should use argv_process_no_env. */ extern int argv_process_env_b; /* * Set to 1 if you want the library to append the arguments from the * program's environmental variable after those specified on the * command line. If set the 0 (the default) then they will be * inserted before those specified on the command line. See * argv_process_env_b for more information. */ extern int argv_env_after_b; /* * int argv_process_no_env * * DESCRIPTION: * * Process the user arguments with an argv_t structure array. Like * argv_process_args but without the processing of the argv * environmental variables. * * RETURNS: * * Success - 0 * * Failure - -1 * * ARGUMENTS: * * args - Array of argv_t structures. * * arg_n - Number of arguments in the argv array. * * argv - Array of character pointers terminated by 0L. */ extern int argv_process_no_env(argv_t *args, const int arg_n, char **argv); /* * int argv_process * * DESCRIPTION: * * Processes a number of arguments depending on the argument array. * This routine will not modify the argv array in any way. * * NOTE: it will modify the args array by setting various flags in the * type field. returns 0 if no error else -1. * * ARGUMENTS: * * args - Array of argv_t structures that we are using to process the * user argument array. If null then an empty array is used. * * argc - Number of arguments in the argv argument array. * * argv - Array of character pointer arguments terminated by a 0L. */ extern int argv_process(argv_t *args, const int argc, char **argv); /* * int argv_usage * * DESCRIPTION: * * Print the standard usage messages for our argument array. You can * specify whether you want to see a short or long usage messages. * * NOTE: if this is called before argv_process then the program name * may be invalid. * * RETURNS: * * Success - 0 * * Failure - -1 * * ARGUMENTS: * * args - Our argument array to print the usage messages about. If * null then an empty array is used. * * which - Either ARGV_USAGE_SHORT (for short usage messages), * ARGV_USAGE_LONG (for long usage messages), or ARGV_USAGE_DEFAULT * (the user's default either long or short). */ extern int argv_usage(const argv_t *args, const int which); /* * int argv_was_used * * DESCRIPTION: * * See if an argument was used in a previous call to argv_process. * * RETURNS: * * 1 if yes it was used, else 0 if not. * * ARGUMENTS: * * args - Argument list to search. * * short_arg - Short argument to see if it was used. */ extern int argv_was_used(const argv_t *args, const char short_arg); /* * int argv_long_was_used * * DESCRIPTION: * * See if a long argument was used in a previous call to argv_process. * * RETURNS: * * 1 if yes it was used, else 0 if not. * * ARGUMENTS: * * args - Argument list to search. * * long_arg - Long argument to see if it was used. */ extern int argv_long_was_used(const argv_t *args, const char *long_arg); /* * int argv_entry_was_used * * DESCRIPTION: * * See if an entry in the argument array was used in a previous call * to argv_process. * * RETURNS: * * 1 if yes it was used, else 0 if not. * * ARGUMENTS: * * argv_entry_p - Pointer to an entry in a argv_t list. */ extern int argv_entry_was_used(const argv_t *argv_entry_p); /* * void argv_cleanup * * DESCRIPTION: * * Frees up any allocations associated with the argument array during * argv_process. This should be done at the end of the program or * after all the arguments have been referenced. * * RETURNS: * * None. * * ARGUMENTS: * * args - Argument array we are cleaning up. */ extern void argv_cleanup(const argv_t *args); /* * int argv_copy_args * * DESCRIPTION: * * Copy all the arguements (not including the 0th) one after the other * into the user specified buffer. * * NOTE: you can get the 0th argument from argv_argv[0] or * argv_program. * * RETURNS: * * Success - 0 * * Failure - -1 * * ARGUMENTS: * * buf - Buffer to copy all of the user arguments into. * * buf_size - Size of the buffer. */ extern int argv_copy_args(char *buf, const int buf_size); /* * int argv_value_string * * DESCRIPTION: * * Convert the value of a RC entry to its string equivalent in the * buffer provided. * * RETURNS: * * Length of bytes copied into the buffer. * * ARGUMENTS: * * argv_entry_p - Pointer to an entry in a argv_t list. * * buf - Buffer to convert the value into. * * buf_size - Size of the buffer. */ extern int argv_value_string(const argv_t *argv_entry_p, char *buf, const int buf_size); /* * int argv_type_info * * DESCRIPTION: * * Get internal information about the type of the argument. * * RETURNS: * * The name of the type. * * ARGUMENTS: * * type - Number of argument type. * * size_p - Pointer to an unsigned integer which, if not NULL, will be * set with the size of the type. * * desc_p - Pointer to a constant character pointer which, if not * NULL, will be pointed to a description of the type. */ extern const char *argv_type_info(const unsigned int type, unsigned int *size_p, const char **desc_p); /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __ARGV_H__ */ dmalloc-5.5.2/dmalloc_argv.c000640 001751 001751 00000251033 10622115666 015711 0ustar00graygray000000 000000 /* * Generic argv processor... * * Copyright 1995 by Gray Watson * * This file is part of the argv library. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ */ #include #include #if HAVE_STRING_H # include #endif #if HAVE_STDLIB_H # include #endif #include "conf.h" #include "dmalloc_argv.h" #include "dmalloc_argv_loc.h" #include "compat.h" /* internal routines */ static void do_list(argv_t *grid, const int arg_c, char **argv, argv_t **queue_list, int *queue_head_p, int *queue_tail_p, int *okay_bp); /* * exported variables */ /* This is a processed version of argv[0], pre-path removed: /bin/ls -> ls */ char argv_program[PROGRAM_NAME + 1] = "Unknown"; /* A global value of argv from main after argv_process has been called */ char **argv_argv = NULL; /* A global value of argc from main after argv_process has been called */ int argv_argc = 0; /* This should be set externally to provide general program help to user */ char *argv_help_string = NULL; /* This should be set externally to provide version information to the user */ char *argv_version_string = NULL; /* * Are we running interactively? This will exit on errors. Set to * false to return error codes instead. */ int argv_interactive = ARGV_TRUE; /* * The FILE stream that argv out_puts all its errors. Set to NULL to * not dump any error messages. Default is stderr. */ FILE *argv_error_stream = ERROR_STREAM_INIT; /* * This is the error code to exit with when we have a usage error and * we are in interactive mode. */ int argv_error_code = EXIT_CODE; /* * global settings */ /* * Set to 1 (the default) to enable the handling of -l=foo or * --logfile=foo type of arguments. Set to 0 to disable. This allows * you to specifically assign a value to an argument. */ int argv_close_enable_b = 1; /* * If the library sees a "--" argument, it will turn off further * argument process. Set to 1 to enable the ability of specifying * additional "--" arguments to reenable (basically toggle on then * off) argument processing. Set to 0 (the default) to disable this * behavior. */ int argv_last_toggle_b = 0; /* * Set to 1 (the default) to have the library accept multiple usage of * the same argument. Set to 0 to have the library generate an error * if you use an argument twice. */ int argv_multi_accept_b = 1; /* * Set to one of the ARGV_USAGE_ defines in the argv.h file. This * tell the library what usage information to display when --usage is * specified by the user. Default is ARGV_USAGE_LONG. */ int argv_usage_type = ARGV_USAGE_LONG; /* * Set to one of the ARGV_USAGE_ defines in the argv.h file. This * tell the library what usage information to display when an error is * encountered. The usage information accompanies the error message. * Default is ARGV_USAGE_SEE. */ int argv_error_type = ARGV_USAGE_SEE; /* * Set to 1 (the default) if you want the library look for associated * arguments from the associated program's environmental variable. If * set the 0 then no environmental variable will be used. If you are * running program foo then the library will look for the * environmental variable ARGV_foo and will add those to the argument * list specified on the command line. By default they will be * inserted in front of those on the command line unless the * argv_env_after_b is set to 1. * * NOTE: this is set by argv_process automatically. If you do not * want this behavior, you should use argv_process_no_env. */ int argv_process_env_b = 1; /* * Set to 1 if you want the library to append the arguments from the * program's environmental variable after those specified on the * command line. If set the 0 (the default) then they will be * inserted before those specified on the command line. See * argv_process_env_b for more information. */ int argv_env_after_b = 0; /* * local variables */ /* empty argument array */ static argv_t empty[] = {{ ARGV_LAST, NULL, 0, NULL, NULL, NULL }}; static int enabled_b = ARGV_FALSE; /* are the lights on? */ /****************************** startup routine ******************************/ /* * static void argv_startup * * DESCRIPTION: * * Turn on the lights. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ static void argv_startup(void) { if (enabled_b) { return; } enabled_b = ARGV_TRUE; /* ANSI says we cannot predefine this above */ if (argv_error_stream == ERROR_STREAM_INIT) { argv_error_stream = stderr; } } /***************************** general utilities *****************************/ /* * static int btoi * * DESCRIPTION: * * Binary string to integer translation. * * RETURNS: * * Integer converted from the string. * * ARGUMENTS: * * str - String of binary 0s and 1s that we are converting. */ static int btoi(const char *str) { int ret = 0; /* strip off spaces */ for (; isspace(*str); str++) { } for (; *str == '0' || *str == '1'; str++) { ret *= 2; ret += *str - '0'; } return ret; } /* * static int otoi * * DESCRIPTION: * * Octal string to integer translation. * * RETURNS: * * Integer converted from the string. * * ARGUMENTS: * * str - String of octal digits that we are converting. */ static int otoi(const char *str) { int ret = 0; /* strip off spaces */ for (; isspace(*str); str++) { } for (; *str >= '0' && *str <= '7'; str++) { ret *= 8; ret += *str - '0'; } return ret; } /* * static int htoi * * DESCRIPTION: * * Hexadecimal string to integer translation. * * RETURNS: * * Integer converted from the string. * * ARGUMENTS: * * str - String of hexadecimal characters and digits that we are * converting. */ static int htoi(const char *str) { int ret = 0; /* strip off spaces */ for (; isspace(*str); str++) { } /* skip a leading 0[xX] */ if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) { str += 2; } for (; isdigit(*str) || (*str >= 'a' && *str <= 'f') || (*str >= 'A' && *str <= 'F'); str++) { ret *= 16; if (*str >= 'a' && *str <= 'f') { ret += *str - 'a' + 10; } else if (*str >= 'A' && *str <= 'F') { ret += *str - 'A' + 10; } else { ret += *str - '0'; } } return ret; } /* * static char *string_copy * * DESCRIPTION: * * Basically a strdup for compatibility sake. * * RETURNS: * * Character pointer that must be freed later. * * ARGUMENTS: * * str - String we are copying. */ static char *string_copy(const char *str) { const char *str_p; char *copy, *copy_p; int len; len = strlen(str); copy = (char *)malloc(len + 1); if (copy == NULL) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: memory error during argument processing\n", argv_program); } if (argv_interactive) { (void)exit(argv_error_code); } return NULL; } for (str_p = str, copy_p = copy; *str_p != '\0';) { *copy_p++ = *str_p++; } *copy_p = '\0'; return copy; } /* * static char **vectorize * * DESCRIPTION: * * Break a string up into its arguments separated by one of the * characters in a token string and return an array of char pointers. * * NOTE: the string argument should stay around until that time. * * RETURNS: * * Success - Allocated list of character poiners into the string * argument which must be freed later. * * Failure - NULL * * ARGUMENTS: * * str - String we are tokenizing. * * tok - List of token characters to look for in the string. * * num_tok_p - Pointer to an integer which will be set to the number * of tokens found in the string. */ static char **vectorize(char *str, const char *tok, int *num_tok_p) { char **vect_p; char *tmp, *str_p, *tok_p; int tok_c, tok_n; /* count the tokens */ tmp = string_copy(str); if (tmp == NULL) { return NULL; } str_p = tmp; tok_c = 0; while (1) { tok_p = strsep(&str_p, tok); if (tok_p == NULL) { break; } if (*tok_p != '\0') { tok_c++; } } tok_n = tok_c; free(tmp); *num_tok_p = tok_n; if (tok_c == 0) { return NULL; } /* allocate the pointer grid */ vect_p = (char **)malloc(sizeof(char *) * tok_c); if (vect_p == NULL) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: memory error during argument processing\n", argv_program); } if (argv_interactive) { (void)exit(argv_error_code); } return NULL; } /* load the tokens into the list */ str_p = str; for (tok_c = 0; tok_c < tok_n;) { tok_p = strsep(&str_p, tok); if (tok_p == NULL) { break; } if (*tok_p != '\0') { vect_p[tok_c] = tok_p; tok_c++; } } return vect_p; } /* * static int expand_buf * * DESCRIPTION: * * Translates a buffer of bytes into its printable version. * * NOTE: it does _not_ add a \0 at the end of OUT. * * RETURNS: * * Number of characters written in to the output buffer. * * ARGUMENTS: * * buf - Input buffer of bytes. * * buf_size - Size of the input buffer. If < 0 then the routing will * translate up to the first \0. * * out - Output buffer for the translated characters. * * out_size - Maximum size of the output buffer. */ static int expand_buf(const void *buf, const int buf_size, char *out, const int out_size) { int buf_c; const unsigned char *buf_p, *spec_p; char *max_p, *out_p = out; /* setup our max pointer */ max_p = out + out_size; /* run through the input buffer, counting the characters as we go */ for (buf_c = 0, buf_p = (const unsigned char *)buf;; buf_c++, buf_p++) { /* did we reach the end of the buffer? */ if (buf_size < 0) { if (*buf_p == '\0') { break; } } else { if (buf_c >= buf_size) { break; } } /* search for special characters */ for (spec_p = (unsigned char *)SPECIAL_CHARS + 1; *(spec_p - 1) != '\0'; spec_p += 2) { if (*spec_p == *buf_p) { break; } } /* did we find one? */ if (*(spec_p - 1) != '\0') { if (out_p + 2 >= max_p) { break; } (void)loc_snprintf(out_p, max_p - out_p, "\\%c", *(spec_p - 1)); out_p += 2; continue; } /* print out any 7-bit printable characters */ if (*buf_p < 128 && isprint(*buf_p)) { if (out_p + 1 >= max_p) { break; } *out_p = *(char *)buf_p; out_p += 1; } else { if (out_p + 4 >= max_p) { break; } (void)loc_snprintf(out_p, max_p - out_p, "\\%03o", *buf_p); out_p += 4; } } return out_p - out; } /****************************** usage routines *******************************/ /* * static void usage_short * * DESCRIPTION: * * Print a short-format usage message. * * RETURNS: * * None. * * ARGUMENTS: * * args - Array of argv_t structions whose usage messages you print. * * flags - User flags. */ static void usage_short(const argv_t *args, const int flag) { const argv_t *arg_p; int len, col_c = 0; int mark_b = ARGV_FALSE; char *prefix; if (argv_error_stream == NULL) { return; } /* print the usage message header */ (void)fprintf(argv_error_stream, "%s%s", USAGE_LABEL, argv_program); col_c += USAGE_LABEL_LENGTH + strlen(argv_program); /* * print all of the boolean arguments first. * NOTE: we assume they all fit on the line */ for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { /* skip or-specifiers */ if (arg_p->ar_short_arg == ARGV_OR || arg_p->ar_short_arg == ARGV_XOR) { continue; } /* skip non booleans */ if (HAS_ARG(arg_p->ar_type)) { continue; } /* skip args with no short component */ if (arg_p->ar_short_arg == '\0') { continue; } if (! mark_b) { len = 2 + SHORT_PREFIX_LENGTH; prefix = " ["; /* we check for -2 here because we should have 1 arg and ] on line */ if (col_c + len > SCREEN_WIDTH - 2) { (void)fprintf(argv_error_stream, "\n%*.*s", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, ""); col_c = USAGE_LABEL_LENGTH; /* if we are the start of a line, skip any starting spaces */ if (*prefix == ' ') { prefix++; len--; } } (void)fprintf(argv_error_stream, "%s%s", prefix, SHORT_PREFIX); col_c += len; mark_b = ARGV_TRUE; } len = 1; /* we check for -1 here because we should need ] */ if (col_c + len > SCREEN_WIDTH - 1) { (void)fprintf(argv_error_stream, "]\n%*.*s", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, ""); col_c = USAGE_LABEL_LENGTH; /* restart the short option list */ (void)fprintf(argv_error_stream, "[%s", SHORT_PREFIX); col_c += 1 + SHORT_PREFIX_LENGTH; } (void)fprintf(argv_error_stream, "%c", arg_p->ar_short_arg); col_c++; } if (mark_b) { (void)fprintf(argv_error_stream, "]"); col_c++; } /* print remaining (non-boolean) arguments */ for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { int var_len; char *var_str, *postfix; /* skip or-specifiers */ if (arg_p->ar_short_arg == ARGV_OR || arg_p->ar_short_arg == ARGV_XOR) { continue; } /* skip booleans types */ if (! HAS_ARG(arg_p->ar_type)) { continue; } if (arg_p->ar_var_label == NULL) { if (ARGV_TYPE(arg_p->ar_type) == ARGV_BOOL_ARG || ARGV_TYPE(arg_p->ar_type) == ARGV_BOOL_INT_ARG) { var_str = BOOL_ARG_LABEL; var_len = BOOL_ARG_LENGTH; } else { var_len = UNKNOWN_ARG_LENGTH; var_str = UNKNOWN_ARG; } } else { var_len = strlen(arg_p->ar_var_label); var_str = arg_p->ar_var_label; } if (arg_p->ar_short_arg == ARGV_MAND) { /* print the mandatory argument desc */ len = 1 + var_len; prefix = " "; postfix = ""; } else if (arg_p->ar_short_arg == ARGV_MAYBE) { /* print the maybe argument desc */ len = 2 + var_len + 1; prefix = " ["; postfix = "]"; } else { /* handle options with arguments */ /* " [" + short_prefix + char */ len = 2 + SHORT_PREFIX_LENGTH + 1; prefix = " ["; /* do we need to wrap */ if (col_c + len > SCREEN_WIDTH) { (void)fprintf(argv_error_stream, "\n%*.*s", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, ""); col_c = USAGE_LABEL_LENGTH; /* if we are the start of a line, skip any starting spaces */ if (*prefix == ' ') { prefix++; len--; } } (void)fprintf(argv_error_stream, "%s%s%c", prefix, SHORT_PREFIX, arg_p->ar_short_arg); col_c += len; len = 1 + var_len + 1; prefix = " "; postfix = "]"; } if (col_c + len > SCREEN_WIDTH) { (void)fprintf(argv_error_stream, "\n%*.*s", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, ""); col_c = USAGE_LABEL_LENGTH; /* if we are the start of a line, skip any starting spaces */ if (*prefix == ' ') { prefix++; len--; } } (void)fprintf(argv_error_stream, "%s%s%s", prefix, var_str, postfix); col_c += len; } (void)fprintf(argv_error_stream, "\n"); if (flag == ARGV_USAGE_SHORT_REM) { (void)fprintf(argv_error_stream, "%*.*sUse the '%s%s' argument for more assistance.\n", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "", LONG_PREFIX, USAGE_ARG); } } /* * static void display_arg * * DESCRIPTION: * * Display an argument type while keeping track of the column we are * in. * * RETURNS: * * None. * * ARGUMENTS: * * stream - Output stream we are writing to. * * arg_p - Argument that we are displaying. * * max - Maximum column position to write to. * * col_cp - Pointer to an integer to record the column position. */ static void display_arg(FILE *stream, const argv_t *arg_p, const int max, int *col_cp) { int var_len, len; if (arg_p->ar_var_label == NULL) { var_len = 0; } else { var_len = strlen(arg_p->ar_var_label); } switch (ARGV_TYPE(arg_p->ar_type)) { case ARGV_BOOL: case ARGV_BOOL_NEG: case ARGV_INCR: case ARGV_BOOL_INT: case ARGV_BOOL_INT_NEG: break; case ARGV_BOOL_ARG: case ARGV_BOOL_INT_ARG: (void)fprintf(stream, "%s", BOOL_ARG_LABEL); (*col_cp) += BOOL_ARG_LENGTH; break; case ARGV_CHAR: case ARGV_CHAR_P: case ARGV_SHORT: case ARGV_U_SHORT: case ARGV_INT: case ARGV_U_INT: case ARGV_LONG: case ARGV_U_LONG: case ARGV_FLOAT: case ARGV_DOUBLE: case ARGV_BIN: case ARGV_OCT: case ARGV_HEX: case ARGV_SIZE: case ARGV_U_SIZE: if (arg_p->ar_var_label == NULL) { len = max - *col_cp; (void)fprintf(stream, "%-.*s", len, UNKNOWN_ARG); *col_cp += MIN(len, (int)UNKNOWN_ARG_LENGTH); } else { len = max - *col_cp; (void)fprintf(stream, "%-.*s", len, arg_p->ar_var_label); *col_cp += MIN(len, var_len); } break; } } /* * static void display_option * * DESCRIPTION: * * Display an option entry while while keeping track of the column we * are in. * * RETURNS: * * None. * * ARGUMENTS: * * stream - Output stream we are writing to. * * arg_p - Argument that we are displaying. * * max - Maximum column position to write to. * * col_cp - Pointer to an integer to record the column position. */ static void display_option(FILE *stream, const argv_t *arg_p, int *col_cp) { if (stream == NULL) { return; } (void)fputc('[', stream); (*col_cp)++; /* arg maybe does not have a -? preface */ if (arg_p->ar_short_arg != ARGV_MAYBE) { (void)fprintf(stream, "%s%c", SHORT_PREFIX, arg_p->ar_short_arg); *col_cp += SHORT_PREFIX_LENGTH + 1; if (HAS_ARG(arg_p->ar_type)) { /* display optional argument */ (void)fputc(' ', stream); (*col_cp)++; } } display_arg(stream, arg_p, LONG_COLUMN - 1, col_cp); (void)fputc(']', stream); (*col_cp)++; } /* * static void usage_long * * DESCRIPTION: * * Print a long-format usage message. * * RETURNS: * * None. * * ars - Array of argv_t structures whose usage we are printing. */ static void usage_long(const argv_t *args) { const argv_t *arg_p; int col_c, len; if (argv_error_stream == NULL) { return; } /* print the usage message header */ (void)fprintf(argv_error_stream, "%s%s\n", USAGE_LABEL, argv_program); /* run through the argument structure */ for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { /* skip or specifiers */ if (arg_p->ar_short_arg == ARGV_OR || arg_p->ar_short_arg == ARGV_XOR) { continue; } /* indent to the short-option col_c */ (void)fprintf(argv_error_stream, "%*.*s", SHORT_COLUMN, SHORT_COLUMN, ""); /* start column counter */ col_c = SHORT_COLUMN; /* print the short-arg stuff if there */ if (arg_p->ar_short_arg == '\0') { (void)fputc('[', argv_error_stream); col_c++; } else { if (arg_p->ar_short_arg == '\0') { ; } else if (arg_p->ar_short_arg == ARGV_MAND) { display_arg(argv_error_stream, arg_p, COMMENT_COLUMN, &col_c); } else { /* ARGV_MAYBE handled here */ display_option(argv_error_stream, arg_p, &col_c); } /* put the long-option message on the correct column */ if (col_c < LONG_COLUMN) { (void)fprintf(argv_error_stream, "%*.*s", LONG_COLUMN - col_c, LONG_COLUMN - col_c, ""); col_c = LONG_COLUMN; } } /* print the long-option message */ if (arg_p->ar_long_arg != NULL) { len = COMMENT_COLUMN - col_c - (LONG_PREFIX_LENGTH + 1); if (arg_p->ar_short_arg != '\0') { (void)fprintf(argv_error_stream, "%s", LONG_LABEL); col_c += LONG_LABEL_LENGTH; len -= LONG_LABEL_LENGTH; } (void)fprintf(argv_error_stream, "%s%-.*s", LONG_PREFIX, len, arg_p->ar_long_arg); col_c += LONG_PREFIX_LENGTH + MIN(len, (int)strlen(arg_p->ar_long_arg)); } /* add the optional argument if no short-arg */ if (arg_p->ar_short_arg == '\0') { if (HAS_ARG(arg_p->ar_type)) { (void)fputc(' ', argv_error_stream); col_c++; } /* display any optional arguments */ display_arg(argv_error_stream, arg_p, COMMENT_COLUMN - 1, &col_c); (void)fputc(']', argv_error_stream); col_c++; } /* print the comment */ if (arg_p->ar_comment != NULL) { /* put the comment message on the correct column */ if (col_c < COMMENT_COLUMN) { (void)fprintf(argv_error_stream, "%*.*s", COMMENT_COLUMN - col_c, COMMENT_COLUMN - col_c, ""); col_c = COMMENT_COLUMN; } len = SCREEN_WIDTH - col_c - COMMENT_LABEL_LENGTH; (void)fprintf(argv_error_stream, "%s%-.*s", COMMENT_LABEL, len, arg_p->ar_comment); } (void)fprintf(argv_error_stream, "\n"); } } /* * static void do_usage * * DESCRIPTION: * * Print the usage messages. * * RETURNS: * * None. * * ARGUMENTS: * * args - Array of argv_t structures. * * flag - Users flags which will tell us whether to display short or * long usage messages. */ static void do_usage(const argv_t *args, const int flag) { if (argv_error_stream == NULL) { return; } if (flag == ARGV_USAGE_SEE) { (void)fprintf(argv_error_stream, "%*.*sUse the '%s%s' argument for assistance.\n", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "", LONG_PREFIX, USAGE_ARG); } else if (flag == ARGV_USAGE_SHORT || flag == ARGV_USAGE_SHORT_REM) { usage_short(args, flag); } else if (flag == ARGV_USAGE_LONG || flag == ARGV_USAGE_ALL) { usage_long(args); } if (flag == ARGV_USAGE_ALL) { (void)fprintf(argv_error_stream, "\n"); (void)fprintf(argv_error_stream, "%*.*sUse '%s%s' for default usage information.\n", SHORT_COLUMN, SHORT_COLUMN, "", LONG_PREFIX, USAGE_ARG); (void)fprintf(argv_error_stream, "%*.*sUse '%s%s' for short usage information.\n", SHORT_COLUMN, SHORT_COLUMN, "", LONG_PREFIX, USAGE_SHORT_ARG); (void)fprintf(argv_error_stream, "%*.*sUse '%s%s' for long usage information.\n", SHORT_COLUMN, SHORT_COLUMN, "", LONG_PREFIX, USAGE_LONG_ARG); (void)fprintf(argv_error_stream, "%*.*sUse '%s%s' for all usage information.\n", SHORT_COLUMN, SHORT_COLUMN, "", LONG_PREFIX, USAGE_ALL_ARG); (void)fprintf(argv_error_stream, "%*.*sUse '%s%s' to display the help message.\n", SHORT_COLUMN, SHORT_COLUMN, "", LONG_PREFIX, HELP_ARG); (void)fprintf(argv_error_stream, "%*.*sUse '%s%s' to display the version message.\n", SHORT_COLUMN, SHORT_COLUMN, "", LONG_PREFIX, VERSION_ARG); (void)fprintf(argv_error_stream, "%*.*sUse '%s%s' to display the options and their values.\n", SHORT_COLUMN, SHORT_COLUMN, "", LONG_PREFIX, DISPLAY_ARG); } } /******************************* preprocessing *******************************/ /* * static int preprocess_array * * DESCRIPTION: * * Preprocess argument array entries and set the mandatory and maybe * flags. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * args - Array of argv_t structures. * * arg_n - Number of entries in the argv_t array. We need this for a * couple of reasons. */ static int preprocess_array(argv_t *args, const int arg_n) { argv_t *arg_p; int mand_array_b = ARGV_FALSE, maybe_field_b = ARGV_FALSE; /* count the args and find the first mandatory */ for (arg_p = args; arg_p < args + arg_n; arg_p++) { /* clear internal flags */ arg_p->ar_type &= ~ARGV_FLAG_USED; /* do we have a mandatory-array? */ if (arg_p->ar_short_arg == ARGV_MAND) { if (mand_array_b) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, no ARGV_MAND's can follow a MAND or MAYBE array\n", argv_program, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } if (maybe_field_b) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, no ARGV_MAND's can follow a ARGV_MAYBE\n", argv_program, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } if (arg_p->ar_type & ARGV_FLAG_ARRAY) { mand_array_b = ARGV_TRUE; } } /* do we have a maybe field? */ if (arg_p->ar_short_arg == ARGV_MAYBE) { if (mand_array_b) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, no ARGV_MAYBE's can follow a MAND or MAYBE array\n", argv_program, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } maybe_field_b = ARGV_TRUE; if (arg_p->ar_type & ARGV_FLAG_ARRAY) { mand_array_b = ARGV_TRUE; } } /* handle initializing the argument array */ if (arg_p->ar_type & ARGV_FLAG_ARRAY) { argv_array_t *arrp = (argv_array_t *)arg_p->ar_variable; if (! HAS_ARG(arg_p->ar_type)) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, cannot have an array of boolean values\n", argv_program, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } if (ARGV_TYPE(arg_p->ar_type) == ARGV_INCR) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, cannot have an array of incremental values\n", argv_program, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } arrp->aa_entry_n = 0; } /* verify variable pointer */ if (arg_p->ar_variable == NULL && arg_p->ar_short_arg != ARGV_OR && arg_p->ar_short_arg != ARGV_XOR) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, NULL variable specified in arg array\n", argv_program, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } /* verify [X]OR's */ if (arg_p->ar_short_arg == ARGV_OR || arg_p->ar_short_arg == ARGV_XOR) { /* that they are not at the start or end of list */ if (arg_p == args || arg_p >= (args + arg_n - 1)) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, ARGV_[X]OR entries cannot be at start or end of array\n", argv_program, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } /* that two aren't next to each other */ if ((arg_p - 1)->ar_short_arg == ARGV_OR || (arg_p - 1)->ar_short_arg == ARGV_XOR) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, two ARGV_[X]OR entries cannot be next to each other\n", argv_program, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } } } return NOERROR; } /* * static int string_to_value * * DESCRIPTION: * * Translate string value argument into a variable value depending on * its type. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * arg - Argument string. * * var - Pointer to our variable. * * type - Type of the variable. */ static int string_to_value(const char *arg, ARGV_PNT var, const unsigned int type) { argv_array_t *arr_p; argv_type_t *type_p; unsigned int val_type = ARGV_TYPE(type), size = 0; /* find the type and the size for array */ for (type_p = argv_types; type_p->at_value != 0; type_p++) { if (type_p->at_value == val_type) { size = type_p->at_size; break; } } if (type_p->at_value == 0) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: illegal variable type %d\n", __FILE__, val_type); } return ERROR; } if (type & ARGV_FLAG_ARRAY) { arr_p = (argv_array_t *)var; if (arr_p->aa_entry_n == 0) { arr_p->aa_entries = (char *)malloc(ARRAY_INCR *size); } else if (arr_p->aa_entry_n % ARRAY_INCR == 0) { arr_p->aa_entries = (char *)realloc(arr_p->aa_entries, (arr_p->aa_entry_n + ARRAY_INCR) * size); } if (arr_p->aa_entries == NULL) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: memory error during argument processing\n", argv_program); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } var = (char *)(arr_p->aa_entries) + arr_p->aa_entry_n * size; arr_p->aa_entry_n++; } /* translate depending on type */ switch (val_type) { case ARGV_BOOL: /* if no close argument, set to true */ if (arg == NULL) { *(char *)var = ARGV_TRUE; } else if (*(char *)arg == 't' || *(char *)arg == 'T' || *(char *)arg == 'y' || *(char *)arg == 'Y' || *(char *)arg == '1') { *(char *)var = ARGV_TRUE; } else { *(char *)var = ARGV_FALSE; } break; case ARGV_BOOL_NEG: /* if no close argument, set to false */ if (arg == NULL) { *(char *)var = ARGV_FALSE; } else if (*(char *)arg == 't' || *(char *)arg == 'T' || *(char *)arg == 'y' || *(char *)arg == 'Y' || *(char *)arg == '1') { *(char *)var = ARGV_TRUE; } else { *(char *)var = ARGV_FALSE; } break; case ARGV_BOOL_ARG: if (*(char *)arg == 't' || *(char *)arg == 'T' || *(char *)arg == 'y' || *(char *)arg == 'Y' || *(char *)arg == '1') { *(char *)var = ARGV_TRUE; } else { *(char *)var = ARGV_FALSE; } break; case ARGV_CHAR: *(char *)var = *(char *)arg; break; case ARGV_CHAR_P: *(char **)var = string_copy((char *)arg); if (*(char **)var == NULL) { return ERROR; } break; case ARGV_SHORT: *(short *)var = (short)atoi(arg); break; case ARGV_U_SHORT: *(unsigned short *)var = (unsigned short)atoi(arg); break; case ARGV_INT: *(int *)var = atoi(arg); break; case ARGV_U_INT: *(unsigned int *)var = atoi(arg); break; case ARGV_LONG: *(long *)var = atol(arg); break; case ARGV_U_LONG: *(unsigned long *)var = atol(arg); break; case ARGV_FLOAT: (void)sscanf(arg, "%f", (float *)var); break; case ARGV_DOUBLE: (void)sscanf(arg, "%lf", (double *)var); break; case ARGV_BIN: *(int *)var = btoi(arg); break; case ARGV_OCT: *(int *)var = otoi(arg); break; case ARGV_HEX: *(int *)var = htoi(arg); break; case ARGV_INCR: /* if no close argument then increment else set the value */ if (arg == NULL) { (*(int *)var)++; } else { *(int *)var = atoi(arg); } break; case ARGV_SIZE: { const char *arg_p; long val; /* take initial integer point */ val = atol(arg); for (arg_p = arg; *arg_p == ' ' || *arg_p == '-' || *arg_p == '+' || (*arg_p >= '0' && *arg_p <= '9'); arg_p++) { } if (*arg_p == 'b' || *arg_p == 'B') { val *= 1; } else if (*arg_p == 'k' || *arg_p == 'B') { val *= 1024; } else if (*arg_p == 'm' || *arg_p == 'M') { val *= 1024 * 1024; } else if (*arg_p == 'g' || *arg_p == 'G') { val *= 1024 * 1024 * 1024; } *(long *)var = val; } break; case ARGV_U_SIZE: { const char *arg_p; unsigned long val; /* take initial integer point */ val = (unsigned long)atol(arg); for (arg_p = arg; *arg_p == ' ' || *arg_p == '-' || *arg_p == '+' || (*arg_p >= '0' && *arg_p <= '9'); arg_p++) { } if (*arg_p == 'b' || *arg_p == 'B') { val *= 1; } else if (*arg_p == 'k' || *arg_p == 'B') { val *= 1024; } else if (*arg_p == 'm' || *arg_p == 'M') { val *= 1024 * 1024; } else if (*arg_p == 'g' || *arg_p == 'G') { val *= 1024 * 1024 * 1024; } *(unsigned long *)var = val; } break; case ARGV_BOOL_INT: /* if no close argument, set to true */ if (arg == NULL) { *(int *)var = ARGV_TRUE; } else if (*(char *)arg == 't' || *(char *)arg == 'T' || *(char *)arg == 'y' || *(char *)arg == 'Y' || *(char *)arg == '1') { *(int *)var = ARGV_TRUE; } else { *(int *)var = ARGV_FALSE; } break; case ARGV_BOOL_INT_NEG: /* if no close argument, set to false */ if (arg == NULL) { *(int *)var = ARGV_FALSE; } else if (*(char *)arg == 't' || *(char *)arg == 'T' || *(char *)arg == 'y' || *(char *)arg == 'Y' || *(char *)arg == '1') { *(int *)var = ARGV_TRUE; } else { *(int *)var = ARGV_FALSE; } break; case ARGV_BOOL_INT_ARG: if (*(char *)arg == 't' || *(char *)arg == 'T' || *(char *)arg == 'y' || *(char *)arg == 'Y' || *(char *)arg == '1') { *(int *)var = ARGV_TRUE; } else { *(int *)var = ARGV_FALSE; } break; } return NOERROR; } /* * static int value_to_string * * DESCRIPTION: * * Translate value from variable depending on its type intoits string * represetnation in buffer. * * RETURNS: * * Number of characters added to the buffer. * * ARGUMENTS: * * var - Variable pointer. * * type - Type of variable. * * buf - User buffer to convert into. * * buf_size - Size of the user buffer. */ static int value_to_string(const ARGV_PNT var, const unsigned int type, char *buf, const int buf_size) { int len = 0; /* * NOTE: without a snprintf, we have to hope that buf_size > integer * and the string repesentations of the numbers. */ /* translate depending on type */ switch (ARGV_TYPE(type)) { case ARGV_BOOL: case ARGV_BOOL_NEG: case ARGV_BOOL_ARG: if (*(char *)var) { strncpy(buf, "true (! 0)", buf_size); } else { strncpy(buf, "false (0)", buf_size); } buf[buf_size - 1] = '\0'; len = strlen(buf); break; case ARGV_CHAR: len = expand_buf((char *)var, 1, buf, buf_size); break; case ARGV_CHAR_P: if (*(char **)var == NULL) { strncpy(buf, "(null)", buf_size); buf[buf_size - 1] = '\0'; len = strlen(buf); } else { len = expand_buf(*(char **)var, -1, buf, buf_size); } break; case ARGV_SHORT: (void)loc_snprintf(buf, buf_size, "%d", *(short *)var); len = strlen(buf); break; case ARGV_U_SHORT: (void)loc_snprintf(buf, buf_size, "%d", *(unsigned short *)var); len = strlen(buf); break; case ARGV_INT: (void)loc_snprintf(buf, buf_size, "%d", *(int *)var); len = strlen(buf); break; case ARGV_U_INT: (void)loc_snprintf(buf, buf_size, "%u", *(unsigned int *)var); len = strlen(buf); break; case ARGV_LONG: (void)loc_snprintf(buf, buf_size, "%ld", *(long *)var); len = strlen(buf); break; case ARGV_U_LONG: (void)loc_snprintf(buf, buf_size, "%lu", *(unsigned long *)var); len = strlen(buf); break; case ARGV_FLOAT: (void)loc_snprintf(buf, buf_size, "%f", *(float *)var); len = strlen(buf); break; case ARGV_DOUBLE: (void)loc_snprintf(buf, buf_size, "%f", *(double *)var); len = strlen(buf); break; /* this should be a routine */ case ARGV_BIN: { int bit_c, bit, first_b = ARGV_FALSE; char binary[2 + 128 + 1], *bin_bounds_p, *bin_p = binary; if (*(int *)var == 0) { strncpy(buf, "0", buf_size); } else { bin_bounds_p = binary + sizeof(binary); /* initially write binary number into tmp buffer, then copy into out */ *bin_p++ = '0'; *bin_p++ = 'b'; for (bit_c = sizeof(int) * BITS_IN_BYTE - 1; bit_c >= 0; bit_c--) { bit = *(int *)var & (1 << bit_c); if (bit == 0) { if (first_b) { *bin_p++ = '0'; } } else { *bin_p++ = '1'; first_b = ARGV_TRUE; } } /* add on the decimal equivalent */ (void)loc_snprintf(bin_p, bin_bounds_p - bin_p, " (%d)", *(int *)var); /* find the \0 at end */ for (; *bin_p != '\0'; bin_p++) { } /* now we copy from the binary buffer to the output */ strncpy(buf, binary, buf_size); } buf[buf_size - 1] = '\0'; len = strlen(buf); } break; case ARGV_OCT: if (*(int *)var == 0) { (void)strncpy(buf, "0", buf_size); buf[buf_size - 1] = '\0'; } else { (void)loc_snprintf(buf, buf_size, "%#o (%d)", *(int *)var, *(int *)var); } len = strlen(buf); break; case ARGV_HEX: if (*(int *)var == 0) { (void)strcpy(buf, "0"); } else { (void)loc_snprintf(buf, buf_size, "%#x (%d)", *(int *)var, *(int *)var); } len = strlen(buf); break; case ARGV_INCR: (void)loc_snprintf(buf, buf_size, "%d", *(int *)var); len = strlen(buf); break; case ARGV_SIZE: { long morf, val = *(long *)var; if (val == 0) { (void)strcpy(buf, "0"); } else if (val % (1024 * 1024 * 1024) == 0) { morf = val / (1024 * 1024 * 1024); (void)loc_snprintf(buf, buf_size, "%ldg (%ld)", morf, val); } else if (val % (1024 * 1024) == 0) { morf = val / (1024 * 1024); (void)loc_snprintf(buf, buf_size, "%ldm (%ld)", morf, val); } else if (val % 1024 == 0) { morf = val / 1024; (void)loc_snprintf(buf, buf_size, "%ldk (%ld)", morf, val); } else { (void)loc_snprintf(buf, buf_size, "%ld", val); } len = strlen(buf); } break; case ARGV_U_SIZE: { unsigned long morf, val = *(unsigned long *)var; if (val == 0) { (void)strcpy(buf, "0"); } else if (val % (1024 * 1024 * 1024) == 0) { morf = val / (1024 * 1024 * 1024); (void)loc_snprintf(buf, buf_size, "%ldg (%ld)", morf, val); } else if (val % (1024 * 1024) == 0) { morf = val / (1024 * 1024); (void)loc_snprintf(buf, buf_size, "%ldm (%ld)", morf, val); } else if (val % 1024 == 0) { morf = val / 1024; (void)loc_snprintf(buf, buf_size, "%ldk (%ld)", morf, val); } else { (void)loc_snprintf(buf, buf_size, "%ld", val); } len = strlen(buf); } break; case ARGV_BOOL_INT: case ARGV_BOOL_INT_NEG: case ARGV_BOOL_INT_ARG: if (*(int *)var) { strncpy(buf, "true (! 0)", buf_size); } else { strncpy(buf, "false (0)", buf_size); } buf[buf_size - 1] = '\0'; len = strlen(buf); break; default: strncpy(buf, "(unknown)", buf_size); buf[buf_size - 1] = '\0'; len = strlen(buf); break; } return len; } /* * static void display_variables * * DESCRIPTION: * * Display all of the variable values from our array. * * RETURNS: * * None. * * ARGUMENTS: * * args - Array of argv_t structures whose variables we are * displaying. */ static void display_variables(const argv_t *args) { const argv_t *arg_p; argv_type_t *type_p; char buf[256]; int len, col_c; unsigned int val_type; /* run through the argument structure */ for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { val_type = ARGV_TYPE(arg_p->ar_type); /* skip or specifiers */ if (arg_p->ar_short_arg == ARGV_OR || arg_p->ar_short_arg == ARGV_XOR) { continue; } col_c = 0; if (arg_p->ar_short_arg == '\0') { if (arg_p->ar_long_arg != NULL) { len = COMMENT_COLUMN - col_c - (LONG_PREFIX_LENGTH + 1); if (arg_p->ar_short_arg != '\0') { (void)fprintf(argv_error_stream, "%s", LONG_LABEL); col_c += LONG_LABEL_LENGTH; len -= LONG_LABEL_LENGTH; } (void)fprintf(argv_error_stream, "%s%-.*s", LONG_PREFIX, len, arg_p->ar_long_arg); col_c += LONG_PREFIX_LENGTH + MIN(len, (int)strlen(arg_p->ar_long_arg)); } } else if (arg_p->ar_short_arg == ARGV_MAND) { display_arg(argv_error_stream, arg_p, COMMENT_COLUMN, &col_c); } else { /* ARGV_MAYBE handled here */ display_option(argv_error_stream, arg_p, &col_c); } /* put the type in the correct column */ if (col_c < LONG_COLUMN) { (void)fprintf(argv_error_stream, "%*.*s", LONG_COLUMN - col_c, LONG_COLUMN - col_c, ""); col_c = LONG_COLUMN; } /* find the type */ type_p = NULL; for (type_p = argv_types; type_p->at_value != 0; type_p++) { if (type_p->at_value == ARGV_TYPE(arg_p->ar_type)) { int tlen; len = COMMENT_COLUMN - col_c - 1; tlen = strlen(type_p->at_name); (void)fprintf(argv_error_stream, " %-.*s", len, type_p->at_name); col_c += MIN(len, tlen); if (arg_p->ar_type & ARGV_FLAG_ARRAY) { (void)fprintf(argv_error_stream, "%s", ARRAY_LABEL); col_c += sizeof(ARRAY_LABEL) - 1; } break; } } if (col_c < COMMENT_COLUMN) { (void)fprintf(argv_error_stream, "%*.*s", COMMENT_COLUMN - col_c, COMMENT_COLUMN - col_c, ""); col_c = COMMENT_COLUMN; } if (arg_p->ar_type & ARGV_FLAG_ARRAY) { argv_array_t *arr_p; int entry_c, size = 0; /* find the type and the size for array */ if (type_p == NULL) { (void)fprintf(argv_error_stream, "%s: illegal variable type %d\n", __FILE__, val_type); continue; } size = type_p->at_size; arr_p = (argv_array_t *)arg_p->ar_variable; if (arr_p->aa_entry_n == 0) { (void)fprintf(argv_error_stream, "no entries"); } else { for (entry_c = 0; entry_c < arr_p->aa_entry_n; entry_c++) { ARGV_PNT var; if (entry_c > 0) { (void)fputc(',', argv_error_stream); } var = (char *)(arr_p->aa_entries) + entry_c * size; len = value_to_string(var, val_type, buf, sizeof(buf)); (void)fwrite(buf, sizeof(char), len, argv_error_stream); } } } else { len = value_to_string(arg_p->ar_variable, val_type, buf, sizeof(buf)); (void)fwrite(buf, sizeof(char), len, argv_error_stream); } (void)fputc('\n', argv_error_stream); } } /************************** checking used arguments **************************/ /* * static int check_or * * DESCRIPTION: * * Check out if an argument has an ARGV_OR attached to it and both * variables have not been set. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * args - Array of argv_t structures that we are checking. * * which_p - Pointer to the specific argument that we are checking for * the ARGV_OR. */ static int check_or(const argv_t *args, const argv_t *which_p) { const argv_t *arg_p, *match_p = NULL; /* check ORs below */ for (arg_p = which_p - 2; arg_p >= args; arg_p -= 2) { if ((arg_p + 1)->ar_short_arg != ARGV_OR && (arg_p + 1)->ar_short_arg != ARGV_XOR) { break; } if (arg_p->ar_type & ARGV_FLAG_USED) { match_p = arg_p; break; } } /* check ORs above */ if (match_p == NULL) { /* NOTE: we assume that which_p is not pointing now to ARGV_LAST */ for (arg_p = which_p + 2; arg_p->ar_short_arg != ARGV_LAST && (arg_p - 1)->ar_short_arg != ARGV_LAST; arg_p += 2) { if ((arg_p - 1)->ar_short_arg != ARGV_OR && (arg_p - 1)->ar_short_arg != ARGV_XOR) { break; } if (arg_p->ar_type & ARGV_FLAG_USED) { match_p = arg_p; break; } } } /* did we not find a problem? */ if (match_p == NULL) { return NOERROR; } if (argv_error_stream == NULL) { return ERROR; } (void)fprintf(argv_error_stream, "%s: %s, specify only one of the following:\n", argv_program, USAGE_ERROR_NAME); /* little hack to print the one that matched and the one we were checking */ for (;;) { if (match_p->ar_long_arg == NULL) { (void)fprintf(argv_error_stream, "%*.*s%s%c\n", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "", SHORT_PREFIX, match_p->ar_short_arg); } else { (void)fprintf(argv_error_stream, "%*.*s%s%c (%s%s)\n", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "", SHORT_PREFIX, match_p->ar_short_arg, LONG_PREFIX, match_p->ar_long_arg); } if (match_p == which_p) { break; } match_p = which_p; } return ERROR; } /* * static int check_xor * * DESCRIPTION: * * Check out if an argument has an ARGV_XOR attached to it and that at * least one but not both variables have been set. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * args - Array of argv_t structures that we are checking. * * which_p - Pointer to the specific argument that we are checking for * the ARGV_XOR. */ static int check_xor(const argv_t *args) { const argv_t *start_p = NULL, *arg_p; /* run through the list of arguments */ for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { /* only check the XORs */ if (arg_p->ar_short_arg != ARGV_XOR) { continue; } start_p = arg_p; /* * NOTE: we are guaranteed that we are on a XOR so there is * something below and above... */ if ((arg_p - 1)->ar_type & ARGV_FLAG_USED) { start_p = NULL; } /* run through all XORs */ for (;;) { arg_p++; if (arg_p->ar_type & ARGV_FLAG_USED) { start_p = NULL; } if ((arg_p + 1)->ar_short_arg != ARGV_XOR) { break; } arg_p++; } /* were none of the xor's filled? */ if (start_p != NULL) { break; } } /* did we not find a problem? */ if (start_p == NULL) { return NOERROR; } /* arg_p points to the first XOR which failed */ if (argv_error_stream == NULL) { return ERROR; } (void)fprintf(argv_error_stream, "%s: %s, must specify one of:\n", argv_program, USAGE_ERROR_NAME); for (arg_p = start_p;; arg_p += 2) { /* * NOTE: we are guaranteed that we are on a XOR so there is * something below and above... */ (void)fprintf(argv_error_stream, "%*.*s%s%c", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "", SHORT_PREFIX, (arg_p - 1)->ar_short_arg); if ((arg_p - 1)->ar_long_arg != NULL) { (void)fprintf(argv_error_stream, " (%s%s)", LONG_PREFIX, (arg_p - 1)->ar_long_arg); } (void)fprintf(argv_error_stream, "\n"); if (arg_p->ar_short_arg != ARGV_XOR) { break; } } return ERROR; } /* * static int check_mand * * DESCRIPTION: * * Verify that all of the mandatory arguments in our array have been * specified. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * args - Array of argv_t structures that we are checking. */ static int check_mand(const argv_t *args) { const argv_t *arg_p; int mand_c = 0, flag_c = 0; /* see if there are any mandatory args left */ for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { if (arg_p->ar_short_arg == ARGV_MAND && (! (arg_p->ar_type & ARGV_FLAG_USED))) { mand_c++; } if (arg_p->ar_type & ARGV_FLAG_MAND && (! (arg_p->ar_type & ARGV_FLAG_USED))) { flag_c++; if (argv_error_stream != NULL) { if (flag_c == 1) { (void)fprintf(argv_error_stream, "%s: %s, these mandatory flags must be specified:\n", argv_program, USAGE_ERROR_NAME); } (void)fprintf(argv_error_stream, "%*.*s%s%c", (int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "", SHORT_PREFIX, arg_p->ar_short_arg); if (arg_p->ar_long_arg != NULL) { (void)fprintf(argv_error_stream, " (%s%s)", LONG_PREFIX, arg_p->ar_long_arg); } (void)fprintf(argv_error_stream, "\n"); } } } if (mand_c > 0 && argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, %d more mandatory argument%s must be specified\n", argv_program, USAGE_ERROR_NAME, mand_c, (mand_c == 1 ? "" : "s")); } if (mand_c > 0 || flag_c > 0) { return ERROR; } else { return NOERROR; } } /* * static int check_opt * * DESCRIPTION: * * Check for any missing argument options. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * queue_head - Head of the option queue. * * queue_tail - Tail of the option queue. */ static int check_opt(const int queue_head, const int queue_tail) { int queue_c; queue_c = queue_head - queue_tail; if (queue_c > 0) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, %d more option-argument%s must be specified\n", argv_program, USAGE_ERROR_NAME, queue_c, (queue_c == 1 ? "" : "s")); } return ERROR; } return NOERROR; } /**************************** argument processing ****************************/ /* * static void file_args * * DESCRIPTION: * * Read in arguments from a file and process them like they were * specified on the command line. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * path -> File of the arguments we are reading in. * * grid -> Array of argv_t structures we are using. * * queue_list <-> Our option queue for storing options to arguments. * * queue_head_p <-> Pointer to integer which will be updated with the * head position in our option queue. * * queue_tail_p <-> Pointer to integer which will be updated with the * tail position in our option queue. * * okay_bp <- Pointer to an integer which is set with 0 if the * arguments specified in the env variable are somehow invalid. */ static void file_args(const char *path, argv_t *grid, argv_t **queue_list, int *queue_head_p, int *queue_tail_p, int *okay_bp) { char **argv, **argv_p; int arg_c, max; FILE *infile; char line[FILE_LINE_SIZE], *line_p; /* open the input file */ if (strcmp(path, "-") == 0) { infile = stdin; } else { infile = fopen(path, "r"); } if (infile == NULL) { *okay_bp = ARGV_FALSE; if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: could not load command-line arguments from: %s\n", argv_program, path); } if (argv_interactive) { (void)exit(argv_error_code); } return; } /* get an array of char * */ arg_c = 0; max = ARRAY_INCR; argv = malloc(sizeof(char *) * max); if (argv == NULL) { *okay_bp = ARGV_FALSE; if (infile != stdin) { (void)fclose(infile); } if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: memory error during argument processing\n", argv_program); } if (argv_interactive) { (void)exit(argv_error_code); } return; } argv_p = argv; /* read in the file lines */ while (fgets(line, sizeof(line), infile) != NULL) { /* punch the \n at end of line */ for (line_p = line; *line_p != '\n' && *line_p != '\0'; line_p++) { } *line_p = '\0'; /* skip blank lines */ if (line_p == line) { continue; } *argv_p = string_copy(line); if (*argv_p == NULL) { *okay_bp = ARGV_FALSE; return; } argv_p++; arg_c++; /* do we need to grow the array of pointers? */ if (arg_c == max) { max += ARRAY_INCR; argv = realloc(argv, sizeof(char *) * max); if (argv == NULL) { *okay_bp = ARGV_FALSE; if (infile != stdin) { (void)fclose(infile); } if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: memory error during argument processing\n", argv_program); } if (argv_interactive) { (void)exit(argv_error_code); } return; } argv_p = argv + arg_c; } } /* now do the list */ do_list(grid, arg_c, argv, queue_list, queue_head_p, queue_tail_p, okay_bp); /* now free up the list */ for (argv_p = argv; argv_p < argv + arg_c; argv_p++) { free(*argv_p); } free(argv); if (infile != stdin) { (void)fclose(infile); } } /* * static void do_arg * * DESCRIPTION: * * Process an argument in MATCH_P which looking at GRID. sets okay_p * to FALSE if the argument was not okay. * * RETURNS: * * None. * * ARGUMENTS: * * grid -> Our array of argv_t structures. * * match_p -> Entry in our argv_t structure array that matches the * specified argument. * * close_p -> Pointer to the value closely associated (with an '=') * with this option or NULL if none. * * queue_list <-> Our option queue for storing options to arguments. * * queue_head_p <-> Pointer to integer which will be updated with the * head position in our option queue. * * okay_bp <- Pointer to an integer which is set with 0 if the * arguments specified in the env variable are somehow invalid. */ static void do_arg(argv_t *grid, argv_t *match_p, const char *close_p, argv_t **queue_list, int *queue_head_p, int *okay_bp) { if (! argv_multi_accept_b) { /* * have we used this one before? * NOTE: should this be a warning or a non-error altogether? */ if (match_p->ar_type & ARGV_FLAG_USED && (! (match_p->ar_type & ARGV_FLAG_ARRAY)) && ARGV_TYPE(match_p->ar_type) != ARGV_INCR) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, you've already specified the '%c' argument\n", argv_program, USAGE_ERROR_NAME, match_p->ar_short_arg); } *okay_bp = ARGV_FALSE; } } /* we used this argument */ match_p->ar_type |= ARGV_FLAG_USED; /* check arguments that must be OR'd */ if (check_or(grid, match_p) != NOERROR) { /* * don't return here else we might generate an XOR error * because the argument wasn't specified */ *okay_bp = ARGV_FALSE; } /* * If we have a close argument, pass to translate. If it is a * boolean or increment variable, then pass in a value of null * else queue it for needing a value argument. */ if (argv_close_enable_b && close_p != NULL) { if (string_to_value(close_p, match_p->ar_variable, match_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } } else if (! HAS_ARG(match_p->ar_type)) { if (string_to_value(NULL, match_p->ar_variable, match_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } } else if (argv_close_enable_b && close_p != NULL) { if (string_to_value(close_p, match_p->ar_variable, match_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } } else { queue_list[*queue_head_p] = match_p; (*queue_head_p)++; } } /* * static int is_number * * DESCRIPTION: * * Examine an argument string to see if it really is a negative number * being passed into a previously specified argument. * * Thanks much to Nick Kisseberth for pointing out this oversight. * * RETURNS: * * 1 if a number otherwise 0. * * ARGUMENTS: * * str - String which may be a number. */ static int is_number(const char *str) { const char *str_p; /* empty strings are not numbers */ if (str[0] == '\0') { return 0; } /* * All chars in the string should be number chars for it to be a * number. Yes this will return yes if the argument is "00-" but * we'll chalk this up to user error. */ for (str_p = str; *str_p != '\0'; str_p++) { if (strchr(NUMBER_ARG_CHARS, *str_p) == NULL) { return 0; } } return 1; } /* * static void do_list * * DESCRIPTION: * * Process a list of arguments with our array of argv_t structures * * RETURNS: * * None. * * ARGUMENTS: * * grid - Our array of argv_t structures. * * arg_c - Number of arguments in argv. * * argv - User argument array of character pointers. * * queue_list <-> Our option queue for storing options to arguments. * * queue_head_p <-> Pointer to integer which will be updated with the * head position in our option queue. * * queue_tail_p <-> Pointer to integer which will be updated with the * tail position in our option queue. * * okay_bp - Pointer to an integer which is set with 0 if the * arguments specified in the env variable are somehow invalid. */ static void do_list(argv_t *grid, const int arg_c, char **argv, argv_t **queue_list, int *queue_head_p, int *queue_tail_p, int *okay_bp) { argv_t *grid_p, *match_p; int len, char_c, unwant_c = 0; int last_arg_b = ARGV_FALSE; char *close_p = NULL, **arg_p; /* run throught rest of arguments */ for (arg_p = argv; arg_p < argv + arg_c; arg_p++) { /* have we reached the LAST_ARG marker? */ if (strcmp(LAST_ARG, *arg_p) == 0) { if (last_arg_b) { if (argv_last_toggle_b) { last_arg_b = ARGV_FALSE; continue; } } else { last_arg_b = ARGV_TRUE; continue; } } /* are we processing a long option? */ if ((! last_arg_b) && strncmp(LONG_PREFIX, *arg_p, LONG_PREFIX_LENGTH) == 0) { /* * check for close equals marker * * NOTE: duplicated in the short prefix section below. In here otherwise * we process normal args with x=5 instead of just -x=5. */ if (argv_close_enable_b) { close_p = strchr(*arg_p, ARG_EQUALS); /* if we found the special char then punch the null and set pointer */ if (close_p != NULL) { *close_p = '\0'; close_p++; } } /* get length of rest of argument */ len = strlen(*arg_p) - LONG_PREFIX_LENGTH; /* we need more than the prefix */ if (len <= 0) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, empty long-option prefix '%s'\n", argv_program, USAGE_ERROR_NAME, *arg_p); } *okay_bp = ARGV_FALSE; continue; } match_p = NULL; /* run though long options looking for a match */ for (grid_p = grid; grid_p->ar_short_arg != ARGV_LAST; grid_p++) { if (grid_p->ar_long_arg == NULL) { continue; } if (strncmp(*arg_p + LONG_PREFIX_LENGTH, grid_p->ar_long_arg, len) == 0) { if (match_p != NULL) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, '%s' might be '%s' or '%s'\n", argv_program, USAGE_ERROR_NAME, *arg_p, grid_p->ar_long_arg, match_p->ar_long_arg); } *okay_bp = ARGV_FALSE; break; } /* record a possible match */ match_p = grid_p; /* don't break, need to see if another one matches */ } } /* if we found a match but quit then we must have found two matches */ if (match_p != NULL && grid_p->ar_short_arg != ARGV_LAST) { continue; } if (match_p != NULL) { (void)do_arg(grid, match_p, close_p, queue_list, queue_head_p, okay_bp); continue; } /* we did not find long-option match */ /* check for special file value */ if (strncmp(FILE_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_close_enable_b && close_p != NULL) { /* open the file and read in the args */ file_args(close_p, grid, queue_list, queue_head_p, queue_tail_p, okay_bp); } else { /* HACK: we enqueue null for the file argument */ queue_list[*queue_head_p] = NULL; (*queue_head_p)++; } continue; } /* check for special usage value */ if (strncmp(USAGE_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0 || strncmp(HELP_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { do_usage(grid, argv_usage_type); (void)exit(0); } continue; } /* check for special short-usage value */ if (strncmp(USAGE_SHORT_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { do_usage(grid, ARGV_USAGE_SHORT); (void)exit(0); } continue; } /* check for special long-usage value */ if (strncmp(USAGE_LONG_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { do_usage(grid, ARGV_USAGE_LONG); (void)exit(0); } continue; } /* check for special long-usage value */ if (strncmp(USAGE_ALL_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { do_usage(grid, ARGV_USAGE_ALL); (void)exit(0); } continue; } /* check for special help value */ if (strncmp(HELP_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { if (argv_error_stream != NULL) { if (argv_help_string == NULL) { (void)fprintf(argv_error_stream, "%s: I'm sorry, no help is available.\n", argv_program); } else { (void)fprintf(argv_error_stream, "%s: %s\n", argv_program, argv_help_string); } } (void)exit(0); } continue; } /* check for special version value */ if (strncmp(VERSION_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { if (argv_error_stream != NULL) { if (argv_version_string == NULL) { (void)fprintf(argv_error_stream, "%s: no version information is available.\n", argv_program); } else { (void)fprintf(argv_error_stream, "%s: %s%s\n", argv_program, VERSION_LABEL, argv_version_string); } } (void)exit(0); } continue; } /* check for display arguments value */ if (strncmp(DISPLAY_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { if (argv_error_stream != NULL) { display_variables(grid); } (void)exit(0); } continue; } if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, unknown long option '%s'.\n", argv_program, USAGE_ERROR_NAME, *arg_p); } *okay_bp = ARGV_FALSE; continue; } /* are we processing a short option? */ if ((! last_arg_b) && strncmp(SHORT_PREFIX, *arg_p, SHORT_PREFIX_LENGTH) == 0) { /* * check for close equals marker * * NOTE: duplicated in the long prefix section above. In here otherwise * we process normal args with x=5 instead of just -x=5. */ if (argv_close_enable_b) { close_p = strchr(*arg_p, ARG_EQUALS); /* if we found the special char then punch the null and set pointer */ if (close_p != NULL) { *close_p = '\0'; close_p++; } } /* get length of rest of argument */ len = strlen(*arg_p) - SHORT_PREFIX_LENGTH; /* we need more than the prefix */ if (len <= 0) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, empty short-option prefix '%s'\n", argv_program, USAGE_ERROR_NAME, *arg_p); } *okay_bp = ARGV_FALSE; continue; } /* run through the chars in this option */ for (char_c = 0; char_c < len; char_c++) { /* run through the arg list looking for a match */ for (match_p = grid; match_p->ar_short_arg != ARGV_LAST; match_p++) { if (match_p->ar_short_arg == (*arg_p)[SHORT_PREFIX_LENGTH + char_c]) { break; } } /* did we not find argument? */ if (match_p->ar_short_arg == ARGV_LAST) { /* check for special usage value */ if ((*arg_p)[SHORT_PREFIX_LENGTH + char_c] == USAGE_CHAR_ARG) { if (argv_interactive) { do_usage(grid, argv_usage_type); (void)exit(0); } continue; } /* * allow values with negative signs if we are at the start * of an argument list, and if the argument is a number, and * we already have a variable looking for a value. Thanks * to Nick Kisseberth for pointing out this oversight. */ if (char_c == 0 && is_number(*arg_p) && *queue_head_p > *queue_tail_p) { match_p = queue_list[*queue_tail_p]; /* * NOTE: we don't advance the queue tail here unless we * find out that we can use it below */ switch (ARGV_TYPE(match_p->ar_type)) { case ARGV_SHORT: case ARGV_INT: case ARGV_LONG: case ARGV_FLOAT: case ARGV_DOUBLE: string_to_value(*arg_p, match_p->ar_variable, match_p->ar_type); char_c = len; /* we actually used it so we advance the queue tail position */ (*queue_tail_p)++; continue; break; } } /* create an error string */ if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, unknown short option '%s%c'.\n", argv_program, USAGE_ERROR_NAME, SHORT_PREFIX, (*arg_p)[SHORT_PREFIX_LENGTH + char_c]); } *okay_bp = ARGV_FALSE; continue; } do_arg(grid, match_p, close_p, queue_list, queue_head_p, okay_bp); } continue; } /* could this be a value? */ if (grid->ar_short_arg != ARGV_LAST && *queue_head_p > *queue_tail_p) { /* pull the variable waiting for a value from the queue */ match_p = queue_list[*queue_tail_p]; (*queue_tail_p)++; /* HACK: is this the file argument */ if (match_p == NULL) { file_args(*arg_p, grid, queue_list, queue_head_p, queue_tail_p, okay_bp); } else { if (string_to_value(*arg_p, match_p->ar_variable, match_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } } continue; } /* process mandatory args if some left to process */ for (grid_p = grid; grid_p->ar_short_arg != ARGV_LAST; grid_p++) { if (grid_p->ar_short_arg == ARGV_MAND && ((! (grid_p->ar_type & ARGV_FLAG_USED)) || grid_p->ar_type & ARGV_FLAG_ARRAY)) { break; } } if (grid_p->ar_short_arg != ARGV_LAST) { /* absorb another mand. arg */ if (string_to_value(*arg_p, grid_p->ar_variable, grid_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } grid_p->ar_type |= ARGV_FLAG_USED; continue; } /* process maybe args if some left to process */ for (grid_p = grid; grid_p->ar_short_arg != ARGV_LAST; grid_p++) { if (grid_p->ar_short_arg == ARGV_MAYBE && ((! (grid_p->ar_type & ARGV_FLAG_USED)) || grid_p->ar_type & ARGV_FLAG_ARRAY)) { break; } } if (grid_p->ar_short_arg != ARGV_LAST) { /* absorb another maybe arg */ if (string_to_value(*arg_p, grid_p->ar_variable, grid_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } grid_p->ar_type |= ARGV_FLAG_USED; continue; } /* default is an error */ unwant_c++; *okay_bp = ARGV_FALSE; } if (unwant_c > 0 && argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, %d unwanted additional argument%s\n", argv_program, USAGE_ERROR_NAME, unwant_c, (unwant_c == 1 ? "" : "s")); } } /****************************** env processing *******************************/ /* * static int do_env_args * * DESCRIPTION: * * Handle the args from the environmentatl variable. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * args - Array of argv_t structures we are using. * * queue_list <-> Our option queue for storing options to arguments. * * queue_head_p <-> Pointer to integer which will be updated with the * head position in our option queue. * * queue_tail_p <-> Pointer to integer which will be updated with the * tail position in our option queue. * * okay_bp - Pointer to an integer which is set with 0 if the * arguments specified in the env variable are somehow invalid. */ static int do_env_args(argv_t *args, argv_t **queue_list, int *queue_head_p, int *queue_tail_p, int *okay_bp) { int env_c, env_n; char **vect_p, env_name[1024], *environ_p; /* create the env variable */ (void)loc_snprintf(env_name, sizeof(env_name), ENVIRON_FORMAT, argv_program); /* NOTE: by default the env name is all uppercase */ for (environ_p = env_name; *environ_p != '\0'; environ_p++) { if (islower(*environ_p)) { *environ_p = toupper(*environ_p); } } environ_p = getenv(env_name); if (environ_p == NULL) { return NOERROR; } /* break the list into tokens and do the list */ environ_p = string_copy(environ_p); if (environ_p == NULL) { return ERROR; } vect_p = vectorize(environ_p, " \t", &env_n); if (vect_p != NULL) { do_list(args, env_n, vect_p, queue_list, queue_head_p, queue_tail_p, okay_bp); /* free token list */ for (env_c = 0; env_c < env_n; env_c++) { free(vect_p[env_c]); } free(vect_p); } free(environ_p); return NOERROR; } /* * static int process_env * * DESCRIPTION: * * Process the global env variables. * * RETURNS: * * Success - 0 * * Faulure - -1 * * ARGUMENTS: * * None. */ static int process_env(void) { static int done_b = ARGV_FALSE; char *env_val, *tok_p, *env_p; int len; /* make sure we only do this once */ if (done_b) { return NOERROR; } done_b = ARGV_TRUE; /* get the argv information */ env_val = getenv(GLOBAL_NAME); if (env_val == NULL) { return NOERROR; } /* save a copy of it */ env_val = string_copy(env_val); if (env_val == NULL) { return ERROR; } env_p = env_val; for (;;) { tok_p = strsep(&env_p, " \t,:"); if (tok_p == NULL) { break; } /* skip any empty tokens */ if (*tok_p == '\0') { continue; } len = strlen(GLOBAL_CLOSE); if (strncmp(GLOBAL_CLOSE, tok_p, len) == 0) { tok_p += len; if (strcmp(tok_p, "disable") == 0 || strcmp(tok_p, "off") == 0 || strcmp(tok_p, "no") == 0 || strcmp(tok_p, "0") == 0) { argv_close_enable_b = 0; } else if (strcmp(tok_p, "enable") == 0 || strcmp(tok_p, "on") == 0 || strcmp(tok_p, "yes") == 0 || strcmp(tok_p, "1") == 0) { argv_close_enable_b = 1; } else { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: illegal env variable '%s' '%s' argument '%s'\n", __FILE__, GLOBAL_NAME, GLOBAL_CLOSE, tok_p); } } continue; } len = strlen(GLOBAL_LASTTOG); if (strncmp(GLOBAL_LASTTOG, tok_p, len) == 0) { tok_p += len; if (strcmp(tok_p, "disable") == 0 || strcmp(tok_p, "off") == 0 || strcmp(tok_p, "no") == 0 || strcmp(tok_p, "0") == 0) { argv_last_toggle_b = 0; } else if (strcmp(tok_p, "enable") == 0 || strcmp(tok_p, "on") == 0 || strcmp(tok_p, "yes") == 0 || strcmp(tok_p, "1") == 0) { argv_last_toggle_b = 1; } else { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: illegal env variable '%s' '%s' argument '%s'\n", __FILE__, GLOBAL_NAME, GLOBAL_LASTTOG, tok_p); } } continue; } len = strlen(GLOBAL_ENV); if (strncmp(GLOBAL_ENV, tok_p, len) == 0) { tok_p += len; if (strcmp(tok_p, "none") == 0) { argv_process_env_b = 0; argv_env_after_b = 0; } else if (strcmp(tok_p, "before") == 0) { argv_process_env_b = 1; argv_env_after_b = 0; } else if (strcmp(tok_p, "after") == 0) { argv_process_env_b = 1; argv_env_after_b = 1; } else { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: illegal env variable '%s' '%s' argument '%s'\n", __FILE__, GLOBAL_NAME, GLOBAL_ENV, tok_p); } } continue; } len = strlen(GLOBAL_ERROR); if (strncmp(GLOBAL_ERROR, tok_p, len) == 0) { tok_p += len; if (strcmp(tok_p, "none") == 0) { argv_error_type = ARGV_USAGE_NONE; } else if (strcmp(tok_p, "see") == 0) { argv_error_type = ARGV_USAGE_SEE; } else if (strcmp(tok_p, "short") == 0) { argv_error_type = ARGV_USAGE_SHORT; } else if (strcmp(tok_p, "shortrem") == 0) { argv_error_type = ARGV_USAGE_SHORT_REM; } else if (strcmp(tok_p, "long") == 0) { argv_error_type = ARGV_USAGE_LONG; } else if (strcmp(tok_p, "all") == 0) { argv_error_type = ARGV_USAGE_ALL; } else { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: illegal env variable '%s' '%s' argument '%s'\n", __FILE__, GLOBAL_NAME, GLOBAL_ERROR, tok_p); } } continue; } len = strlen(GLOBAL_MULTI); if (strncmp(GLOBAL_MULTI, tok_p, len) == 0) { tok_p += len; if (strcmp(tok_p, "reject") == 0) { argv_multi_accept_b = 0; } else if (strcmp(tok_p, "accept") == 0) { argv_multi_accept_b = 1; } else { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: illegal env variable '%s' '%s' argument '%s'\n", __FILE__, GLOBAL_NAME, GLOBAL_MULTI, tok_p); } } continue; } len = strlen(GLOBAL_USAGE); if (strncmp(GLOBAL_USAGE, tok_p, len) == 0) { tok_p += len; if (strcmp(tok_p, "short") == 0) { argv_usage_type = ARGV_USAGE_SHORT; } else if (strcmp(tok_p, "shortrem") == 0) { argv_usage_type = ARGV_USAGE_SHORT_REM; } else if (strcmp(tok_p, "long") == 0) { argv_usage_type = ARGV_USAGE_LONG; } else if (strcmp(tok_p, "all") == 0) { argv_usage_type = ARGV_USAGE_ALL; } else { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: illegal env variable '%s' '%s' argument '%s'\n", __FILE__, GLOBAL_NAME, GLOBAL_USAGE, tok_p); } } continue; } if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: illegal env variable '%s' setting '%s'\n", __FILE__, GLOBAL_NAME, tok_p); } } free(env_val); return NOERROR; } /***************************** exported routines *****************************/ /* * int argv_process_no_env * * DESCRIPTION: * * Process the user arguments with an argv_t structure array. Like * argv_process_args but without the processing of the argv * environmental variables. * * RETURNS: * * Success - 0 * * Failure - -1 * * ARGUMENTS: * * args - Array of argv_t structures. * * arg_n - Number of arguments in the argv array. * * argv - Array of character pointers terminated by 0L. */ int argv_process_no_env(argv_t *args, const int arg_n, char **argv) { int entry_c; const char *prog_p; int okay_b = ARGV_TRUE; argv_t *arg_p; argv_t **queue_list = NULL; int queue_head = 0, queue_tail = 0; if (args == NULL) { args = empty; } if (arg_n < 0) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, argc argument to argv_process is %d\n", __FILE__, INTERNAL_ERROR_NAME, arg_n); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } if (argv == NULL) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, argv argument to argv_process is NULL\n", __FILE__, INTERNAL_ERROR_NAME); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } /* set global variables */ argv_argv = argv; argv_argc = arg_n; /* build the program name from the argv[0] path */ { const char *tmp_p; prog_p = *argv; for (tmp_p = *argv; *tmp_p != '\0'; tmp_p++) { if (*tmp_p == '/') { prog_p = tmp_p + 1; } } } /* so we can step on the environmental space */ (void)strncpy(argv_program, prog_p, PROGRAM_NAME); /* count the args */ entry_c = 0; for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { entry_c++; } /* verify the argument array */ if (preprocess_array(args, entry_c) != NOERROR) { return ERROR; } /* allocate our value queue */ if (arg_n > 0) { /* allocate our argument queue */ queue_list = (argv_t **)malloc(sizeof(argv_t *) * arg_n); if (queue_list == NULL) { return ERROR; } queue_head = 0; queue_tail = 0; } /* do the env args before? */ if (argv_process_env_b && (! argv_env_after_b)) { if (do_env_args(args, queue_list, &queue_head, &queue_tail, &okay_b) != NOERROR) { return ERROR; } } /* do the external args */ do_list(args, arg_n - 1, argv + 1, queue_list, &queue_head, &queue_tail, &okay_b); /* DO the env args after? */ if (argv_process_env_b && argv_env_after_b) { if (do_env_args(args, queue_list, &queue_head, &queue_tail, &okay_b) != NOERROR) { return ERROR; } } /* make sure the XOR and MAND args and argument-options are okay */ if (check_mand(args) != NOERROR) { okay_b = ARGV_FALSE; } if (check_opt(queue_head, queue_tail) != NOERROR) { okay_b = ARGV_FALSE; } if (check_xor(args) != NOERROR) { okay_b = ARGV_FALSE; } /* if we allocated the space then free it */ if (arg_n > 0) { free(queue_list); } /* was there an error? */ if (! okay_b) { if (argv_error_stream != NULL) { do_usage(args, argv_error_type); } if (argv_interactive) { (void)exit(argv_error_code); } return ERROR; } return NOERROR; } /* * int argv_process * * DESCRIPTION: * * Processes a number of arguments depending on the argument array. * This routine will not modify the argv array in any way. * * NOTE: it will modify the args array by setting various flags in the * type field. returns 0 if no error else -1. * * ARGUMENTS: * * args - Array of argv_t structures that we are using to process the * user argument array. If null then an empty array is used. * * argc - Number of arguments in the argv argument array. * * argv - Array of character pointer arguments terminated by a 0L. */ int argv_process(argv_t *args, const int argc, char **argv) { if (! enabled_b) { argv_startup(); } /* we only process env variables here */ if (process_env() != NOERROR) { return ERROR; } if (argv_process_no_env(args, argc, argv) == NOERROR) { return NOERROR; } else { return ERROR; } } /* * int argv_usage * * DESCRIPTION: * * Print the standard usage messages for our argument array. You can * specify whether you want to see a short or long usage messages. * * NOTE: if this is called before argv_process then the program name * may be invalid. * * RETURNS: * * Success - 0 * * Failure - -1 * * ARGUMENTS: * * args - Our argument array to print the usage messages about. If * null then an empty array is used. * * which - Either ARGV_USAGE_SHORT (for short usage messages), * ARGV_USAGE_LONG (for long usage messages), or ARGV_USAGE_DEFAULT * (the user's default either long or short). */ int argv_usage(const argv_t *args, const int which) { if (! enabled_b) { argv_startup(); } if (process_env() != NOERROR) { return ERROR; } if (args == NULL) { args = empty; } if (which == ARGV_USAGE_SHORT || which == ARGV_USAGE_LONG || which == ARGV_USAGE_ALL) { do_usage(args, which); } else { /* default/env settings */ do_usage(args, argv_usage_type); } return NOERROR; } /* * int argv_was_used * * DESCRIPTION: * * See if an argument was used in a previous call to argv_process. * * RETURNS: * * 1 if yes it was used, else 0 if not. * * ARGUMENTS: * * args - Argument list to search. * * short_arg - Short argument to see if it was used. */ int argv_was_used(const argv_t *args, const char short_arg) { const argv_t *arg_p; if (! enabled_b) { argv_startup(); } for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { if (arg_p->ar_short_arg == short_arg) { if (arg_p->ar_type & ARGV_FLAG_USED) { return 1; } else { return 0; } } } return 0; } /* * int argv_long_was_used * * DESCRIPTION: * * See if a long argument was used in a previous call to argv_process. * * RETURNS: * * 1 if yes it was used, else 0 if not. * * ARGUMENTS: * * args - Argument list to search. * * long_arg - Long argument to see if it was used. */ int argv_long_was_used(const argv_t *args, const char *long_arg) { const argv_t *arg_p; if (! enabled_b) { argv_startup(); } for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { if (arg_p->ar_long_arg == long_arg) { if (arg_p->ar_type & ARGV_FLAG_USED) { return 1; } else { return 0; } } } return 0; } /* * int argv_entry_was_used * * DESCRIPTION: * * See if an entry in the argument array was used in a previous call * to argv_process. * * RETURNS: * * 1 if yes it was used, else 0 if not. * * ARGUMENTS: * * argv_entry_p - Pointer to an entry in a argv_t list. */ int argv_entry_was_used(const argv_t *argv_entry_p) { if (argv_entry_p->ar_type & ARGV_FLAG_USED) { return 1; } else { return 0; } } /* * void argv_cleanup * * DESCRIPTION: * * Frees up any allocations associated with the argument array during * argv_process. This should be done at the end of the program or * after all the arguments have been referenced. * * RETURNS: * * None. * * ARGUMENTS: * * args - Argument array we are cleaning up. */ void argv_cleanup(const argv_t *args) { const argv_t *arg_p; int entry_c; if (! enabled_b) { argv_startup(); } if (args == NULL) { return; } /* run through the argument structure */ for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) { /* handle any arrays */ if (arg_p->ar_type & ARGV_FLAG_ARRAY) { argv_array_t *arr_p = (argv_array_t *)arg_p->ar_variable; /* free any entries */ if (arr_p->aa_entry_n > 0) { if (ARGV_TYPE(arg_p->ar_type) == ARGV_CHAR_P) { for (entry_c = 0; entry_c < arr_p->aa_entry_n; entry_c++) { free(ARGV_ARRAY_ENTRY(*arr_p, char *, entry_c)); } } free(arr_p->aa_entries); } arr_p->aa_entries = NULL; arr_p->aa_entry_n = 0; continue; } /* handle individual charps */ if (arg_p->ar_type & ARGV_FLAG_USED && ARGV_TYPE(arg_p->ar_type) == ARGV_CHAR_P) { free(*(char **)arg_p->ar_variable); continue; } } } /* * int argv_copy_args * * DESCRIPTION: * * Copy all the arguements (not including the 0th) one after the other * into the user specified buffer. * * NOTE: you can get the 0th argument from argv_argv[0] or * argv_program. * * RETURNS: * * Success - 0 * * Failure - -1 * * ARGUMENTS: * * buf - Buffer to copy all of the user arguments into. * * buf_size - Size of the buffer. */ int argv_copy_args(char *buf, const int buf_size) { char **argv_p, *buf_p = buf, *arg_p; int arg_c, size_c = buf_size; if (! enabled_b) { argv_startup(); } if (buf_size <= 0) { return NOERROR; } *buf_p = '\0'; if (argv_argv == NULL || buf_size == 1) { return NOERROR; } for (argv_p = argv_argv + 1, arg_c = 1; arg_c < argv_argc; argv_p++, arg_c++) { /* we compare against 2 for the ' ' and the \0 */ if (size_c < 2) { break; } if (argv_p > argv_argv + 1) { *buf_p++ = ' '; size_c--; } /* we always compare against 2 to include the \0 */ for (arg_p = *argv_p; *arg_p != '\0' && size_c >= 2; size_c--) { *buf_p++ = *arg_p++; } } *buf_p = '\0'; return NOERROR; } /* * int argv_value_string * * DESCRIPTION: * * Convert the value of a RC entry to its string equivalent in the * buffer provided. * * RETURNS: * * Length of bytes copied into the buffer. * * ARGUMENTS: * * argv_entry_p - Pointer to an entry in a argv_t list. * * buf - Buffer to convert the value into. * * buf_size - Size of the buffer. */ int argv_value_string(const argv_t *argv_entry_p, char *buf, const int buf_size) { argv_array_t *arr_p; int ret, len; char details[128]; if (! enabled_b) { argv_startup(); } /* do we have an array here? */ if (argv_entry_p->ar_type & ARGV_FLAG_ARRAY) { /* if we have an array, then */ arr_p = (argv_array_t *)argv_entry_p->ar_variable; if (arr_p->aa_entry_n == 0) { strncpy(buf, "0 array entries", buf_size); buf[buf_size - 1] = '\0'; ret = strlen(buf); } else { len = value_to_string(arr_p->aa_entries, ARGV_TYPE(argv_entry_p->ar_type), buf, buf_size); if (arr_p->aa_entry_n == 1) { ret = len; } else { (void)loc_snprintf(details, sizeof(details), " (1st of %d entries)", arr_p->aa_entry_n); strncpy(buf + len, details, buf_size - len); buf[buf_size - 1] = '\0'; ret = strlen(buf); } } } else { ret = value_to_string(argv_entry_p->ar_variable, argv_entry_p->ar_type, buf, buf_size); } return ret; } /* * int argv_type_info * * DESCRIPTION: * * Get internal information about the type of the argument. * * RETURNS: * * The name of the type. * * ARGUMENTS: * * type - Number of argument type. * * size_p - Pointer to an unsigned integer which, if not NULL, will be * set with the size of the type. * * desc_p - Pointer to a constant character pointer which, if not * NULL, will be pointed to a description of the type. */ const char *argv_type_info(const unsigned int type, unsigned int *size_p, const char **desc_p) { unsigned int val_type; argv_type_t *type_p; val_type = ARGV_TYPE(type); for (type_p = argv_types; type_p->at_value != 0; type_p++) { if (type_p->at_value == val_type) { if (size_p != NULL) { *size_p = type_p->at_size; } if (desc_p != NULL) { *desc_p = type_p->at_desc; } return type_p->at_name; } } if (size_p != NULL) { *size_p = 0; } if (desc_p != NULL) { *desc_p = "Unknown type"; } return "(unknown type)"; } dmalloc-5.5.2/settings.dist000640 001751 001751 00000037540 10622115666 015645 0ustar00graygray000000 000000 /* * Manual configuration flags * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: settings.dist,v 1.71 2007/03/13 01:11:25 gray Exp $ */ /* * PROGRAMMING NOTE: this file cannot be included before conf.h, so * you might as well only include conf.h and never this file. */ #ifndef __SETTINGS_H__ #define __SETTINGS_H__ /* * Should we allow zero length allocations? This will generate the * smallest possible allocation. * * FYI: if fence post checking is requested, the top and bottom of the * fence post information will be touching. */ #define ALLOW_ALLOC_ZERO_SIZE 1 /* * Should we allow realloc of a NULL pointer? If set to one, this * will call malloc when 0L is realloc-ed. This is useful when you * are extending an array in a loop and do not want to allocate it * specially the first time. */ #define ALLOW_REALLOC_NULL 1 /* * Should we allow realloc to a 0 size to cause the pointer to be * freed? If set to one, this will call free when a pointer is * realloc-ed to a size of 0. Thanks to Stefan Froehlich * for patiently pointing that the realloc in just about every Unix * has this functionality. */ #define ALLOW_REALLOC_SIZE_ZERO 1 /* * I have swayed to public pressure and allowing free(0L) is now the * default. Sigh. :-) * * Should we allow the free of a NULL pointer and if it happens, * should a message be generated to that effect. Most (if not all) * POSIX C libraries allow you to free() or delete() a NULL pointer * and a number of programming reference manuals mention that freeing * of NULL is "allowed". However, I believe that it is bad form, * promotes lazy pointer handling, and can often hide program bugs. I * encourage you to do something like the following in your programs: * if (pnt != NULL) { free(pnt); } * * Setting ALLOW_FREE_NULL to 0 will cause an exception whenever a * free of NULL is encountered allowing the user to determine where * s/he is freeing a possibly random pointer. I recommend at least * logging a message with the ALLOW_FREE_NULL_MESSAGE set to 1. * * Even with ALLOW_FREE_NULL set to 1, you can enable the * 'error-free-null' token at runtime for a specific program to * generate an exception when it sees a free(0L). */ #define ALLOW_FREE_NULL 1 #define ALLOW_FREE_NULL_MESSAGE 1 /* * Should we use the ra-address macros in return.h. These are system * specific macros designed to return the return-address for logging * callers (i.e. possible offenders) of malloc routines. * * Please mail me if you have any questions with this functionality. */ #define USE_RETURN_MACROS 1 /* * Write this character into memory when it is allocated and not * calloc-ed if the alloc-blank token is enabled. It will also write * this into realloc'd memory which you extend or reduce. You can * verify that these sections have not been overwritten with the * check-blank token. * * \332 == 0xda, 0332, decimal 218 (i.e. dmalloc-alloc) */ #define ALLOC_BLANK_CHAR '\332' /* * Write this character into memory when it is freed if the free-blank * token is enabled. You can verify that these sections have not been * overwritten with the check-blank token. * * \337 == 0xdf, 0337, decimal 223 (i.e. dmalloc-free) */ #define FREE_BLANK_CHAR '\337' /* * The following information sets limits on the size of the source * file name and line numbers returned by the __FILE__ and __LINE__ * compiler macros. You may need to tune then to fit your environment * although I would argue that if you have filenames longer than 40 * characters or files longer than 10,000 lines, you are doing * something wrong. * * MIN_FILE_LENGTH 3 => file "[a-zA-Z].c" * * Set MAX_FILE_LENGTH or MAX_LINE_NUMBER to be 0 to disable checks. * * NOTE: if the max is changed then the dmalloc.texi file reference to * it will need to be changed too. */ #define MIN_FILE_LENGTH 3 #define MAX_FILE_LENGTH 100 #define MAX_LINE_NUMBER 30000 /* * The largest allowable allocation size. This is only for * verification purposes to control allocations of bizarre sizes. Any * allocation larger than this will generate a ERROR_TOO_BIG error. * * Set to 0 to disable the test altogether. */ #define LARGEST_ALLOCATION 268435456UL /* 256 mb */ /* * Automatically call dmalloc_shutdown if on_exit or atexit is * available. See conf.h for whether configure found on_exit or * atexit calls. If neither is available, your program will have to * call dmalloc_shutdown yourself before it exits. You can also take * a look at atexit.c in the contrib directory which may provide this * useful functionality for your system. * * NOTE: If you are having problems with the library going recursive * (see LOCK_THREADS below if you are using pthreads), you might want * to try setting this to 0. Because the library makes a call to * on_exit or atexit to register itself, it may cause memory * transactions by the system causing the dreaded recursive message. * You may then be forced to register dmalloc_shutdown yourself via * on_exit or atexit in main() or call dmalloc_shutdown directly * before you exit(). */ #define AUTO_SHUTDOWN 1 /* * The ABORT_OKAY is auto-configured but may have to be adjusted by * forcing the USE_ABORT to be 1 or 0. On some OS's, abort calls * fclose() which may want to free memory making the library go * recursive when it is aborting. See ABORT_OKAY in the conf.h file * for more information. * * If you need to override it or if ABORT_OKAY is 0, set KILL_PROCESS * to the proper way to stop the program. Killing the current process * (id 0) with SIGABRT works on a number of Unix systems. You may * have to define some include file to get the value for the signal * that is used. * * Alternatives might be: * * #define KILL_PROCESS { int *_int_p = 0L; *_int_p = 1; } */ #if ABORT_OKAY #define USE_ABORT 1 #else #define USE_ABORT 0 #endif #if SIGNAL_OKAY #define KILL_INCLUDE #define KILL_PROCESS (void)kill(0, SIGABRT) #endif /* * Define the signals that are to be caught by the catch-signals * token. When caught, these signals will cause an automatic shutdown * of the library so that the not-freed memory and other statistics will * be displayed. Thanks Marty. */ #if SIGNAL_OKAY #define SIGNAL1 SIGHUP #define SIGNAL2 SIGINT #define SIGNAL3 SIGTERM #undef SIGNAL4 #undef SIGNAL5 #undef SIGNAL6 #endif /* * Number of bytes to write at the top of allocations (if fence-post * checking is enabled). A larger number means more memory space used * up but better protection against fence overruns. See the manual * for more information. */ #define FENCE_TOP_SIZE 4 /* * Number of bytes to write at the bottom of allocations. See the * FENCE_TOP_SIZE setting above or the manual for more information. * * WARNING: this should changed with caution and probably should only be * increased. If you need to change it, use (ALLOCATION_ALIGNMENT * * X) or some such. For more information see ALLOCATION_ALIGNMENT in * conf.h. */ #define FENCE_BOTTOM_SIZE ALLOCATION_ALIGNMENT /* * Amount of space that we are to display whenever we need to dump a * pointer's contents to a log file or stream. This should be more * than FENCE_BOTTOM_SIZE and FENCE_TOP_SIZE. */ #define DUMP_SPACE 20 /* * At the front of each log message, print the output from the time() * call as a number. This requires that the time function be defined. */ #define LOG_TIME_NUMBER 1 #define TIME_INCLUDE /* * Write the iteration count at the start of every log entry. This is * handy when you are using the DMALLOC_START variable and want to * begin the tough debugging at a certain point. This is also returned * by the dmalloc_mark() function. */ #define LOG_ITERATION 1 /* * Write the pid number at the start of every log entry if the * getpid() function is available. This is handy when you are using * dmalloc with a program which forks. See LOG_REOPEN below. */ #define LOG_PID 0 /* * If the getpid() function is available, notice when the pid of the * process changes and reopen the logfile. This is handy when you are * using dmalloc with a program which forks and you want the separate * forked programs to have separate logs. * * NOTE: This only works if the %p string is in the logfile name * otherwise the log might reopen and clobber the existing log. */ #define LOG_REOPEN 1 /* * Store the number of times a pointer is "seen" being allocated or * freed -- it shows up as a s# (for seen) in the logfile. This is * useful for tracking of not-freed memory. See the documents for more * information. * * NOTE: This creates a certain amount of memory overhead. */ #define LOG_PNT_SEEN_COUNT 1 /* * Store the iteration count when a pointer is allocated -- it * shows up as a i# (for iteration) in the logfile. This is to give * you some idea when during program execution, a pointer was * allocated but not freed. * * NOTE: This creates a certain amount of memory overhead. */ #define LOG_PNT_ITERATION 0 /* * At the front of each log message, print the output from the ctime() * function (not including the \n). The TIME_NUMBER_TYPE is the type * that will store the output of time() and whose address we will pass * into ctime. This requires that the ctime and time functions both * be defined. */ #if LOG_TIME_NUMBER == 0 #define LOG_CTIME_STRING 1 #define TIME_TYPE unsigned int #endif /* * Store the time (in seconds) or timeval (in seconds and * microseconds) when a pointer is allocated -- it shows up as a w# * (for when) in the logfile. This is to give you some idea when a * pointer was allocated but not freed. The library will log the * starting and the ending time if either of these flags is set. * TIMEVAL_INCLUDE is the include file to define struct timeval and * GET_TIMEVAL does the actual reading of the current time of day. * * WARNING: only TIME _or_ TIMEVAL can be defined at one time. * * NOTE: This creates a certain amount of memory overhead. */ #define LOG_PNT_TIME 0 #ifndef TIME_INCLUDE #define TIME_INCLUDE #endif #ifndef TIME_TYPE #define TIME_TYPE unsigned int #endif #define LOG_PNT_TIMEVAL 0 #define TIMEVAL_INCLUDE #define TIMEVAL_TYPE struct timeval #define GET_TIMEVAL(timeval) (void)gettimeofday(&(timeval), NULL) /* * In OSF (anyone else?) you can setup __fini_* functions in each * module which will be called automagically at shutdown of the * program. If you enable this variable, dmalloc will shut itself * down and log statistics when the program closes on its own. Pretty * cool OS feature. */ #define FINI_DMALLOC 0 /* If you enable this, you probably want the AUTO_SHUTDOWN flag turned off */ #if FINI_DMALLOC #undef AUTO_SHUTDOWN #define AUTO_SHUTDOWN 0 #endif /* * Keep addresses that are freed from recycling back into the used * queue for a certain number of memory transactions. For instance, * if this is set to 10 then after you free a pointer, it cannot be * reused until after 10 additional calls to malloc, free, realloc, * etc.. Define to 0 to disable. NOTE: setting to 1 does nothing. * * For more drastic debugging, you can enable the never-reuse flag * which will cause the library to never reuse previously allocated * memory. This may significantly expand the memory requirements of * your system however. */ #define FREED_POINTER_DELAY 20 /* * Size of the table of file and line number memory entries. This * memory table records the top locations by file/line or * return-address of all pointers allocated. It also tabulates the * freed memory pointers so you can easily locate the large memory * leaks. See the MEMORY_TABLE_TOP_LOG value below to 0 to disable * the table. * * NOTE: The table will only hold the _first_ pointers into the table. * If you configure a size of 10 then the 11th pointer allocated will * not be accounted for. * * NOTE: the library will actually allocated 2 times this many entries * for speed reasons. */ #define MEMORY_TABLE_SIZE 4096 /* * This indicates how many of the top entries from the memory table * you want to log by default to the log file. * * NOTE: to display the top entries correctly, your OS must support * the quicksort function. */ #define MEMORY_TABLE_TOP_LOG 10 /* * Define this to 1 to only display the memory table summary of the * dumped table pointers. The default is to display the summary as * well as the individual pointers so the individual leaks can be * tracked down. */ #define DUMP_UNFREED_SUMMARY_ONLY 0 /* * If (and _only_ if) your system does not have sbrk(), you can have * dmalloc pre-allocate its only heap space. The default heap size is * 1mb but you can set the space to be any size. For super-small * memory applications please understand that dmalloc is in no way * optimized for space and so you can easily run out of memory with * it. * * WARNING: this probably should only be used if HAVE_SBRK and * HAVE_MMAP are 0. Please send me email with any problems or * comments on this feature. */ #if HAVE_SBRK == 0 && HAVE_MMAP == 0 #define INTERNAL_MEMORY_SPACE (1024 * 1024) #endif /* * The default smallest allowable allocations in bytes. Any blocks * asked for that are smaller will be rounded up to this size. */ #define DEFAULT_SMALLEST_ALLOCATION 8 /****************************** thread settings ******************************/ /* * The following definition allows use of the library in threaded * programs. The most common package is MIT's pthreads so this is the * default. Please send me mail if these definitions are configurable * enough to work with your thread package. */ #ifndef LOCK_THREADS #define LOCK_THREADS 0 #endif #if LOCK_THREADS /* * Which threads library header to include when needed. It is assumed * that the types and functions in the THREAD_TYPE and THREAD_GET_ID * macros below are defined in this include file. In addition, the * thread mutex init, lock, and unlock functions in malloc.c should * also be prototyped here. */ #define THREAD_INCLUDE /* * As we approach the time when we start mutex locking the library, we * need to init the mutex variable. This sets how many times before * we start locking should we init the variable taking in account that * the init itself might generate a call into the library. Ugh. */ #define THREAD_INIT_LOCK 2 /* * For those threaded programs, the following settings allow the * library to log the identity of the thread that allocated a specific * pointer. The thread-id will show up as a ``t'' followed by a * string identifying the thread. The LOG_THREAD_ID macro says * whether the thread-id is logged at the front of all log messages. * The THREAD_TYPE macro defines the variable type of the id. The * THREAD_GET_ID macro is what function to call to get the currently * running thread. The THREAD_ID_TO_STRING defines how the thread-id * value is translated to the string necessary to be included with the * ``t'' in the logfile. */ #define LOG_PNT_THREAD_ID 0 #define THREAD_TYPE pthread_t #define THREAD_GET_ID() pthread_self() #if HAVE_SNPRINTF #define THREAD_ID_TO_STRING(buf, buf_size, thread_id) \ (void)snprintf((buf), (buf_size), "%#lx", \ (long)(thread_id)) #else #define THREAD_ID_TO_STRING(buf, buf_size, thread_id) \ (void)sprintf((buf), "%#lx", (long)(thread_id)) #endif #endif /* LOCK_THREADS */ #endif /* ! __SETTINGS_H__ */ dmalloc-5.5.2/version.h000640 001751 001751 00000002525 10622115666 014751 0ustar00graygray000000 000000 /* * Version string for the library * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: version.h,v 1.132 2007/05/14 17:23:37 gray Exp $ */ #ifndef __VERSION_H__ #define __VERSION_H__ /* * NOTE to gray: whenever this is changed, a corresponding entry * should be entered in: * * Changlog * NEWS * RELEASE.html * configure.ac (in AC_INIT) * dmalloc.spec * dmalloc.texi * dmalloc.h.4 (DMALLOC_VERSION defines at top of file) * ports/.../Makefile and ports/.../distfile files * * Make sure to also cvs tag the release. dmalloc_release_X_X_X */ static char *dmalloc_version = "5.5.2" ; /* Version Date: $Date: 2007/05/14 17:23:37 $ */ #endif /* ! __VERSION_H__ */ dmalloc-5.5.2/return.h000640 001751 001751 00000021560 10622115666 014603 0ustar00graygray000000 000000 /* * defines to get the return-address for non-dmalloc_lp malloc calls. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: return.h,v 1.37 2005/10/15 14:44:22 gray Exp $ */ /* * This file contains the definition of the SET_RET_ADDR macro which * is designed to contain the archecture/compiler specific hacks to * determine the return-address from inside the malloc library. With * this information, the library can display caller information from * calls that do not use the malloc_lp functions. * * Most of the archectures here have been contributed by other * individuals and may need to be toggled a bit to remove local * configuration differences. * * PLEASE send all submissions, comments, problems to the author. * * NOTE: examining the assembly code for x = * __builtin_return_address(0); with gcc version 2+ should give you a * good start on building a hack for your box. */ #ifndef __RETURN_H__ #define __RETURN_H__ /* * we check this here because configure needs to be able to use * return.h without conf.h existance */ #ifndef __CONF_H__ #include "conf.h" /* for USE_RETURN_MACROS and RETURN_MACROS_WORK */ #endif #if USE_RETURN_MACROS && RETURN_MACROS_WORK /*************************************/ /* for Sun SparcStations with GCC */ #if __sparc && __GNUC__ > 1 /* * NOTE: %i7 seems to be more reliable than the [%fp+4] used by * __builtin_return_address. [%fp+4] is on the stack however, meaning * it may be better -- less prone to be erased. However, it produces * some bogus data -- it seems to return the last return-address or * something like that. * * Alexandre Oliva recently advised to change the "=g" to a "=m". If * you are having problems, you may want to return to the =g to see if * it works. */ #define GET_RET_ADDR(file) asm("st %%i7,%0" : \ "=m" (file) : \ /* no inputs */ ) #if 0 /* this was the default however =g was recommended to be changed to =m */ #define GET_RET_ADDR(file) asm("st %%i7,%0" : \ "=g" (file) : \ /* no inputs */ ) /* * This was what the gcc __builtin_return_address returned. The above * versions worked better. It is here for reference purposes only. */ #define GET_RET_ADDR(file) asm("ld [%%fp+4],%%o0; st %%o0,%0" : \ "=g" (file) : \ /* no inputs */ : \ "o0") #endif #endif /* __sparc */ /*************************************/ /* for i[34]86 machines with GCC */ #if __i386 && __GNUC__ > 1 #define GET_RET_ADDR(file) asm("movl 4(%%ebp),%%eax ; movl %%eax,%0" : \ "=g" (file) : \ /* no inputs */ : \ "eax") #endif /* __i386 */ /*************************************/ /* * For DEC Mips machines running Ultrix */ #if __mips /* * I have no idea how to get inline assembly with the default cc. * Anyone know how? */ #if 0 /* * NOTE: we assume here that file is global. * * $31 is the frame pointer. $2 looks to be the return address but maybe * not consistently. */ #define GET_RET_ADDR(file) asm("sw $2, file") #endif #endif /* __mips */ /******************************* contributions *******************************/ /* * For DEC Alphas running OSF. From Dave Hill and Alexandre Oliva. * Thanks guys. */ #if __alpha #ifdef __GNUC__ #define GET_RET_ADDR(file) asm("bis $26, $26, %0" : "=r" (file)) #else /* __GNUC__ */ #include #define GET_RET_ADDR(file) file = (char *)asm("bis %ra,%ra,%v0") #endif /* __GNUC__ */ #endif /* __alpha */ /*************************************/ /* * For Data General workstations running DG/UX 5.4R3.00 from Joerg * Wunsch. */ #ifdef __m88k__ /* * I have no ideas about the syntax of Motorola SVR[34] assemblers. * Also, there may be occasions where gcc does not set up a stack * frame for some function, so the returned value should be taken with * a grain of salt. For the ``average'' function calls it proved to be * correct anyway -- jw */ #if !__DGUX__ || _DGUXCOFF_TARGET # define M88K_RET_ADDR "ld %0,r30,4" #else /* __DGUX__ && !_DGUXCOFF_TARGET: DG/UX ELF with version 3 assembler */ # define M88K_RET_ADDR "ld %0,#r30,4" #endif #define GET_RET_ADDR(file) asm(M88K_RET_ADDR : \ "=r" (file) : \ /* no inputs */) #endif /* m88k */ /*************************************/ /* * SGI compilers implement a C level method of accessing the return * address by simply referencing the __return_address symbol. -- James * Bonfield. */ #if defined(__sgi) #define GET_RET_ADDR(file) file = (void *)__return_address #endif /* __sgi */ /*************************************/ /* * Stratus FTX system (UNIX_System_V 4.0 FTX release 2.3.1.1 XA/R * Model 310 Intel i860XP processor) * * I ended up with compiling according to full-ANSI rules (using the * -Xa compiler option). This I could only do after modifying the * "dmalloc.h.3" in such a way that the malloc/calloc/realloc/free * definitions would no longer cause the compiler to bark with * 'identifier redeclared' (I just put an #ifdef _STDLIB_H ... #endif * around those functions). -- Wim van Duuren. */ #if defined(_FTX) && defined(i860) /* * we first have the define the little assembly code function */ asm void ASM_GET_RET_ADDR(file) { % reg file; mov %r1, file % mem file; st.l %r31,-40(%fp) orh file@ha, %r0, %r31 st.l %r1, file@l(%r31) ld.l -40(%fp),%r31 % error } #define GET_RET_ADDR(file) ASM_GET_RET_ADDR(file) #endif /* _FTX & i860 */ /*************************************/ /* * For HP-UX PA-RISC with gcc/g++ from Jack Perdue. */ #if __hpux && __hppa && __GNUC__ > 1 /* * This is my very first line of PA-RISC assembly ever. I have no * idea if is correct, but it seems to work. Register 2 (%r2) * contains the return address. The code generated by x = * __builtin_return_address() was considerably longer and without a * PA-RISC Instruction Set guide available (not even on the web), I * just put togther little tidbits of knowledge I found while looking * for one to take a stab with this. Like I said, it seems to work on * my g++ code under HPUX11 on a HP V-class system. YMMV. -- Jack * Perdue. */ #define GET_RET_ADDR(file) asm("stw %%r2, %0" : "=m" (file) : ); #endif /*************************************/ /* * For Powerpc 603 based system running LynxOS 2.3.1 using gcc/gas. */ #if defined(__powerpc__) && defined(__GNUC__) && !defined(__OPTIMIZE__) /* * This won't compile if "-O2" is used, but it seems to work fine with * "-O0". I'm no assembler expert; I was happy enough to come up with * something that works at all... :-) */ #define GET_RET_ADDR(file) \ do { \ asm("mflr 0"); \ asm("stw 0,%0" : "=g" (file)); \ } while(0) #endif /* __powerpc__ && __GNUC__ && !__OPTIMIZE__ */ /*************************************/ /* * RH AS2.1 gcc 2.96, tested on a piece of code compiled with icc (Intel * compiler V8) from Didier Remy. */ #ifdef __ia64__ #define GET_RET_ADDR(file) asm("mov %0=b0" : "=g" (file) : /* no inputs */ ) #endif /*************************************/ /* * AIX 4.3 RS/6000 from Joe Buehler. */ #if defined(_AIX) static void aix_c_get_ret_addr(int i, int *file) { int start = *((int *)&start + 4); while (--i >= 0) { start = *((int *)start); } *file = *((int *)start + 2); } #define GET_RET_ADDR(file) aix_c_get_ret_addr(0, (int *)&file) #endif /* _AIX */ /*************************************/ /* * For ARM based machines with gcc/gas 3.3.3 -- Silvester Erdeg. Used * to be =g which may be for various gcc/gas or arm versions. Please * let the dmalloc author know if there is a better ifdef combination * for this. */ #ifdef __arm__ #define GET_RET_ADDR(file) asm("str lr, %0" : "=m" (file) : /* no inputs */ ) #endif /*************************************/ /* * For Analog Device's Blackfin processors with gcc/gas 3.4.1 -- * Silvester Erdeg. */ #ifdef bfin #define GET_RET_ADDR(file) asm("%0 = RETS;" : "=g" (file) : /* no inputs */ ) #endif /*************************************/ #endif /* USE_RETURN_MACROS */ /********************************** default **********************************/ /* for all others, do nothing */ #ifndef GET_RET_ADDR #ifdef DMALLOC_DEFAULT_FILE #define GET_RET_ADDR(file) file = DMALLOC_DEFAULT_FILE #else #define GET_RET_ADDR(file) file = 0L #endif #endif #endif /* ! __RETURN_H__ */ dmalloc-5.5.2/malloc_funcs.h000640 001751 001751 00000020556 10622115666 015735 0ustar00graygray000000 000000 /* * Function prototypes for the malloc user level routines. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://www.dmalloc.com/ * * $Id: malloc_funcs.h,v 1.1 2000/11/07 17:33:03 gray Exp $ */ #ifndef __MALLOC_H__ #define __MALLOC_H__ /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ /* * Shutdown memory-allocation module, provide statistics if necessary */ extern void _dmalloc_shutdown(void); #if FINI_DMALLOC /* * Automatic OSF function to close dmalloc. Pretty cool OS/compiler * hack. By default it is not necessary because we use atexit() and * on_exit() to register the close functions. These are more * portable. */ extern void __fini_dmalloc(); #endif /* if FINI_DMALLOC */ /* * Allocate and return a SIZE block of bytes. FUNC_ID contains the * type of function. If we are aligning our malloc then ALIGNMENT is * greater than 0. * * Returns 0L on error. */ extern DMALLOC_PNT _loc_malloc(const char *file, const int line, const DMALLOC_SIZE size, const int func_id, const DMALLOC_SIZE alignment); /* * Resizes OLD_PNT to NEW_SIZE bytes and return the new space after * either copying all of OLD_PNT to the new area or truncating. If * OLD_PNT is 0L then it will do the equivalent of malloc(NEW_SIZE). * If NEW_SIZE is 0 and OLD_PNT is not 0L then it will do the * equivalent of free(OLD_PNT) and will return 0L. If the RECALLOC_B * flag is enabled, it will zero any new memory. * * Returns 0L on error. */ extern DMALLOC_PNT _loc_realloc(const char *file, const int line, DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size, const int func_id); /* * Release PNT in the heap. * * Returns FREE_ERROR, FREE_NOERROR. */ extern int _loc_free(const char *file, const int line, DMALLOC_PNT pnt); /* * Allocate and return a SIZE block of bytes. * * Returns 0L on error. */ extern DMALLOC_PNT malloc(DMALLOC_SIZE size); /* * Allocate and return a block of _zeroed_ bytes able to hold * NUM_ELEMENTS, each element contains SIZE bytes. * * Returns 0L on error. */ extern DMALLOC_PNT calloc(DMALLOC_SIZE num_elements, DMALLOC_SIZE size); /* * Resizes OLD_PNT to NEW_SIZE bytes and return the new space after * either copying all of OLD_PNT to the new area or truncating. If * OLD_PNT is 0L then it will do the equivalent of malloc(NEW_SIZE). * If NEW_SIZE is 0 and OLD_PNT is not 0L then it will do the * equivalent of free(OLD_PNT) and will return 0L. * * Returns 0L on error. */ extern DMALLOC_PNT realloc(DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size); /* * Resizes OLD_PNT to NEW_SIZE bytes and return the new space after * either copying all of OLD_PNT to the new area or truncating. If * OLD_PNT is 0L then it will do the equivalent of malloc(NEW_SIZE). * If NEW_SIZE is 0 and OLD_PNT is not 0L then it will do the * equivalent of free(OLD_PNT) and will return 0L. Any extended * memory space will be zeroed like calloc. * * Returns 0L on error. */ extern DMALLOC_PNT recalloc(DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size); /* * Allocate and return a SIZE block of bytes that has been aligned to * ALIGNMENT bytes. ALIGNMENT must be a power of two and must be less * than or equal to the block-size. * * Returns 0L on error. */ extern DMALLOC_PNT memalign(DMALLOC_SIZE alignment, DMALLOC_SIZE size); /* * Allocate and return a SIZE block of bytes that has been aligned to * a page-size. * * Returns 0L on error. */ extern DMALLOC_PNT valloc(DMALLOC_SIZE size); #ifndef DMALLOC_STRDUP_MACRO /* * Allocate and return a block of bytes that contains the string STR * including the \0. * * Returns 0L on error. */ extern char *strdup(const char *str); #endif /* ifndef DMALLOC_STRDUP_MACRO */ /* * Release PNT in the heap. * * Returns FREE_ERROR, FREE_NOERROR or void depending on whether STDC * is defined by your compiler. */ extern DMALLOC_FREE_RET free(DMALLOC_PNT pnt); /* * same as free PNT */ extern DMALLOC_FREE_RET cfree(DMALLOC_PNT pnt); /* * Log the heap structure plus information on the blocks if necessary. */ extern void _dmalloc_log_heap_map(const char *file, const int line); /* * Dump dmalloc statistics to logfile. */ extern void _dmalloc_log_stats(const char *file, const int line); /* * Dump unfreed-memory info to logfile. */ extern void _dmalloc_log_unfreed(const char *file, const int line); /* * Verify pointer PNT, if PNT is 0 then check the entire heap. * * Returns MALLOC_VERIFY_ERROR or MALLOC_VERIFY_NOERROR */ extern int _dmalloc_verify(const char *file, const int line, const DMALLOC_PNT pnt); /* * Verify pointer PNT, if PNT is 0 then check the entire heap. * * Returns MALLOC_VERIFY_ERROR or MALLOC_VERIFY_NOERROR */ extern int malloc_verify(const DMALLOC_PNT pnt); /* * Set the global debug functionality FLAGS (0 to disable all * debugging). * * NOTE: you cannot remove certain flags such as signal handlers since * they are setup at initialization time only. Also you cannot add * certain flags such as fence-post or free-space checking since they * must be on from the start. * * Returns the old debug flag value. */ extern unsigned int _dmalloc_debug(const unsigned int flags); /* * Returns the current debug functionality flags. This allows you to * save a dmalloc library state to be restored later. */ extern unsigned int _dmalloc_debug_current(void); /* * int _dmalloc_examine * * DESCRIPTION: * * Examine a pointer and return information on its allocation size as * well as the file and line-number where it was allocated. If the * file and line number is not available, then it will return the * allocation location's return-address if available. * * RETURNS: * * Success - DMALLOC_NOERROR * * Failure - DMALLOC_ERROR * * ARGUMENTS: * * file -> File were we are examining the pointer. * * line -> Line-number from where we are examining the pointer. * * pnt -> Pointer we are checking. * * size_p <- Pointer to an unsigned int which, if not NULL, will be * set to the size of bytes from the pointer. * * file_p <- Pointer to a character pointer which, if not NULL, will * be set to the file where the pointer was allocated. * * line_p <- Pointer to a character pointer which, if not NULL, will * be set to the line-number where the pointer was allocated. * * ret_attr_p <- Pointer to a void pointer, if not NULL, will be set * to the return-address where the pointer was allocated. */ extern int _dmalloc_examine(const char *file, const int line, const DMALLOC_PNT pnt, DMALLOC_SIZE *size_p, char **file_p, unsigned int *line_p, DMALLOC_PNT *ret_attr_p); /* * Register an allocation tracking function which will be called each * time an allocation occurs. Pass in NULL to disable. */ extern void _dmalloc_track(const dmalloc_track_t track_func); /* * Return to the caller the current ``mark'' which can be used later * to dmalloc_log_changed pointers since this point. Multiple marks * can be saved and used. */ extern unsigned long _dmalloc_mark(void); /* * Dump the pointers that have changed since the mark which was * returned by dmalloc_mark. If not_freed_b is set to non-0 then log * the new pointers that are non-freed. If free_b is set to non-0 * then log the new pointers that are freed. If details_b set to * non-0 then dump the individual pointers that have changed otherwise * just dump the summaries. */ extern void _dmalloc_log_changed(const char *file, const int line, const unsigned long mark, const int not_freed_b, const int free_b, const int details_b); /* * Dmalloc version of strerror to return the string version of * ERROR_NUM. * * Returns an invaid errno string if ERROR_NUM is out-of-range. */ extern const char *_dmalloc_strerror(const int error_num); /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __MALLOC_H__ */ dmalloc-5.5.2/dmalloc_fc_t.c000644 001751 001751 00000056306 10622115666 015677 0ustar00graygray000000 000000 /* * Specific test program for dmalloc function checking code * * Copyright 2007 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_fc_t.c,v 1.1 2007/03/23 16:20:42 gray Exp $ */ #include /* for stdin */ #if HAVE_STDLIB_H # include /* for exit... */ #endif #if HAVE_STRING_H # include /* for string funcs */ #endif #if HAVE_UNISTD_H # include /* for getpid */ #endif #define DMALLOC_FUNC_CHECK #include "conf.h" #if HAVE_TIME # ifdef TIME_INCLUDE # include TIME_INCLUDE # endif #endif #include "dmalloc.h" #include "dmalloc_argv.h" #include "dmalloc_rand.h" #include "debug_tok.h" #include "error_val.h" /* argument variables */ static char *env_string = NULL; /* env options */ static int log_trans_b = ARGV_FALSE; /* log transactions */ static int random_debug_b = ARGV_FALSE; /* random flag */ static int silent_b = ARGV_FALSE; /* silent flag */ static unsigned int seed_random = 0; /* random seed */ static int verbose_b = ARGV_FALSE; /* verbose flag */ static argv_t arg_list[] = { { 'e', "env-string", ARGV_CHAR_P, &env_string, "string", "string of env commands to set" }, { 'l', "log-trans", ARGV_BOOL_INT, &log_trans_b, NULL, "log transactions via tracking-func" }, { 'r', "random-debug", ARGV_BOOL_INT, &random_debug_b, NULL, "randomly change debug flag" }, { 's', "silent", ARGV_BOOL_INT, &silent_b, NULL, "do not display messages" }, { 'S', "seed-random", ARGV_U_INT, &seed_random, "number", "seed for random function" }, { 'v', "verbose", ARGV_BOOL_INT, &verbose_b, NULL, "enables verbose messages" }, { ARGV_LAST } }; /* * Make sure that the last call did not fail. */ static int check_ok(const char *what) { if (dmalloc_errno == ERROR_NONE) { return 1; } else { if (! silent_b) { (void)printf(" ERROR: %s failed: %s\n", what, dmalloc_strerror(dmalloc_errno)); } dmalloc_message(" ERROR: %s failed: %s\n", what, dmalloc_strerror(dmalloc_errno)); return 0; } } /* * Make sure that the last call failed. */ static int check_fail(const char *what, const int expected_errno) { if (dmalloc_errno == ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s succeeded but should have failed with %s\n", what, dmalloc_strerror(expected_errno)); } dmalloc_message(" ERROR: %s succeeded but should have failed with %s\n", what, dmalloc_strerror(expected_errno)); return 0; } else if (dmalloc_errno == expected_errno) { return 1; } else { if (! silent_b) { (void)printf(" ERROR: %s failed with %s, expected %s\n", what, dmalloc_strerror(dmalloc_errno), dmalloc_strerror(expected_errno)); } dmalloc_message(" ERROR: %s failed with %s, expected %s\n", what, dmalloc_strerror(dmalloc_errno), dmalloc_strerror(expected_errno)); return 0; } } #if HAVE_ATOI static int do_atoi(void) { void *pnt; char *func_name = "atoi"; int val, ret; pnt = malloc(5); val = 1234; strcpy(pnt, "1234"); ret = atoi(pnt); if (! check_ok(func_name)) { return 0; } if (ret != val) { if (! silent_b) { (void)printf(" ERROR: %s should have gotten %d but got %d\n", func_name, val, ret); } return 0; } memmove(pnt, "12345", 5); atoi(pnt); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_ATOL static int do_atol(void) { void *pnt; char *func_name = "atol"; long val, ret; pnt = malloc(5); val = 1234L; strcpy(pnt, "1234"); ret = atol(pnt); if (! check_ok(func_name)) { return 0; } if (ret != val) { if (! silent_b) { (void)printf(" ERROR: %s should have gotten %ld but got %ld\n", func_name, val, ret); } return 0; } memmove(pnt, "12345", 5); atol(pnt); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_BCMP static int do_bcmp(void) { char *pnt, *val; char *func_name = "bcmp"; int ret; pnt = malloc(5); val = "12345"; memmove(pnt, val, strlen(val)); ret = bcmp(pnt, val, 5); if (! check_ok(func_name)) { return 0; } if (ret != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have gotten 0 got %d\n", func_name, ret); } return 0; } val = "123456"; memmove(pnt, val, strlen(val)); bcmp(pnt, val, 6); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_BCOPY static int do_bcopy(void) { char *pnt, *val; char *func_name = "bcopy"; pnt = malloc(5); val = "12345"; bcopy(val, pnt, strlen(val)); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, val, 5) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have copied the bytes\n", func_name); } return 0; } val = "123456"; bcopy(val, pnt, strlen(val)); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_BZERO static int do_bzero(void) { char *pnt; char *func_name = "bzero"; char *zeros = "\000\000\000\000\000"; int size = 5; pnt = malloc(size); strcpy(pnt, "foo"); if (memcmp(pnt, zeros, size) == 0) { if (! silent_b) { (void)printf(" ERROR: %s pnt should not have zeros initially\n", func_name); } return 0; } bzero(pnt, size); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, zeros, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s pnt should have zeros\n", func_name); } return 0; } bzero(pnt, size + 1); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_INDEX static int do_index(void) { char *pnt, *val, *ret; char *func_name = "index"; pnt = malloc(5); val = "foot"; strcpy(pnt, val); ret = index(pnt, 't'); if (! check_ok(func_name)) { return 0; } if (*ret != 't') { if (! silent_b) { (void)printf(" ERROR: %s should have found the t\n", func_name); } return 0; } val = "footy"; memmove(pnt, val, strlen(val)); index(pnt, 'u'); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_MEMCCPY static int do_memccpy(void) { char *pnt, *val, *ret; char *func_name = "memccpy"; pnt = malloc(5); val = "footy"; ret = memccpy(pnt, val, 'z', strlen(val)); if (! check_ok(func_name)) { return 0; } if (ret != 0L) { if (! silent_b) { (void)printf(" ERROR: %s pointer should have returned 0L\n", func_name); } return 0; } if (memcmp(pnt, val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have copied the string\n", func_name); } return 0; } val = "footies"; memccpy(pnt, val, 'z', strlen(val)); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_MEMCHR static int do_memchr(void) { char *pnt, *val, *ret; char *func_name = "memchr"; pnt = malloc(5); val = "footy"; memmove(pnt, val, strlen(val)); ret = memchr(pnt, 't', strlen(val)); if (! check_ok(func_name)) { return 0; } if (*ret != 't') { if (! silent_b) { (void)printf(" ERROR: %s should have found the t\n", func_name); } return 0; } memchr(pnt, 'u', strlen(val) + 1); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_MEMCMP static int do_memcmp(void) { char *pnt, *val; char *func_name = "memcmp"; int ret; pnt = malloc(5); val = "12345"; memmove(pnt, val, strlen(val)); ret = memcmp(pnt, val, strlen(val)); if (! check_ok(func_name)) { return 0; } if (ret != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have gotten 0 got %d\n", func_name, ret); } return 0; } val = "123456"; memmove(pnt, val, strlen(val)); memcmp(pnt, val, 6); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_MEMCPY static int do_memcpy(void) { char *pnt, *val; char *func_name = "memcpy"; pnt = malloc(5); val = "12345"; memcpy(pnt, val, strlen(val)); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have copied the bytes\n", func_name); } return 0; } val = "123456"; memcpy(pnt, val, strlen(val)); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_MEMMOVE static int do_memmove(void) { char *pnt, *val; char *func_name = "memmove"; pnt = malloc(5); val = "12345"; memmove(pnt, val, strlen(val)); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have copied the bytes\n", func_name); } return 0; } val = "123456"; memmove(pnt, val, strlen(val)); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_MEMSET static int do_memset(void) { char *pnt; char *func_name = "memset"; char *zeros = "\000\000\000\000\000"; int size = 5; pnt = malloc(size); strcpy(pnt, "foo"); if (memcmp(pnt, zeros, size) == 0) { if (! silent_b) { (void)printf(" ERROR: %s pnt should not have zeros initially\n", func_name); } return 0; } memset(pnt, 0, size); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, zeros, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s pnt should have zeros\n", func_name); } return 0; } memset(pnt, 0, size + 1); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_RINDEX static int do_rindex(void) { char *pnt, *val, *ret; char *func_name = "rindex"; pnt = malloc(5); val = "foot"; strcpy(pnt, val); ret = index(pnt, *val); if (! check_ok(func_name)) { return 0; } if (ret != pnt) { if (! silent_b) { (void)printf(" ERROR: %s should have found the f\n", func_name); } return 0; } val = "footy"; memmove(pnt, val, strlen(val)); rindex(pnt, *val); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRCASECMP static int do_strcasecmp(void) { char *pnt, *val, *big_val; char *func_name = "strcasecmp"; int ret; pnt = malloc(5); val = "abcd"; big_val = "ABCD"; strcpy(pnt, big_val); ret = strcasecmp(pnt, val); if (! check_ok(func_name)) { return 0; } if (ret != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have gotten 0 got %d\n", func_name, ret); } return 0; } val = "abcdef"; big_val = "ABCDEF"; memmove(pnt, big_val, strlen(big_val)); strcasecmp(pnt, val); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRCAT static int do_strcat(void) { char *pnt, *val; char *func_name = "strcat"; pnt = malloc(5); val = "ab"; strcpy(pnt, val); strcat(pnt, val); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have copied string in\n", func_name); } return 0; } if (memcmp(pnt + strlen(val), val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have appending string\n", func_name); } return 0; } strcat(pnt, val); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRCHR static int do_strchr(void) { char *pnt, *val, *ret; char *func_name = "strchr"; pnt = malloc(5); val = "foot"; strcpy(pnt, val); ret = strchr(pnt, 't'); if (! check_ok(func_name)) { return 0; } if (*ret != 't') { if (! silent_b) { (void)printf(" ERROR: %s should have found the t\n", func_name); } return 0; } val = "footy"; memmove(pnt, val, strlen(val)); strchr(pnt, 'y'); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRCMP static int do_strcmp(void) { char *pnt, *val; char *func_name = "strcmp"; int ret; pnt = malloc(5); val = "foot"; strcpy(pnt, val); ret = strcmp(pnt, val); if (! check_ok(func_name)) { return 0; } if (ret != 0) { if (! silent_b) { (void)printf(" ERROR: %s strings should have been the same\n", func_name); } return 0; } val = "footy"; memmove(pnt, val, strlen(val)); strcmp(pnt, val); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRCPY static int do_strcpy(void) { char *pnt, *val; char *func_name = "strcpy"; pnt = malloc(5); val = "1234"; strcpy(pnt, val); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have copied the bytes\n", func_name); } return 0; } val = "12345"; strcpy(pnt, val); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRCSPN static int do_strcspn(void) { char *pnt, *val; char *func_name = "strcspn"; int ret; pnt = malloc(5); val = "1234"; ret = strcspn(pnt, val); if (! check_ok(func_name)) { return 0; } if (ret != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have found all chars\n", func_name); } return 0; } /* can't make this fail */ return 1; } #endif #if HAVE_STRLEN static int do_strlen(void) { char *pnt, *val; char *func_name = "strlen"; int ret; pnt = malloc(5); val = "1234"; strcpy(pnt, val); ret = strlen(pnt); if (! check_ok(func_name)) { return 0; } if (ret != _dmalloc_strlen(__FILE__, __LINE__, val)) { if (! silent_b) { (void)printf(" ERROR: %s got improper string length\n", func_name); } return 0; } val = "12345"; memmove(pnt, val, strlen(val)); strlen(pnt); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRNCASECMP static int do_strncasecmp(void) { char *pnt, *val, *big_val; char *func_name = "strncasecmp"; int ret; pnt = malloc(5); val = "abcde"; big_val = "ABCDE"; memmove(pnt, big_val, strlen(big_val)); ret = strncasecmp(pnt, val, strlen(val)); if (! check_ok(func_name)) { return 0; } if (ret != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have gotten 0 got %d\n", func_name, ret); } return 0; } big_val = "ABCDEF"; strncasecmp(pnt, big_val, strlen(big_val)); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRNCAT static int do_strncat(void) { char *pnt, *val; char *func_name = "strncat"; pnt = malloc(5); val = "ab"; strcpy(pnt, val); strncat(pnt, val, strlen(val)); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have copied string in\n", func_name); } return 0; } if (memcmp(pnt + strlen(val), val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have appending string\n", func_name); } return 0; } strncat(pnt, val, strlen(val)); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRNCMP static int do_strncmp(void) { char *pnt, *val; char *func_name = "strncmp"; int ret; pnt = malloc(5); val = "footy"; memmove(pnt, val, strlen(val)); ret = strncmp(pnt, val, strlen(val)); if (! check_ok(func_name)) { return 0; } if (ret != 0) { if (! silent_b) { (void)printf(" ERROR: %s strings should have been the same\n", func_name); } return 0; } strncmp(pnt, val, strlen(val) + 1); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRNCPY static int do_strncpy(void) { char *pnt, *val; char *func_name = "strncpy"; pnt = malloc(5); val = "12345"; strncpy(pnt, val, strlen(val)); if (! check_ok(func_name)) { return 0; } if (memcmp(pnt, val, strlen(val)) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have copied the bytes\n", func_name); } return 0; } val = "123456"; strncpy(pnt, val, strlen(val)); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRPBRK static int do_strpbrk(void) { char *pnt, *val, *ret; char *func_name = "strpbrk"; pnt = malloc(5); val = "foot"; strcpy(pnt, val); ret = strpbrk(pnt, "t"); if (! check_ok(func_name)) { return 0; } if (*ret != 't') { if (! silent_b) { (void)printf(" ERROR: %s should have found the t\n", func_name); } return 0; } val = "footy"; memmove(pnt, val, strlen(val)); strpbrk(pnt, "y"); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRRCHR static int do_strrchr(void) { char *pnt, *val, *ret; char *func_name = "rindex"; pnt = malloc(5); val = "foot"; strcpy(pnt, val); ret = strrchr(pnt, *val); if (! check_ok(func_name)) { return 0; } if (ret != pnt) { if (! silent_b) { (void)printf(" ERROR: %s should have found the f\n", func_name); } return 0; } val = "footy"; memmove(pnt, val, strlen(val)); strrchr(pnt, *val); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRSPN static int do_strspn(void) { char *pnt, *val; char *func_name = "strspn"; int ret; pnt = malloc(5); val = "foot"; strcpy(pnt, val); ret = strspn(pnt, val); if (! check_ok(func_name)) { return 0; } if (ret != strlen(val)) { if (! silent_b) { (void)printf(" ERROR: %s should have counted all chars\n", func_name); } return 0; } val = "footy"; memmove(pnt, val, strlen(val)); strspn(pnt, val); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRSTR static int do_strstr(void) { char *pnt, *val, *ret; char *func_name = "strstr"; pnt = malloc(5); val = "foot"; strcpy(pnt, val); ret = strstr(pnt, "ot"); if (! check_ok(func_name)) { return 0; } if (ret - pnt != 2) { if (! silent_b) { (void)printf(" ERROR: %s should have found the ot\n", func_name); } return 0; } val = "footy"; memmove(pnt, val, strlen(val)); strstr(pnt, "none"); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif #if HAVE_STRTOK static int do_strtok(void) { char *pnt, *val, *ret; char *func_name = "strtok"; pnt = malloc(5); val = "a,b,"; strcpy(pnt, val); ret = strtok(pnt, ","); if (! check_ok(func_name)) { return 0; } if (ret != pnt) { if (! silent_b) { (void)printf(" ERROR: %s first token should be start of pnt\n", func_name); } return 0; } val = "a,b,c"; memmove(pnt, val, strlen(val)); strtok(pnt, ","); return check_fail(func_name, ERROR_WOULD_OVERWRITE); } #endif static int (*test_funcs[])() = { #if HAVE_ATOI do_atoi, #endif #if HAVE_ATOL do_atol, #endif #if HAVE_BCMP do_bcmp, #endif #if HAVE_BCOPY do_bcopy, #endif #if HAVE_BZERO do_bzero, #endif #if HAVE_INDEX do_index, #endif #if HAVE_MEMCCPY do_memccpy, #endif #if HAVE_MEMCHR do_memchr, #endif #if HAVE_MEMCMP do_memcmp, #endif #if HAVE_MEMCPY do_memcpy, #endif #if HAVE_MEMMOVE do_memmove, #endif #if HAVE_MEMSET do_memset, #endif #if HAVE_RINDEX do_rindex, #endif #if HAVE_STRCASECMP do_strcasecmp, #endif #if HAVE_STRCAT do_strcat, #endif #if HAVE_STRCHR do_strchr, #endif #if HAVE_STRCMP do_strcmp, #endif #if HAVE_STRCPY do_strcpy, #endif #if HAVE_STRCSPN do_strcspn, #endif #if HAVE_STRLEN do_strlen, #endif #if HAVE_STRNCASECMP do_strncasecmp, #endif #if HAVE_STRNCAT do_strncat, #endif #if HAVE_STRNCMP do_strncmp, #endif #if HAVE_STRNCPY do_strncpy, #endif #if HAVE_STRPBRK do_strpbrk, #endif #if HAVE_STRRCHR do_strrchr, #endif #if HAVE_STRSPN do_strspn, #endif #if HAVE_STRSTR do_strstr, #endif #if HAVE_STRTOK do_strtok, #endif 0L, }; static int do_tests(void) { int final = 1, prev_errno, test_c; unsigned int old_flags; old_flags = dmalloc_debug_current(); dmalloc_debug(old_flags | DEBUG_CHECK_FUNCS); for (test_c = 0; test_funcs[test_c] != 0L; test_c++) { prev_errno = dmalloc_errno; dmalloc_errno = ERROR_NONE; final &= test_funcs[test_c](); if (prev_errno != ERROR_NONE) { dmalloc_errno = prev_errno; } } dmalloc_debug(old_flags); return final; } int main(int argc, char **argv) { int ret, final = 0; argv_process(arg_list, argc, argv); if (silent_b && verbose_b) { silent_b = ARGV_FALSE; } if (env_string != NULL) { dmalloc_debug_setup(env_string); if (! silent_b) { (void)printf("Set dmalloc environment to: %s\n", env_string); } } /* repeat until we get a non 0 seed */ while (seed_random == 0) { #ifdef HAVE_TIME #ifdef HAVE_GETPID seed_random = time(0) ^ getpid(); #else /* ! HAVE_GETPID */ seed_random = time(0) ^ 0xDEADBEEF; #endif /* ! HAVE_GETPID */ #else /* ! HAVE_TIME */ #ifdef HAVE_GETPID seed_random = getpid(); #else /* ! HAVE_GETPID */ /* okay, I give up */ seed_random = 0xDEADBEEF; #endif /* ! HAVE_GETPID */ #endif /* ! HAVE_TIME */ } _dmalloc_srand(seed_random); if (! silent_b) { (void)printf("Random seed is %u\n", seed_random); } dmalloc_message("random seed is %u\n", seed_random); /*************************************************/ if (! silent_b) { (void)printf("Running tests...\n"); } (void)fflush(stdout); if (do_tests()) { if (! silent_b) { (void)printf(" Succeeded.\n"); } } else { if (silent_b) { (void)printf("ERROR: Random tests failed. Last dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } else { (void)printf(" Failed. Last dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 1; } /*************************************************/ if (final != 0) { /* * Even if we are silent, we must give the random seed which is * the only way we can reproduce the problem. */ if (silent_b) { (void)printf("Random seed is %u. Final dmalloc error: %s (err %d)\n", seed_random, dmalloc_strerror(dmalloc_errno), dmalloc_errno); } else { (void)printf("Final dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } } argv_cleanup(arg_list); /* last thing is to verify the heap */ ret = dmalloc_verify(NULL /* check all heap */); if (ret != DMALLOC_NOERROR) { (void)printf("Final dmalloc_verify returned failure: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } /* you will need this if you can't auto-shutdown */ #if HAVE_ATEXIT == 0 && HAVE_ON_EXIT == 0 && FINI_DMALLOC == 0 /* shutdown the alloc routines */ dmalloc_shutdown(); #endif exit(final); } dmalloc-5.5.2/dmalloc_t.c000640 001751 001751 00000316325 10622115666 015223 0ustar00graygray000000 000000 /* * Test program for malloc code * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_t.c,v 1.129 2007/03/25 18:53:41 gray Exp $ */ /* * Test program for the malloc library. Current it is interactive although * should be script based. */ #include /* for stdin */ #if HAVE_STDLIB_H # include /* for atoi + */ #endif #if HAVE_STRING_H # include #endif #if HAVE_UNISTD_H # include #endif #include "conf.h" #include "compat.h" /* for loc_snprintf */ #if HAVE_TIME # ifdef TIME_INCLUDE # include TIME_INCLUDE # endif #endif #include "dmalloc.h" #include "dmalloc_argv.h" #include "dmalloc_rand.h" #include "arg_check.h" /* * NOTE: these are only needed to test certain features of the library. */ #include "debug_tok.h" #include "error_val.h" #include "heap.h" /* for external testing */ #define INTER_CHAR 'i' #define DEFAULT_ITERATIONS 10000 #define MAX_POINTERS 1024 #if HAVE_SBRK == 0 && HAVE_MMAP == 0 /* if we have a small memory area then just take 1/10 of the internal space */ #define MAX_ALLOC (INTERNAL_MEMORY_SPACE / 10) #else /* otherwise allocate a megabyte */ #define MAX_ALLOC (1024 * 1024) #endif #define MIN_AVAIL 10 /* pointer tracking structure */ typedef struct pnt_info_st { long pi_crc; /* crc of storage */ int pi_size; /* size of storage */ void *pi_pnt; /* pnt to storage */ struct pnt_info_st *pi_next; /* pnt to next */ } pnt_info_t; static pnt_info_t *pointer_grid; /* argument variables */ static long default_iter_n = DEFAULT_ITERATIONS; /* # of iters */ static char *env_string = NULL; /* env options */ static int interactive_b = ARGV_FALSE; /* interactive flag */ static int log_trans_b = ARGV_FALSE; /* log transactions */ static int no_special_b = ARGV_FALSE; /* no-special flag */ static long max_alloc = MAX_ALLOC; /* amt of mem to use */ static long max_pointers = MAX_POINTERS; /* # of pnts to use */ static int random_debug_b = ARGV_FALSE; /* random flag */ static int silent_b = ARGV_FALSE; /* silent flag */ static unsigned int seed_random = 0; /* random seed */ static int verbose_b = ARGV_FALSE; /* verbose flag */ static argv_t arg_list[] = { { INTER_CHAR, "interactive", ARGV_BOOL_INT, &interactive_b, NULL, "turn on interactive mode" }, { 'e', "env-string", ARGV_CHAR_P, &env_string, "string", "string of env commands to set" }, { 'l', "log-trans", ARGV_BOOL_INT, &log_trans_b, NULL, "log transactions via tracking-func" }, { 'm', "max-alloc", ARGV_SIZE, &max_alloc, "bytes", "maximum allocation to test" }, { 'n', "no-special", ARGV_BOOL_INT, &no_special_b, NULL, "do not run special tests" }, { 'p', "max-pointers", ARGV_SIZE, &max_pointers, "pointers", "number of pointers to test" }, { 'r', "random-debug", ARGV_BOOL_INT, &random_debug_b, NULL, "randomly change debug flag" }, { 's', "silent", ARGV_BOOL_INT, &silent_b, NULL, "do not display messages" }, { 'S', "seed-random", ARGV_U_INT, &seed_random, "number", "seed for random function" }, { 't', "times", ARGV_SIZE, &default_iter_n, "number", "number of iterations to run" }, { 'v', "verbose", ARGV_BOOL_INT, &verbose_b, NULL, "enables verbose messages" }, { ARGV_LAST } }; /* * Hexadecimal STR to integer translation */ static long hex_to_long(char *str) { long ret; /* strip off spaces */ for (; *str == ' ' || *str == '\t'; str++) { } /* skip a leading 0[xX] */ if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) { str += 2; } for (ret = 0;; str++) { if (*str >= '0' && *str <= '9') { ret = ret * 16 + (*str - '0'); } else if (*str >= 'a' && *str <= 'f') { ret = ret * 16 + (*str - 'a' + 10); } else if (*str >= 'A' && *str <= 'F') { ret = ret * 16 + (*str - 'A' + 10); } else { break; } } return ret; } /* * Read an address from the user */ static void *get_address(void) { char line[80]; void *pnt; do { (void)printf("Enter a hex address: "); if (fgets(line, sizeof(line), stdin) == NULL) { return NULL; } } while (line[0] == '\0'); pnt = (void *)hex_to_long(line); return pnt; } /* * Free a slot from the used_p list and put it on the free list */ static void free_slot(const int iter_c, pnt_info_t *slot_p, pnt_info_t **used_pp, pnt_info_t **free_pp) { pnt_info_t *this_p, *prev_p; if (verbose_b) { (void)printf("%d: free'd %d bytes from slot %d (%#lx)\n", iter_c + 1, slot_p->pi_size, slot_p - pointer_grid, (long)slot_p->pi_pnt); } slot_p->pi_pnt = NULL; /* find pnt in the used list */ for (this_p = *used_pp, prev_p = NULL; this_p != NULL; prev_p = this_p, this_p = this_p->pi_next) { if (this_p == slot_p) { break; } } if (prev_p == NULL) { *used_pp = slot_p->pi_next; } else { prev_p->pi_next = slot_p->pi_next; } slot_p->pi_next = *free_pp; *free_pp = slot_p; } /* * Try ITER_N random program iterations, returns 1 on success else 0 */ static int do_random(const int iter_n) { unsigned int old_flags = dmalloc_debug_current(); unsigned int flags; int iter_c, prev_errno, amount, max_avail, free_c; int final = 1; char *chunk_p; pnt_info_t *free_p, *used_p = NULL; pnt_info_t *pnt_p; max_avail = max_alloc; flags = dmalloc_debug_current(); pointer_grid = (pnt_info_t *)malloc(sizeof(pnt_info_t) * max_pointers); if (pointer_grid == NULL) { (void)printf("%s: problems allocating space for %ld pointer slots.\n", argv_program, max_pointers); return 0; } /* initialize free list */ free_p = pointer_grid; for (pnt_p = pointer_grid; pnt_p < pointer_grid + max_pointers; pnt_p++) { pnt_p->pi_size = 0; pnt_p->pi_pnt = NULL; pnt_p->pi_next = pnt_p + 1; } /* redo the last next pointer */ (pnt_p - 1)->pi_next = NULL; free_c = max_pointers; prev_errno = ERROR_NONE; for (iter_c = 0; iter_c < iter_n;) { int which_func, which; if (dmalloc_errno != prev_errno && ! silent_b) { (void)printf("ERROR: iter %d, %s (err %d)\n", iter_c, dmalloc_strerror(dmalloc_errno), dmalloc_errno); prev_errno = dmalloc_errno; final = 0; } /* special case when doing non-linear stuff, sbrk took all memory */ if (max_avail < MIN_AVAIL && free_p == NULL) { break; } if (random_debug_b) { unsigned int new_flag; which = _dmalloc_rand() % (sizeof(int) * 8); new_flag = 1 << which; flags ^= new_flag; if (verbose_b) { (void)printf("%d: debug flags = %#x\n", iter_c + 1, flags); } dmalloc_debug(flags); } /* decide whether to malloc a new pointer or free/realloc an existing */ which = _dmalloc_rand() % 4; if ((free_p == NULL || which == 3 || max_avail < MIN_AVAIL || free_c == max_pointers) && used_p != NULL) { /* choose a random slot to free */ which = _dmalloc_rand() % (max_pointers - free_c); for (pnt_p = used_p; which > 0; which--) { pnt_p = pnt_p->pi_next; } free(pnt_p->pi_pnt); free_slot(iter_c, pnt_p, &used_p, &free_p); free_c++; if (verbose_b) { (void)printf("%d: free'd %d bytes from slot %d (%#lx)\n", iter_c + 1, pnt_p->pi_size, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } max_avail += pnt_p->pi_size; iter_c++; continue; } /* sanity check */ if (free_p == NULL) { (void)fprintf(stderr, "%s: problem with test program free list\n", argv_program); exit(1); } /* rest are allocations */ amount = _dmalloc_rand() % (max_avail / 2); #if ALLOW_ALLOC_ZERO_SIZE == 0 if (amount == 0) { amount = 1; } #endif which_func = _dmalloc_rand() % 9; switch (which_func) { /* malloc */ case 0: pnt_p = free_p; pnt_p->pi_pnt = malloc(amount); if (verbose_b) { (void)printf("%d: malloc %d of max %d into slot %d. got %#lx\n", iter_c + 1, amount, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } break; /* calloc */ case 1: pnt_p = free_p; pnt_p->pi_pnt = calloc(amount, sizeof(char)); if (verbose_b) { (void)printf("%d: calloc %d of max %d into slot %d. got %#lx\n", iter_c + 1, amount, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } /* test the returned block to make sure that is has been cleared */ if (pnt_p->pi_pnt != NULL) { for (chunk_p = pnt_p->pi_pnt; chunk_p < (char *)pnt_p->pi_pnt + amount; chunk_p++) { if (*chunk_p != '\0') { if (! silent_b) { (void)printf("calloc of %d was not fully zeroed on iteration #%d\n", amount, iter_c + 1); } break; } } } break; /* realloc */ case 2: if (free_c == max_pointers) { continue; } which = _dmalloc_rand() % (max_pointers - free_c); for (pnt_p = used_p; which > 0; which--) { pnt_p = pnt_p->pi_next; } pnt_p->pi_pnt = realloc(pnt_p->pi_pnt, amount); /* * note that we've free the old size, we'll account for the * alloc below */ max_avail += pnt_p->pi_size; if (verbose_b) { (void)printf("%d: realloc %d from %d of max %d slot %d. got %#lx\n", iter_c + 1, amount, pnt_p->pi_size, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } if (amount == 0) { free_slot(iter_c, pnt_p, &used_p, &free_p); free_c++; pnt_p = NULL; continue; } break; /* recalloc */ case 3: if (free_c == max_pointers) { continue; } which = _dmalloc_rand() % (max_pointers - free_c); for (pnt_p = used_p; which > 0; which--) { pnt_p = pnt_p->pi_next; } pnt_p->pi_pnt = recalloc(pnt_p->pi_pnt, amount); /* * note that we've free the old size, we'll account for the * alloc below */ max_avail += pnt_p->pi_size; if (verbose_b) { (void)printf("%d: recalloc %d from %d of max %d slot %d. got %#lx\n", iter_c + 1, amount, pnt_p->pi_size, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } /* test the returned block to make sure that is has been cleared */ if (pnt_p->pi_pnt != NULL && amount > pnt_p->pi_size) { for (chunk_p = (char *)pnt_p->pi_pnt + pnt_p->pi_size; chunk_p < (char *)pnt_p->pi_pnt + amount; chunk_p++) { if (*chunk_p != '\0') { if (! silent_b) { (void)printf("recalloc %d from %d was not fully zeroed on iteration #%d\n", amount, pnt_p->pi_size, iter_c + 1); } break; } } } if (amount == 0) { free_slot(iter_c, pnt_p, &used_p, &free_p); free_c++; pnt_p = NULL; continue; } break; /* valloc */ case 4: pnt_p = free_p; pnt_p->pi_pnt = valloc(amount); if (verbose_b) { (void)printf("%d: valloc %d of max %d into slot %d. got %#lx\n", iter_c + 1, amount, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } break; /* sbrk */ case 5: /* do it less often then the other functions */ which = _dmalloc_rand() % 5; if (which == 3 && amount > 0) { void *mem; mem = _dmalloc_heap_alloc(amount); if (verbose_b) { (void)printf("%d: heap alloc %d of max %d bytes. got %#lx\n", iter_c + 1, amount, max_avail, (long)mem); } iter_c++; } /* don't store the memory */ continue; break; /* heap check in the middle */ case 6: /* do it less often then the other functions */ which = _dmalloc_rand() % 20; if (which == 7) { if (dmalloc_verify(NULL /* check all heap */) != DMALLOC_NOERROR) { if (! silent_b) { (void)printf("%d: ERROR dmalloc_verify failed\n", iter_c + 1); } final = 0; } iter_c++; } continue; break; #if HAVE_STRDUP /* strdup */ case 7: { char str[] = "this is a test of the emergency broadcasting system, the broadcasters in your area would like you to know that this system has really never been fully tested so we have no idea if it would actually work in the advent of a real disaster."; amount = _dmalloc_rand() % strlen(str); str[amount] = '\0'; pnt_p = free_p; pnt_p->pi_pnt = strdup(str); if (verbose_b) { /* the amount includes the \0 */ (void)printf("%d: strdup %d of max %d into slot %d. got %#lx\n", iter_c + 1, amount + 1, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } } break; #endif #if HAVE_STRNDUP /* strndup */ case 8: { char str[] = "this is a test of the emergency broadcasting system, the broadcasters in your area would like you to know that this system has really never been fully tested so we have no idea if it would actually work in the advent of a real disaster."; amount = _dmalloc_rand() % strlen(str); pnt_p = free_p; pnt_p->pi_pnt = strndup(str, amount); if (verbose_b) { (void)printf("%d: strdup %d of max %d into slot %d. got %#lx\n", iter_c + 1, amount, max_avail, pnt_p - pointer_grid, (long)pnt_p->pi_pnt); } } break; #endif default: continue; break; } if (pnt_p->pi_pnt == NULL) { if (! silent_b) { (void)printf("%d: ERROR allocation of %d returned error\n", iter_c + 1, amount); } final = 0; iter_c++; continue; } /* set the size and take it off the free-list and put on used list */ pnt_p->pi_size = amount; if (pnt_p == free_p) { free_p = pnt_p->pi_next; pnt_p->pi_next = used_p; used_p = pnt_p; free_c--; } max_avail -= amount; iter_c++; continue; } /* free used pointers */ for (pnt_p = pointer_grid; pnt_p < pointer_grid + max_pointers; pnt_p++) { if (pnt_p->pi_pnt != NULL) { free(pnt_p->pi_pnt); } } free(pointer_grid); dmalloc_debug(old_flags); return final; } /* * Do some special tests as soon as we run the test program. Returns * 1 on success else 0. */ static int check_initial_special(void) { void *pnt; int final = 1, iter_c; /********************/ do { int amount; /* * So I ran across a bad check for the seen value versus the * iteration count. It was only seen when there were a greater * number of reallocs to the same pointer at the start of the * program running. */ if (! silent_b) { (void)printf(" Checking realloc(malloc) seen count\n"); } do { /* NOTE: must be less than 1024 because below depends on this */ amount = _dmalloc_rand() % 10; } while (amount == 0); pnt = malloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; break; } for (iter_c = 0; iter_c < 100; iter_c++) { /* change the amount */ pnt = realloc(pnt, amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not reallocate %d bytes.\n", amount); } final = 0; break; } } if (pnt == NULL) { break; } /* * now try freeing the pointer with a free that provides a return * value */ if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: free of realloc(malloc) pointer %lx failed.\n", (unsigned long)pnt); } final = 0; } /* now check the heap to verify tha the freed slot is good */ if (dmalloc_verify(NULL /* check all heap */) != DMALLOC_NOERROR) { if (! silent_b) { (void)printf(" ERROR: dmalloc_verify failed\n"); } final = 0; } } while(0); /********************/ #define NEVER_REUSE_ITERS 20 { void *new_pnt, *pnts[NEVER_REUSE_ITERS]; unsigned int old_flags, amount, check_c; if (! silent_b) { (void)printf(" Checking never-reuse token\n"); } old_flags = dmalloc_debug_current(); dmalloc_debug(old_flags | DEBUG_NEVER_REUSE); for (iter_c = 0; iter_c < NEVER_REUSE_ITERS; iter_c++) { amount = 1024; pnts[iter_c] = malloc(amount); if (pnts[iter_c] == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; break; } } /* now free them */ for (iter_c = 0; iter_c < NEVER_REUSE_ITERS; iter_c++) { if (dmalloc_free(__FILE__, __LINE__, pnts[iter_c], DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: free of pointer %lx failed.\n", (unsigned long)pnts[iter_c]); } final = 0; } } /* * now allocate them again and make sure we don't get the same * pointers */ for (iter_c = 0; iter_c < NEVER_REUSE_ITERS; iter_c++) { amount = 1024; new_pnt = malloc(amount); if (new_pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; } /* did we get a previous pointer? */ for (check_c = 0; check_c < NEVER_REUSE_ITERS; check_c++) { if (new_pnt == pnts[check_c]) { if (! silent_b) { (void)printf(" ERROR: pointer %lx was improperly reused.\n", (unsigned long)new_pnt); } final = 0; break; } } if (dmalloc_free(__FILE__, __LINE__, new_pnt, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: free of pointer %lx failed.\n", (unsigned long)new_pnt); } final = 0; } } dmalloc_debug(old_flags); } /********************/ return final; } /* * Make sure that some of the arg check stuff works. */ static int check_arg_check(void) { unsigned int old_flags = dmalloc_debug_current(); char *func; int our_errno_hold = dmalloc_errno; int size, final = 1; char *pnt, *pnt2, hold_ch; if (! silent_b) { (void)printf(" Checking arg-check functions\n"); } /* * enable function checking and remove check-fence which caused * extra errors */ dmalloc_debug((old_flags | DEBUG_CHECK_FUNCS) & (~DEBUG_CHECK_FENCE)); size = 5; pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", size); } return 0; } pnt2 = malloc(size * 2); if (pnt2 == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", size * 2); } return 0; } /*********/ #if HAVE_ATOI func = "atoi"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "1234", size); if (_dmalloc_atoi(__FILE__, __LINE__, pnt) != 1234) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "12345", size); if (_dmalloc_atoi(__FILE__, __LINE__, pnt) != 12345) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_ATOL func = "atol"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "1234", size); if (_dmalloc_atol(__FILE__, __LINE__, pnt) != 1234) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "12345", size); if (_dmalloc_atol(__FILE__, __LINE__, pnt) != 12345) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_BCMP func = "bcmp"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memset(pnt, 1, size); memset(pnt2, 1, size); if (_dmalloc_bcmp(__FILE__, __LINE__, pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; memset(pnt, 1, size); memset(pnt2, 2, size); if (_dmalloc_bcmp(__FILE__, __LINE__, pnt, pnt2, size) == 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this should cause an error */ dmalloc_errno = ERROR_NONE; _dmalloc_bcmp(__FILE__, __LINE__, pnt, pnt2, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload did not register overwrite\n", func); } final = 0; } #endif /*********/ #if HAVE_BCOPY func = "bcopy"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this copies the right number of characters into buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 2, size); _dmalloc_bcopy(__FILE__, __LINE__, pnt, pnt2, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* check to see if it worked */ if (memcmp(pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } /* this copies too many characters into buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 2, size); _dmalloc_bcopy(__FILE__, __LINE__, pnt, pnt2, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_BZERO func = "bzero"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this copies enough characters into buffer */ dmalloc_errno = ERROR_NONE; _dmalloc_bzero(__FILE__, __LINE__, pnt, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this copies too many characters into buffer */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); _dmalloc_bzero(__FILE__, __LINE__, pnt, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_INDEX func = "index"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "1234", size); if (_dmalloc_index(__FILE__, __LINE__, pnt, '4') != pnt + 3) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); memcpy(pnt, "12345", size); if (_dmalloc_index(__FILE__, __LINE__, pnt, '5') != pnt + 4) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_MEMCCPY func = "memccpy"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this copies the right number of characters into buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 3, size); _dmalloc_memccpy(__FILE__, __LINE__, pnt2, pnt, 0, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this copies too many characters into buffer */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); _dmalloc_memccpy(__FILE__, __LINE__, pnt2, pnt, 0, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_MEMCHR func = "memchr"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this looks at the right number of characters in buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 4, size); if (_dmalloc_memchr(__FILE__, __LINE__, pnt, 0, size) != NULL) { if (! silent_b) { (void)printf(" ERROR: %s should have failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this looks at too many characters in buffer */ dmalloc_errno = ERROR_NONE; (void)_dmalloc_memchr(__FILE__, __LINE__, pnt, 0, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_MEMCMP func = "memcmp"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this checks the right number of characters in buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 5, size); memset(pnt2, 5, size); if (_dmalloc_memcmp(__FILE__, __LINE__, pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s should have passed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this checks too many characters from buffer */ dmalloc_errno = ERROR_NONE; (void)_dmalloc_memcmp(__FILE__, __LINE__, pnt, pnt2, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_MEMCPY func = "memcpy"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this copies enough characters into buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 6, size); _dmalloc_memcpy(__FILE__, __LINE__, pnt2, pnt, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } if (memcmp(pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } /* this copies too many characters into buffer */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); (void)_dmalloc_memcpy(__FILE__, __LINE__, pnt, pnt2, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_MEMMOVE func = "memmove"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this copies enough characters into buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 7, size); _dmalloc_memmove(__FILE__, __LINE__, pnt2, pnt, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } if (memcmp(pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } /* this copies too many characters into buffer */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); (void)_dmalloc_memmove(__FILE__, __LINE__, pnt, pnt2, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_MEMSET func = "memset"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this sets the right number of characters in buffer */ dmalloc_errno = ERROR_NONE; _dmalloc_memset(__FILE__, __LINE__, pnt, 0, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this sets too many characters in buffer */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); _dmalloc_memset(__FILE__, __LINE__, pnt, 0, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_RINDEX func = "rindex"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "1234", size); if (_dmalloc_rindex(__FILE__, __LINE__, pnt, '1') != pnt) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "12345", size); if (_dmalloc_rindex(__FILE__, __LINE__, pnt, '1') != pnt) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_STRCASECMP func = "strcasecmp"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "abcd", size); memcpy(pnt2, "ABCD", size); if (_dmalloc_strcasecmp(__FILE__, __LINE__, pnt, pnt2) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "abcde", size); memcpy(pnt2, "ABCDE", size); /* unknown results */ (void)_dmalloc_strcasecmp(__FILE__, __LINE__, pnt, pnt2); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_STRCAT func = "strcat"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "ab", 3); memcpy(pnt2, "cd", 3); if (_dmalloc_strcat(__FILE__, __LINE__, pnt, pnt2) != pnt) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "ab", 3); memcpy(pnt2, "abc", 4); hold_ch = *(pnt + size); if (_dmalloc_strcat(__FILE__, __LINE__, pnt, pnt2) != pnt) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_STRCHR func = "strchr"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "1234", size); if (_dmalloc_strchr(__FILE__, __LINE__, pnt, '4') != pnt + 3) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "12345", size); if (_dmalloc_strchr(__FILE__, __LINE__, pnt, '5') != pnt + 4) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_STRCMP func = "strcmp"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "abcd", size); memcpy(pnt2, "abcd", size); if (_dmalloc_strcmp(__FILE__, __LINE__, pnt, pnt2) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "abcde", size); memcpy(pnt2, "abcde", size); /* unknown results */ (void)_dmalloc_strcmp(__FILE__, __LINE__, pnt, pnt2); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_STRCPY func = "strcpy"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt2, "abcd", size); _dmalloc_strcpy(__FILE__, __LINE__, pnt, pnt2); if (memcmp(pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); memcpy(pnt2, "abcde", size + 1); _dmalloc_strcpy(__FILE__, __LINE__, pnt, pnt2); if (memcmp(pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_STRCSPN func = "strcspn"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* they should be the same */ dmalloc_errno = ERROR_NONE; memcpy(pnt, "abcd", size); if (_dmalloc_strcspn(__FILE__, __LINE__, pnt, ".") != 4) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* they should be different */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); memcpy(pnt, "abcde", size); /* unknown results */ (void)_dmalloc_strcspn(__FILE__, __LINE__, pnt, "."); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_STRDUP #ifdef DMALLOC_STRDUP_MACRO func = "strdup"; if (! silent_b) { (void)printf(" Checking %s\n", func); } { char *new_pnt; /* this copies characters into buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 3, size); memset(pnt + size - 1, 0, 1); new_pnt = strdup(pnt); if (new_pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this looks at too many characters from buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 3, size); new_pnt = strdup(pnt); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } } #endif #endif /*********/ #if HAVE_STRNCASECMP func = "strncasecmp"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this compares enough characters from buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 'a', size); memset(pnt2, 'A', size); if (_dmalloc_strncasecmp(__FILE__, __LINE__, pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this compares too many characters from buffer */ dmalloc_errno = ERROR_NONE; (void)_dmalloc_strncasecmp(__FILE__, __LINE__, pnt, pnt2, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_STRNCAT func = "strncat"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this copies enough characters into buffer */ dmalloc_errno = ERROR_NONE; /* sanity check */ if (size <= 2) { abort(); } memset(pnt, 8, size); /* remove 2 chars from end of pnt to fit 1 from pnt2 and \0 */ pnt[size - 2] = '\0'; memset(pnt2, 8, size); pnt2[1] = '\0'; _dmalloc_strncat(__FILE__, __LINE__, pnt, pnt2, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this copies too many characters into buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 8, size); /* now just remove one so the \0 would overwrite */ pnt[size - 1] = '\0'; hold_ch = *(pnt + size); _dmalloc_strncat(__FILE__, __LINE__, pnt, pnt2, size); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_STRNCMP func = "strncat"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this compares too many characters from buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 9, size); memset(pnt2, 9, size); if (_dmalloc_strncmp(__FILE__, __LINE__, pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } /* this compares too many characters from buffer */ dmalloc_errno = ERROR_NONE; (void)_dmalloc_strncmp(__FILE__, __LINE__, pnt, pnt2, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } #endif /*********/ #if HAVE_STRNCPY func = "strncpy"; if (! silent_b) { (void)printf(" Checking %s\n", func); } /* this looks at enough characters into buffer */ dmalloc_errno = ERROR_NONE; memset(pnt, 9, size); _dmalloc_strncpy(__FILE__, __LINE__, pnt, pnt2, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } if (memcmp(pnt, pnt2, size) != 0) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } /* this copies too many characters into buffer */ dmalloc_errno = ERROR_NONE; hold_ch = *(pnt + size); _dmalloc_strncpy(__FILE__, __LINE__, pnt, pnt2, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: %s overload should get error\n", func); } final = 0; } *(pnt + size) = hold_ch; #endif /*********/ #if HAVE_STRNDUP func = "strndup"; if (! silent_b) { (void)printf(" Checking %s\n", func); } { void *new_pnt; /* this looks at enough characters in buffer */ dmalloc_errno = ERROR_NONE; new_pnt = strndup(pnt, size); if (new_pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: %s overload failed\n", func); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } free(new_pnt); dmalloc_errno = ERROR_NONE; memset(pnt, 1, size); new_pnt = strndup(pnt, size + 1); if (new_pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: strndup failed\n"); } final = 0; } if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: %s overload should not get error\n", func); } final = 0; } free(new_pnt); } #endif /*********/ free(pnt); free(pnt2); /* restore flags */ dmalloc_debug(old_flags); dmalloc_errno = our_errno_hold; return final; } /* * Do some special tests, returns 1 on success else 0 */ static int check_special(void) { void *pnt; int page_size; int final = 1; /* get our page size */ page_size = dmalloc_page_size(); dmalloc_message("-------------------------------------------------------\n"); dmalloc_message("NOTE: ignore any errors until the next ------\n"); /********************/ /* * Check to make sure that we are handling free(0L) correctly. */ { int errno_hold = dmalloc_errno; if (! silent_b) { (void)printf(" Trying to free 0L pointer.\n"); } free(NULL); #if ALLOW_FREE_NULL if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: free of 0L returned error.\n"); } final = 0; } #else if (dmalloc_errno == ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: free of 0L did not return error.\n"); } final = 0; } #endif /* now test the dmalloc_free function */ if (dmalloc_free(__FILE__, __LINE__, NULL, DMALLOC_FUNC_FREE) != FREE_ERROR) { if (! silent_b) { (void)printf(" ERROR: free of NULL should have failed.\n"); } final = 0; } dmalloc_errno = errno_hold; } /********************/ /* * Check to make sure that large mallocs are handled correctly. */ #if LARGEST_ALLOCATION { int errno_hold = dmalloc_errno; if (! silent_b) { (void)printf(" Allocating a block of too-many bytes.\n"); } pnt = malloc(LARGEST_ALLOCATION + 1); if (pnt == NULL) { dmalloc_errno = ERROR_NONE; } else { if (! silent_b) { (void)printf(" ERROR: allocation of > largest allowed size did not return error.\n"); } free(pnt); final = 0; } dmalloc_errno = errno_hold; } #endif /********************/ /* * Check to see if overwritten freed memory is detected. */ if (dmalloc_verify(NULL /* check all heap */) == DMALLOC_NOERROR) { int iter_c, amount, where; int errno_hold = dmalloc_errno; unsigned int old_flags = dmalloc_debug_current(); unsigned char ch_hold; dmalloc_debug(old_flags | DEBUG_FREE_BLANK); if (! silent_b) { (void)printf(" Overwriting free memory.\n"); } for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = malloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; continue; } free(pnt); /* find out where overwrite inside of the pointer */ where = _dmalloc_rand() % amount; ch_hold = *((char *)pnt + where); *((char *)pnt + where) = 'h'; /* now verify that the pnt and the whole heap register errors */ dmalloc_errno = ERROR_NONE; if (dmalloc_verify(pnt) == DMALLOC_NOERROR || dmalloc_verify(NULL /* check all heap */) == DMALLOC_NOERROR) { if (! silent_b) { (void)printf(" ERROR: overwriting free memory not detected.\n"); } final = 0; } else if (dmalloc_errno == ERROR_FREE_OVERWRITTEN) { } else { if (! silent_b) { (void)printf(" ERROR: verify of overwritten memory returned: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } *((char *)pnt + where) = ch_hold; } dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * Check to see if the space above an allocated pnt is detected. */ { int iter_c, amount, where; int errno_hold = dmalloc_errno; unsigned int old_flags; DMALLOC_SIZE tot_size; unsigned char ch_hold; old_flags = dmalloc_debug_current(); /* sure on free-blank on and check-fence off */ dmalloc_debug((old_flags | DEBUG_ALLOC_BLANK) & (~DEBUG_CHECK_FENCE)); if (! silent_b) { (void)printf(" Overwriting memory above allocation.\n"); } for (iter_c = 0; iter_c < 20; /* iter_c ++ below */) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = malloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; continue; } /* * check out the pointer now to make sure that we have some * space above the pointer */ if (dmalloc_examine(pnt, NULL /* now user size */, &tot_size, NULL /* no file */, NULL /* no line */, NULL /* no return address */, NULL /* no mark */, NULL /* no seen */) != DMALLOC_NOERROR) { if (! silent_b) { (void)printf(" ERROR: examining pointer %lx failed.\n", (unsigned long)pnt); } final = 0; break; } if (tot_size == amount) { /* we need some space to overwrite */ free(pnt); continue; } /* now we can increment */ iter_c++; /* where to overwrite is then a random from 0 to the remainder-1 */ where = _dmalloc_rand() % (tot_size - amount); ch_hold = *((char *)pnt + amount + where); *((char *)pnt + amount + where) = 'h'; /* now verify that the pnt and the whole heap register errors */ dmalloc_errno = ERROR_NONE; if (dmalloc_verify(pnt) == DMALLOC_NOERROR || dmalloc_verify(NULL /* check all heap */) == DMALLOC_NOERROR) { if (! silent_b) { (void)printf(" ERROR: overwriting above allocated memory not detected.\n"); } final = 0; } else if (dmalloc_errno == ERROR_FREE_OVERWRITTEN) { } else { if (! silent_b) { (void)printf(" ERROR: verify of overwritten above allocated memory returned: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } *((char *)pnt + amount + where) = ch_hold; free(pnt); } dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * See if we can free invalid pointers and get the appropriate errors */ { int errno_hold = dmalloc_errno; int iter_c, amount, wrong; if (! silent_b) { (void)printf(" Freeing invalid pointers\n"); } for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = malloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; continue; } wrong = _dmalloc_rand() % amount; if (wrong == 0) { wrong = 1; } if (dmalloc_free(__FILE__, __LINE__, (char *)pnt + wrong, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (dmalloc_errno == ERROR_NOT_START_BLOCK) { } else { if (! silent_b) { (void)printf(" ERROR: free bad pointer produced: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } } else { if (! silent_b) { (void)printf(" ERROR: no problem freeing bad pointer.\n"); } final = 0; } free(pnt); } dmalloc_errno = errno_hold; } /********************/ /* * Saw a number of problems where the used_iter value was not being * set and the proper flags were not being set on the slots. */ { char *loc_file, *ex_file; void *new_pnt; int errno_hold = dmalloc_errno; unsigned int amount, loc_line, ex_line, old_flags; unsigned long loc_mark, ex_mark, old_seen, ex_seen; DMALLOC_SIZE ex_user_size, ex_tot_size; int iter_c; if (! silent_b) { (void)printf(" Checking dmalloc_examine information\n"); } old_flags = dmalloc_debug_current(); /* * We have to turn off the realloc-copy and new-reuse flags * otherwise this won't work. */ dmalloc_debug(old_flags & ~DEBUG_REALLOC_COPY & ~DEBUG_NEVER_REUSE); for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); /* we need 2 because we are doing a 2-1 below */ } while (amount < 2); pnt = malloc(amount); loc_file = __FILE__; loc_line = __LINE__; if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; continue; } /* record the mark */ loc_mark = dmalloc_mark(); /* check out the pointer */ if (dmalloc_examine(pnt, &ex_user_size, &ex_tot_size, &ex_file, &ex_line, NULL /* no return address */, &ex_mark, &ex_seen) != DMALLOC_NOERROR) { if (! silent_b) { (void)printf(" ERROR: examining pointer %lx failed.\n", (unsigned long)pnt); } final = 0; } else if (ex_user_size != amount || ex_file == NULL || strcmp(ex_file, loc_file) != 0 || ex_line != loc_line || ex_mark <= 0 || ex_mark != loc_mark || ex_tot_size < ex_user_size #if LOG_PNT_SEEN_COUNT || ex_seen < 1 #endif ) { if (! silent_b) { (void)printf(" ERROR: examined pointer info invalid.\n"); } final = 0; } old_seen = ex_seen; /* * Now realloc the pointer again and make sure that the mark and * the seen increment by 1. We decrement instead of * incrementing because the library will never reposition an * allocation if shrinking. */ new_pnt = realloc(pnt, amount - 1); if (new_pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not reallocate %d bytes.\n", amount + 1); } final = 0; continue; } /* should always get a new pointer */ if (new_pnt != pnt) { if (! silent_b) { (void)printf(" ERROR: could not reallocate %d bytes.\n", amount + 1); } final = 0; continue; } /* check out the pointer */ if (dmalloc_examine(pnt, &ex_user_size, NULL, NULL, NULL, NULL, &ex_mark, &ex_seen) != DMALLOC_NOERROR) { if (! silent_b) { (void)printf(" ERROR: examining pointer %lx failed.\n", (unsigned long)pnt); } final = 0; } else if (ex_user_size != amount - 1 /* +2 on the mark because of the examine */ || ex_mark != loc_mark + 2 #if LOG_PNT_SEEN_COUNT /* +2 on seen because realloc counts it in and out */ || ex_seen != old_seen + 2 #endif ) { if (! silent_b) { (void)printf(" ERROR: examined realloced pointer info invalid.\n"); } final = 0; } free(pnt); /* this should fail now that we freed the pointer */ if (dmalloc_examine(pnt, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != DMALLOC_ERROR) { if (! silent_b) { (void)printf(" ERROR: examining freed pointer %lx did not fail.\n", (unsigned long)pnt); } final = 0; } } dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * Make sure that the start file:line works. */ { unsigned int old_flags = dmalloc_debug_current(); int errno_hold = dmalloc_errno; char *loc_file, save_ch; int iter_c, loc_line; void *pnts[2]; char setup[128]; /* turn on fence post checking */ dmalloc_debug(DEBUG_CHECK_FENCE); dmalloc_errno = ERROR_NONE; if (! silent_b) { (void)printf(" Checking heap check start at file:line\n"); } #define BUF_SIZE 64 /* make an allocation */ pnts[0] = malloc(BUF_SIZE); if (pnts[0] == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* save the character but then overwrite the high fence post */ save_ch = *((char *)pnts[0] + BUF_SIZE); *((char *)pnts[0] + BUF_SIZE) = '\0'; /* make another allocation */ pnts[1] = malloc(BUF_SIZE); if (pnts[1] == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* it shouldn't generate an error */ if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: should not have gotten an error with no heap checking enabled.\n"); } return 0; } /* restore the overwritten character otherwise we can't free pointer */ *((char *)pnts[0] + BUF_SIZE) = save_ch; free(pnts[0]); free(pnts[1]); for (iter_c = 0; iter_c < 2; iter_c++) { /* * we have to do this loop hack here because we need to know the * __FILE__ and __LINE__ of a certain location to set the * variable so then we need to run it again. */ /* * Make an allocation recording where we did it. * * NOTE: This all needs to be on the same line. */ loc_file= __FILE__; loc_line = __LINE__; pnts[iter_c] = malloc(BUF_SIZE); if (pnts[iter_c] == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* first time through the loop? */ if (iter_c == 0) { /* save the character and then overwrite the high fence post */ save_ch = *((char *)pnts[0] + BUF_SIZE); *((char *)pnts[0] + BUF_SIZE) = '\0'; /* * build and enable an options string turning on checking at * the above allocation */ (void)loc_snprintf(setup, sizeof(setup), "debug=%#x,start=%s:%d", DEBUG_CHECK_FENCE, loc_file, loc_line); dmalloc_debug_setup(setup); continue; } /* * now the 2nd time through the loop we should have seen an * error because heap checking should have been enabled at the * 2nd allocation so the heap should have been checked and the * problem with the 1st allocation detected. */ if (dmalloc_errno != ERROR_OVER_FENCE) { if (! silent_b) { (void)printf(" ERROR: should have gotten over fence-post error after checking started.\n"); } return 0; } /* * restore the overwritten character otherwise we can't free * the pointer */ *((char *)pnts[0] + BUF_SIZE) = save_ch; } free(pnts[0]); free(pnts[1]); /* reset the debug flags and errno */ dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * Make sure that the start iteration count works. */ { unsigned int old_flags = dmalloc_debug_current(); int errno_hold = dmalloc_errno; char save_ch; void *pnt2; char setup[128]; /* turn on fence post checking */ dmalloc_debug(DEBUG_CHECK_FENCE); dmalloc_errno = ERROR_NONE; if (! silent_b) { (void)printf(" Checking heap check start at iteration count\n"); } #define BUF_SIZE 64 /* make an allocation */ pnt = malloc(BUF_SIZE); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* overwrite the high fence post */ save_ch = *((char *)pnt + BUF_SIZE); *((char *)pnt + BUF_SIZE) = '\0'; /* make another allocation */ pnt2 = malloc(BUF_SIZE); if (pnt2 == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* it shouldn't generate an error */ if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: should not have gotten an error with no heap checking enabled.\n"); } return 0; } /* free the 2nd pointer */ free(pnt2); /* * build and enable an options string turning on checking at the * next transaction */ (void)loc_snprintf(setup, sizeof(setup), "debug=%#x,start=c1", DEBUG_CHECK_FENCE); dmalloc_debug_setup(setup); /* * make another allocation which should enable heap checking and * notice the above pointer overwrite */ pnt2 = malloc(BUF_SIZE); if (pnt2 == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* now we should see the error */ if (dmalloc_errno != ERROR_OVER_FENCE) { if (! silent_b) { (void)printf(" ERROR: should have gotten over fence-post error after checking started.\n"); } return 0; } /* restore the overwritten character otherwise we can't free the pointer */ *((char *)pnt + BUF_SIZE) = save_ch; free(pnt); free(pnt2); /* reset the debug flags and errno */ dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * Make sure that the start after memory size allocated. */ { unsigned int old_flags = dmalloc_debug_current(); int errno_hold = dmalloc_errno; char save_ch; void *pnt2; char setup[128]; /* turn on fence post checking */ dmalloc_debug(DEBUG_CHECK_FENCE); dmalloc_errno = ERROR_NONE; if (! silent_b) { (void)printf(" Checking heap check start at memory size\n"); } #define BUF_SIZE 64 /* make an allocation */ pnt = malloc(BUF_SIZE); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* overwrite the high fence post */ save_ch = *((char *)pnt + BUF_SIZE); *((char *)pnt + BUF_SIZE) = '\0'; /* make another allocation */ pnt2 = malloc(BUF_SIZE); if (pnt2 == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* it shouldn't generate an error */ if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: should not have gotten an error with no heap checking enabled.\n"); } return 0; } free(pnt2); /* * build and enable an options string turning on checking at the * next transaction */ (void)loc_snprintf(setup, sizeof(setup), "debug=%#x,start=s%lu", DEBUG_CHECK_FENCE, dmalloc_memory_allocated()); dmalloc_debug_setup(setup); /* * make another allocation which should enable heap checking and * notice the above pointer overwrite */ pnt2 = malloc(BUF_SIZE); if (pnt2 == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } /* now we should see the error */ if (dmalloc_errno != ERROR_OVER_FENCE) { if (! silent_b) { (void)printf(" ERROR: should have gotten over fence-post error after checking started.\n"); } return 0; } /* restore the overwritten character otherwise we can't free the pointer */ *((char *)pnt + BUF_SIZE) = save_ch; free(pnt); free(pnt2); /* reset the debug flags and errno */ dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * Make sure per-pointer blanking flags work. */ { int errno_hold = dmalloc_errno; unsigned long size; unsigned int old_flags = dmalloc_debug_current(); char save_ch; if (! silent_b) { (void)printf(" Checking per-pointer blanking flags\n"); } /* disable alloc and check blanking */ dmalloc_debug(old_flags & (~(DEBUG_ALLOC_BLANK | DEBUG_CHECK_BLANK))); /* allocate a pointer */ size = _dmalloc_rand() % MAX_ALLOC + 10; pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %lu bytes.\n", size); } return 0; } /* now enable alloc and check blanking */ dmalloc_debug(old_flags | DEBUG_ALLOC_BLANK | DEBUG_CHECK_BLANK); if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: per-pointer blanking flags failed: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } /********/ /* now, enable alloc and check blanking */ dmalloc_debug((old_flags | DEBUG_ALLOC_BLANK | DEBUG_CHECK_BLANK) & (~DEBUG_CHECK_FENCE)); /* allocate a pointer */ size = BLOCK_SIZE / 2 + 1; pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %lu bytes.\n", size); } return 0; } /* now disable alloc blanking */ dmalloc_debug(old_flags | DEBUG_CHECK_BLANK); /* overwrite one of the top chars */ save_ch = *((char *)pnt + size); *((char *)pnt + size) = '\0'; /* free the pointer should still see the error */ if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) == FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: per-pointer blanking flags should have failed: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } /* restore the overwrite */ *((char *)pnt + size) = save_ch; /* restore flags */ dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * Make sure that a pointer reallocating, get's the per-pointer * alloc flags enabled. */ { int errno_hold = dmalloc_errno; unsigned long size; unsigned int old_flags = dmalloc_debug_current(); char save_ch; if (! silent_b) { (void)printf(" Checking per-pointer alloc flags and realloc\n"); } /* enable alloc blanking without fence-posts */ dmalloc_debug((old_flags | DEBUG_ALLOC_BLANK | DEBUG_FREE_BLANK) & (~(DEBUG_CHECK_FENCE | DEBUG_CHECK_BLANK))); /* allocate a pointer that should fill the block */ size = BLOCK_SIZE; pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %lu bytes.\n", size); } return 0; } /* now disable all checking */ dmalloc_debug((old_flags | DEBUG_CHECK_BLANK) & (~(DEBUG_CHECK_FENCE | DEBUG_ALLOC_BLANK | DEBUG_FREE_BLANK))); pnt = realloc(pnt, size - 1); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not realloc %#lx to %lu bytes.\n", (long)pnt, size - 1); } return 0; } /* overwrite one of the top chars */ save_ch = *((char *)pnt + size - 1); *((char *)pnt + size - 1) = '\0'; /* we should notice the overwrite */ if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) == FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: per-pointer alloc flags should have failed: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } /* restore the overwrite */ *((char *)pnt + size - 1) = save_ch; /* restore flags */ dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * Make sure that a free of an existing pointer gets the right error. */ { int errno_hold = dmalloc_errno; int size = 10; if (! silent_b) { (void)printf(" Checking double free error\n"); } pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", size); } return 0; } if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: 1st of double free should not fail: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } dmalloc_errno = ERROR_NONE; if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) == FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: 2nd of double free should have failed: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } else if (dmalloc_errno != ERROR_ALREADY_FREE) { if (! silent_b) { (void)printf(" ERROR: 2nd of double free should get ERROR_ALREADY_FREE not: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } dmalloc_errno = errno_hold; } /********************/ /* * Coverage tests */ #if FREED_POINTER_DELAY > 0 { int errno_hold = dmalloc_errno; int size = 10, pnt_c; if (! silent_b) { (void)printf(" Checking freed pointer delay\n"); } pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", size); } return 0; } for (pnt_c = 0; pnt_c < FREED_POINTER_DELAY; pnt_c++) { void *pnt2 = malloc(size); if (pnt2 == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", size); } return 0; } free(pnt2); } /* now double free the first one */ dmalloc_errno = ERROR_NONE; if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: 1st of double free should not fail: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) == FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: 2nd of double free should have failed: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } else if (dmalloc_errno != ERROR_ALREADY_FREE) { if (! silent_b) { (void)printf(" ERROR: 2nd of double free should get ERROR_ALREADY_FREE not: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } dmalloc_errno = errno_hold; } #endif /********************/ /* * Test strndup. */ { int errno_hold = dmalloc_errno; int size = 5; char *str, *ret; unsigned int old_flags = dmalloc_debug_current(); if (! silent_b) { (void)printf(" Checking strndup\n"); } dmalloc_debug(old_flags | DEBUG_CHECK_FUNCS); pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", size); } return 0; } str = "1234"; memmove(pnt, str, size); dmalloc_errno = ERROR_NONE; ret = strndup(pnt, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: strndup shouldn't produce error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } else if (strcmp(pnt, str) != 0) { if (! silent_b) { (void)printf(" ERROR: strndup should have copied string\n"); } final = 0; } dmalloc_errno = ERROR_NONE; ret = strndup(pnt, size + 1); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: strndup shouldn't produce error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } else if (strcmp(pnt, str) != 0) { if (! silent_b) { (void)printf(" ERROR: strndup should have copied string\n"); } final = 0; } str = "12345"; memmove(pnt, str, size); dmalloc_errno = ERROR_NONE; strndup(pnt, size); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: strndup shouldn't produce error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } else if (strcmp(pnt, str) != 0) { if (! silent_b) { (void)printf(" ERROR: strndup should have copied string\n"); } final = 0; } dmalloc_errno = ERROR_NONE; strndup(pnt, size + 1); if (dmalloc_errno != ERROR_WOULD_OVERWRITE) { if (! silent_b) { (void)printf(" ERROR: strndup should produce overwrite error not: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* check all of the arg check routines */ if (! check_arg_check()) { final = 0; } /********************/ dmalloc_message("NOTE: ignore the errors from the above ----- to here.\n"); dmalloc_message("-------------------------------------------------------\n"); /* * The following errors whould not generate a dmalloc_errno nor any * error messages */ /********************/ /* * Make sure that realloc of NULL pointers either works or doesn't * depending on the proper ALLOW_REALLOC_NULL setting. */ { if (! silent_b) { (void)printf(" Trying to realloc a 0L pointer.\n"); } pnt = realloc(NULL, 10); #if ALLOW_REALLOC_NULL if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: re-allocation of 0L returned error.\n"); } final = 0; } else { free(pnt); } #else if (pnt == NULL) { dmalloc_errno = ERROR_NONE; } else { if (! silent_b) { (void)printf(" ERROR: re-allocation of 0L did not return error.\n"); } free(pnt); final = 0; } #endif } /********************/ /* * Make sure that valloc returns properly page-aligned memory. */ { int iter_c, amount; unsigned int old_flags = dmalloc_debug_current(); if (! silent_b) { (void)printf(" Testing valloc()\n"); } /* * First check without frence posts */ dmalloc_debug(old_flags & ~DEBUG_CHECK_FENCE); for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = valloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not valloc %d bytes.\n", amount); } final = 0; continue; } if ((unsigned long)pnt % page_size != 0) { if (! silent_b) { (void)printf(" ERROR: valloc got %lx which is not page aligned.\n", (unsigned long)pnt); } final = 0; } free(pnt); } /* * Now test with fence posts enabled */ dmalloc_debug(old_flags | DEBUG_CHECK_FENCE); for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = valloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not valloc %d bytes.\n", amount); } final = 0; continue; } if ((unsigned long)pnt % page_size != 0) { if (! silent_b) { (void)printf(" ERROR: valloc got %lx which is not page aligned.\n", (unsigned long)pnt); } final = 0; } free(pnt); } dmalloc_debug(old_flags); } /********************/ /* * Make sure that the blanking flags actually blank all of the * allocated pointer space. */ { char *alloc_p; unsigned int old_flags, iter_c, amount; if (! silent_b) { (void)printf(" Checking alloc blanking\n"); } old_flags = dmalloc_debug_current(); /* turn on alloc blanking without fence posts */ dmalloc_debug((old_flags | DEBUG_ALLOC_BLANK) & (~DEBUG_CHECK_FENCE)); for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = malloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; continue; } for (alloc_p = pnt; alloc_p < (char *)pnt + amount; alloc_p++) { if (*alloc_p != ALLOC_BLANK_CHAR) { if (! silent_b) { (void)printf(" ERROR: allocation not fully blanked.\n"); } final = 0; } } free(pnt); } /* * Now test with fence posts enabled */ dmalloc_debug(old_flags | DEBUG_CHECK_FENCE); for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = valloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not valloc %d bytes.\n", amount); } final = 0; continue; } if ((unsigned long)pnt % page_size != 0) { if (! silent_b) { (void)printf(" ERROR: valloc got %lx which is not page aligned.\n", (unsigned long)pnt); } final = 0; } free(pnt); } dmalloc_debug(old_flags); } /********************/ /* * Make sure realloc copy works right. */ { void *new_pnt; unsigned int amount, old_flags; int iter_c; if (! silent_b) { (void)printf(" Checking realloc_copy token\n"); } old_flags = dmalloc_debug_current(); dmalloc_debug(old_flags | DEBUG_REALLOC_COPY); for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = malloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; continue; } /* we should get the same pointer */ new_pnt = realloc(pnt, amount); if (new_pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not reallocate %d bytes.\n", amount + 10); } final = 0; continue; } if (new_pnt == pnt) { if (! silent_b) { (void)printf(" ERROR: realloc produced same pointer.\n"); } final = 0; continue; } if (dmalloc_free(__FILE__, __LINE__, new_pnt, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: free bad pointer produced: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } } dmalloc_debug(old_flags); } /********************/ /* * Make sure realloc copy works right. */ { void *new_pnt; unsigned int amount, old_flags; int iter_c; if (! silent_b) { (void)printf(" Checking never-reuse token\n"); } old_flags = dmalloc_debug_current(); dmalloc_debug(old_flags | DEBUG_NEVER_REUSE); for (iter_c = 0; iter_c < 20; iter_c++) { do { amount = _dmalloc_rand() % (page_size * 3); } while (amount == 0); pnt = malloc(amount); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not allocate %d bytes.\n", amount); } final = 0; continue; } /* we should get the same pointer */ new_pnt = realloc(pnt, amount); if (new_pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not reallocate %d bytes.\n", amount + 10); } final = 0; continue; } if (new_pnt == pnt) { if (! silent_b) { (void)printf(" ERROR: realloc produced same pointer.\n"); } final = 0; continue; } if (dmalloc_free(__FILE__, __LINE__, new_pnt, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: free bad pointer produced: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } } dmalloc_debug(old_flags); } /********************/ /* * Make sure that the dmalloc function checking allows external * pointers. */ { int errno_hold = dmalloc_errno; unsigned int old_flags; char buf[20]; if (! silent_b) { (void)printf(" Checking function checking of non-heap pointers\n"); } old_flags = dmalloc_debug_current(); dmalloc_debug(old_flags | DEBUG_CHECK_FUNCS); dmalloc_errno = ERROR_NONE; _dmalloc_memset(__FILE__, __LINE__, buf, 0, sizeof(buf)); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: dmalloc_memset of non-heap pointer failed: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } dmalloc_debug(old_flags); dmalloc_errno = errno_hold; } /********************/ /* * Make sure that string tokens work in the processing program. */ { unsigned int old_flags, new_flags; if (! silent_b) { (void)printf(" Checking string tokens in dmalloc_debug_setup\n"); } old_flags = dmalloc_debug_current(); dmalloc_debug(0); dmalloc_debug_setup("log-stats,log-non-free,log-bad-space"); new_flags = dmalloc_debug_current(); if (! (new_flags & DEBUG_LOG_STATS && new_flags & DEBUG_LOG_NONFREE && new_flags & DEBUG_LOG_BAD_SPACE)) { if (! silent_b) { (void)printf(" ERROR: dmalloc_debug_setup didn't process comma separated tokens.\n"); } final = 0; } dmalloc_debug(old_flags); } /********************/ /* * Make sure that the calloc macro is valid. */ { DMALLOC_SIZE user_size; if (! silent_b) { (void)printf(" Checking calloc macro arguments\n"); } /* notice that we do not have a () around this operation */ #define SIZE_ARG 10 + 1 #define COUNT_ARG 2 /* * Initially I was not putting parens around macro arguments in * dmalloc.h. Rookie mistake. This should allocate (10 + 1) * 2 * bytes (22) not 10 + 1 * 2 bytes (12). */ pnt = calloc(SIZE_ARG, COUNT_ARG); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not calloc %d bytes.\n", (SIZE_ARG) * (COUNT_ARG)); } final = 0; } else if (dmalloc_examine(pnt, &user_size, NULL, NULL, NULL, NULL, NULL, NULL) != DMALLOC_NOERROR) { if (! silent_b) { (void)printf(" ERROR: examining pointer %lx failed.\n", (unsigned long)pnt); } final = 0; } else if (user_size != (SIZE_ARG) * (COUNT_ARG)) { if (! silent_b) { (void)printf(" ERROR: calloc size should be %d but was %d.\n", (SIZE_ARG) * (COUNT_ARG), user_size); } final = 0; } } /********************/ /* * Verify that the check-funcs work with check-fence. Thanks to * John Hetherington for reporting this. */ { unsigned int old_flags = dmalloc_debug_current(); int errno_hold = dmalloc_errno; dmalloc_debug(DEBUG_CHECK_FUNCS); if (! silent_b) { (void)printf(" Checking check-funcs with check-fence\n"); } #define BUF_SIZE 64 pnt = malloc(BUF_SIZE); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } dmalloc_errno = ERROR_NONE; _dmalloc_memset(__FILE__, __LINE__, pnt, 0, BUF_SIZE); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: memset on buf of %d bytes failed.\n", BUF_SIZE); } final = 0; } free(pnt); /* now turn on the check-fence token */ dmalloc_debug(DEBUG_CHECK_FENCE | DEBUG_CHECK_FUNCS); pnt = malloc(BUF_SIZE); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %d bytes.\n", BLOCK_SIZE); } return 0; } dmalloc_errno = ERROR_NONE; _dmalloc_memset(__FILE__, __LINE__, pnt, 0, BUF_SIZE); if (dmalloc_errno != ERROR_NONE) { if (! silent_b) { (void)printf(" ERROR: memset of %d bytes with check-fence failed.\n", BUF_SIZE); } final = 0; } free(pnt); dmalloc_debug(old_flags); /* recover the errno if necessary */ if (dmalloc_errno == ERROR_NONE) { dmalloc_errno = errno_hold; } } /********************/ /* * Verify the dmalloc_count_changed function. */ { unsigned long size, mem_count, loc_mark; if (! silent_b) { (void)printf(" Checking dmalloc_count_changed function\n"); } /* get a mark */ loc_mark = dmalloc_mark(); /* make sure that nothing has changed */ mem_count = dmalloc_count_changed(loc_mark, 1 /* not-freed */, 1 /* freed */); if (mem_count != 0) { if (! silent_b) { (void)printf(" ERROR: count-changed reported %lu bytes changed.\n", mem_count); } return 0; } /* allocate a pointer */ size = _dmalloc_rand() % MAX_ALLOC + 10; pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %lu bytes.\n", size); } return 0; } /* make sure that we see the non-freed pointer */ mem_count = dmalloc_count_changed(loc_mark, 1 /* not-freed */, 0 /* no freed */); if (mem_count != size) { if (! silent_b) { (void)printf(" ERROR: count-changed reported %lu bytes changed not %lu.\n", mem_count, size); } return 0; } /* make sure that we see non-freed pointer with non-fred + freed flags */ mem_count = dmalloc_count_changed(loc_mark, 1 /* not-freed */, 1 /* no freed */); if (mem_count != size) { if (! silent_b) { (void)printf(" ERROR: count-changed reported %lu bytes changed not %lu.\n", mem_count, size); } return 0; } /* now free it */ free(pnt); /* make sure that everything is freed */ mem_count = dmalloc_count_changed(loc_mark, 1 /* not-freed */, 0 /* no freed */); if (mem_count != 0) { if (! silent_b) { (void)printf(" ERROR: count-changed reported %lu bytes changed.\n", mem_count); } return 0; } /* make sure that we see the freed pointer */ mem_count = dmalloc_count_changed(loc_mark, 0 /* no not-freed */, 1 /* no freed */); if (mem_count != size) { if (! silent_b) { (void)printf(" ERROR: count-changed report %lu bytes changed not %lu.\n", mem_count, size); } return 0; } /* make sure that we see the freed pointer with both flags */ mem_count = dmalloc_count_changed(loc_mark, 1 /* no not-freed */, 1 /* no freed */); if (mem_count != size) { if (! silent_b) { (void)printf(" ERROR: count-changed report %lu bytes changed not %lu.\n", mem_count, size); } return 0; } } /********************/ /* * Check block rounding by allocator. */ { unsigned long size; unsigned int old_flags = dmalloc_debug_current(); if (! silent_b) { (void)printf(" Checking block-size alignment rounding\n"); } /* enable never-reuse and disable fence checking */ dmalloc_debug((old_flags | DEBUG_NEVER_REUSE) & (~DEBUG_CHECK_FENCE)); size = BLOCK_SIZE / 2 + 1; pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %lu bytes.\n", size); } return 0; } if ((unsigned long)pnt % BLOCK_SIZE != 0) { if (! silent_b) { (void)printf(" ERROR: alloc of %lu bytes was not block aligned.\n", size); } return 0; } free(pnt); /* * Now we'll allocate some pitifully small chunk from the heap * allocator and it should return a good pointer. In the future * it should re-align the heap. */ size = 10; pnt = _dmalloc_heap_alloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not heap-alloc %lu bytes.\n", size); } return 0; } size = BLOCK_SIZE / 2 + 1; pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %lu bytes.\n", size); } return 0; } if ((unsigned long)pnt % BLOCK_SIZE != 0) { if (! silent_b) { (void)printf(" ERROR: alloc of %lu bytes was not block aligned.\n", size); } return 0; } free(pnt); /* restore flags */ dmalloc_debug(old_flags); } /********************/ /* * Make sure free-blank doesn't imply alloc-blank */ { unsigned long size; unsigned int old_flags = dmalloc_debug_current(); if (! silent_b) { (void)printf(" Checking free versus alloc blank\n"); } /* enable free blank only without fence-post, alloc, or check blank */ dmalloc_debug((old_flags | DEBUG_FREE_BLANK) & (~(DEBUG_CHECK_FENCE | DEBUG_CHECK_BLANK | DEBUG_ALLOC_BLANK))); /* allocate a pointer */ size = BLOCK_SIZE / 2 + 1; pnt = malloc(size); if (pnt == NULL) { if (! silent_b) { (void)printf(" ERROR: could not malloc %lu bytes.\n", size); } return 0; } /* overwrite one of the top chars */ *((char *)pnt + size) = '\0'; /* this shouldn't notice */ if (dmalloc_free(__FILE__, __LINE__, pnt, DMALLOC_FUNC_FREE) != FREE_NOERROR) { if (! silent_b) { (void)printf(" ERROR: free versus alloc flags failed: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 0; } /* NOTE: no restoring of overwritten chars here because of free-blank */ /* restore flags */ dmalloc_debug(old_flags); } /********************/ /* * Check the dmalloc_get_stats function */ { unsigned long current_allocated, current_pnt_n; unsigned long current_allocated2, current_pnt_n2; int amount; if (! silent_b) { (void)printf(" Checking the dmalloc_get_stats function\n"); } dmalloc_get_stats(NULL, NULL, NULL, NULL, ¤t_allocated, ¤t_pnt_n, NULL, NULL, NULL); amount = 12; pnt = malloc(amount); dmalloc_get_stats(NULL, NULL, NULL, NULL, ¤t_allocated2, ¤t_pnt_n2, NULL, NULL, NULL); if (current_allocated2 != current_allocated + amount) { if (! silent_b) { (void)printf(" ERROR: dmalloc_get_stats did not count alloc of %d\n", amount); } final = 0; } if (current_pnt_n2 != current_pnt_n + 1) { if (! silent_b) { (void)printf(" ERROR: dmalloc_get_stats did not count pnt alloc\n"); } final = 0; } free(pnt); dmalloc_get_stats(NULL, NULL, NULL, NULL, ¤t_allocated2, ¤t_pnt_n2, NULL, NULL, NULL); if (current_allocated2 != current_allocated) { if (! silent_b) { (void)printf(" ERROR: dmalloc_get_stats did not count free of %d\n", amount); } final = 0; } if (current_pnt_n2 != current_pnt_n) { if (! silent_b) { (void)printf(" ERROR: dmalloc_get_stats did not count pnt free\n"); } final = 0; } } /********************/ /* * NOTE: add tests which should result in errors before the ------- * message above */ return final; } /* * Run the interactive section of the program */ static void do_interactive(void) { int len; char line[128], *line_p; void *pnt; (void)printf("Malloc test program. Type 'help' for assistance.\n"); while (1) { (void)printf("> "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } line_p = strchr(line, '\n'); if (line_p != NULL) { *line_p = '\0'; } len = strlen(line); if (len == 0) { continue; } if (strncmp(line, "?", len) == 0 || strncmp(line, "help", len) == 0) { (void)printf("\thelp - print this message\n\n"); (void)printf("\tmalloc - allocate memory\n"); (void)printf("\tcalloc - allocate/clear memory\n"); (void)printf("\trealloc - reallocate memory\n"); (void)printf("\trecalloc - reallocate cleared memory\n"); (void)printf("\tmemalign - allocate aligned memory\n"); (void)printf("\tvalloc - allocate page-aligned memory\n"); (void)printf("\tstrdup - allocate a string\n"); (void)printf("\tfree - deallocate memory\n\n"); (void)printf("\tstats - dump heap stats to the logfile\n"); (void)printf("\tunfreed - list the unfree memory to the logfile\n"); (void)printf("\tmark - display the current mark value\n"); (void)printf("\tchanged - display what pointers have changed\n\n"); (void)printf("\tverify - check out a memory address (or all heap)\n"); (void)printf("\toverwrite - overwrite some memory to test errors\n"); #if HAVE_SBRK (void)printf("\tsbrk - call sbrk to test external areas\n\n"); #endif (void)printf("\trandom - randomly execute a number of [de] allocs\n"); (void)printf("\tspecial - run some special tests\n\n"); (void)printf("\tquit - quit this test program\n"); continue; } if (strncmp(line, "quit", len) == 0) { break; } if (strncmp(line, "malloc", len) == 0) { int size; (void)printf("How much to malloc: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } size = atoi(line); (void)printf("malloc(%d) returned '%#lx'\n", size, (long)malloc(size)); continue; } if (strncmp(line, "calloc", len) == 0) { int size; (void)printf("How much to calloc: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } size = atoi(line); (void)printf("calloc(%d) returned '%#lx'\n", size, (long)calloc(size, sizeof(char))); continue; } if (strncmp(line, "realloc", len) == 0) { int size; pnt = get_address(); (void)printf("How much to realloc: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } size = atoi(line); (void)printf("realloc(%#lx, %d) returned '%#lx'\n", (long)pnt, size, (long)realloc(pnt, size)); continue; } if (strncmp(line, "recalloc", len) == 0) { int size; pnt = get_address(); (void)printf("How much to recalloc: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } size = atoi(line); (void)printf("realloc(%#lx, %d) returned '%#lx'\n", (long)pnt, size, (long)recalloc(pnt, size)); continue; } if (strncmp(line, "memalign", len) == 0) { int alignment, size; (void)printf("Alignment in bytes: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } alignment = atoi(line); (void)printf("How much to memalign: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } size = atoi(line); (void)printf("memalign(%d, %d) returned '%#lx'\n", alignment, size, (long)memalign(alignment, size)); continue; } if (strncmp(line, "valloc", len) == 0) { int size; (void)printf("How much to valloc: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } size = atoi(line); (void)printf("valloc(%d) returned '%#lx'\n", size, (long)valloc(size)); continue; } if (strncmp(line, "strdup", len) == 0) { (void)printf("Enter a string to strdup: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } (void)printf("strdup returned '%#lx'\n", (long)strdup(line)); continue; } if (strncmp(line, "free", len) == 0) { pnt = get_address(); free(pnt); continue; } if (strncmp(line, "stats", len) == 0) { dmalloc_log_stats(); (void)printf("Done.\n"); continue; } if (strncmp(line, "unfreed", len) == 0) { dmalloc_log_unfreed(); (void)printf("Done.\n"); continue; } if (strncmp(line, "mark", len) == 0) { (void)printf("Mark is %lu.\n", dmalloc_mark()); continue; } if (strncmp(line, "changed", len) == 0) { (void)printf("Enter the mark: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } dmalloc_log_changed(atoi(line), 1, 1, 1); (void)printf("Done.\n"); continue; } if (strncmp(line, "overwrite", len) == 0) { char *overwrite = "OVERWRITTEN"; pnt = get_address(); memcpy((char *)pnt, overwrite, strlen(overwrite)); (void)printf("Done.\n"); continue; } #if HAVE_SBRK /* call sbrk directly */ if (strncmp(line, "sbrk", len) == 0) { int size; (void)printf("How much to sbrk: "); if (fgets(line, sizeof(line), stdin) == NULL) { break; } size = atoi(line); (void)printf("sbrk(%d) returned '%#lx'\n", size, (long)sbrk(size)); continue; } #endif /* do random heap hits */ if (strncmp(line, "random", len) == 0) { int iter_n; (void)printf("How many iterations[%ld]: ", default_iter_n); if (fgets(line, sizeof(line), stdin) == NULL) { break; } if (line[0] == '\0' || line[0] == '\n') { iter_n = default_iter_n; } else { iter_n = atoi(line); } if (do_random(iter_n)) { (void)printf("It succeeded.\n"); } else { (void)printf("It failed.\n"); } continue; } /* do special checks */ if (strncmp(line, "special", len) == 0) { if (check_special()) { (void)printf("It succeeded.\n"); } else { (void)printf("It failed.\n"); } continue; } if (strncmp(line, "verify", len) == 0) { int ret; (void)printf("If the address is 0, verify will check the whole heap.\n"); pnt = get_address(); ret = dmalloc_verify(pnt); (void)printf("dmalloc_verify(%#lx) returned '%s'\n", (long)pnt, (ret == DMALLOC_NOERROR ? "success" : "failure")); continue; } (void)printf("Unknown command '%s'. Type 'help' for assistance.\n", line); } } /* * Allocation tracking function called each time an allocation occurs. * FILE may be a return address if LINE is 0. FUNC_ID is one of the * above DMALLOC_FUNC_ defines. BYTE_SIZE is how many bytes were * requested with a possible ALIGNMENT. OLD_ADDR is for realloc and * free functions. NEW_ADDR is the pointer returned by the allocation * functions. */ static void track_alloc_trxn(const char *file, const unsigned int line, const int func_id, const DMALLOC_SIZE byte_size, const DMALLOC_SIZE alignment, const DMALLOC_PNT old_addr, const DMALLOC_PNT new_addr) { char file_line[64]; if (file == NULL && line == 0) { strcpy(file_line, "unknown"); } else if (line == 0) { (void)loc_snprintf(file_line, sizeof(file_line), "ra=%#lx", (long)file); } else { (void)loc_snprintf(file_line, sizeof(file_line), "%s:%d", file, line); } switch (func_id) { case DMALLOC_FUNC_MALLOC: (void)printf("%s malloc %d bytes got %#lx\n", file_line, byte_size, (long)new_addr); break; case DMALLOC_FUNC_CALLOC: (void)printf("%s calloc %d bytes got %#lx\n", file_line, byte_size, (long)new_addr); break; case DMALLOC_FUNC_REALLOC: (void)printf("%s realloc %d bytes from %#lx got %#lx\n", file_line, byte_size, (long)old_addr, (long)new_addr); break; case DMALLOC_FUNC_RECALLOC: (void)printf("%s recalloc %d bytes from %#lx got %#lx\n", file_line, byte_size, (long)old_addr, (long)new_addr); break; case DMALLOC_FUNC_MEMALIGN: (void)printf("%s memalign %d bytes alignment %d got %#lx\n", file_line, byte_size, alignment, (long)new_addr); break; case DMALLOC_FUNC_VALLOC: (void)printf("%s valloc %d bytes alignment %d got %#lx\n", file_line, byte_size, alignment, (long)new_addr); break; case DMALLOC_FUNC_STRDUP: (void)printf("%s strdup %d bytes ot %#lx\n", file_line, byte_size, (long)new_addr); break; case DMALLOC_FUNC_FREE: (void)printf("%s free %#lx\n", file_line, (long)old_addr); break; case DMALLOC_FUNC_NEW: (void)printf("%s new %d bytes got %#lx\n", file_line, byte_size, (long)new_addr); break; case DMALLOC_FUNC_NEW_ARRAY: (void)printf("%s new[] %d bytes got %#lx\n", file_line, byte_size, (long)new_addr); break; case DMALLOC_FUNC_DELETE: (void)printf("%s delete %#lx\n", file_line, (long)old_addr); break; case DMALLOC_FUNC_DELETE_ARRAY: (void)printf("%s delete[] %#lx\n", file_line, (long)old_addr); break; default: (void)printf("%s unknown function %d bytes, %d alignment, %#lx old-addr " "%#lx new-addr\n", file_line, byte_size, alignment, (long)old_addr, (long)new_addr); break; } } int main(int argc, char **argv) { unsigned int store_flags; int ret, final = 0; argv_process(arg_list, argc, argv); if (silent_b && (verbose_b || interactive_b)) { silent_b = ARGV_FALSE; } if (env_string != NULL) { dmalloc_debug_setup(env_string); if (! silent_b) { (void)printf("Set dmalloc environment to: %s\n", env_string); } } /* repeat until we get a non 0 seed */ while (seed_random == 0) { #ifdef HAVE_TIME #ifdef HAVE_GETPID seed_random = time(0) ^ getpid(); #else /* ! HAVE_GETPID */ seed_random = time(0) ^ 0xDEADBEEF; #endif /* ! HAVE_GETPID */ #else /* ! HAVE_TIME */ #ifdef HAVE_GETPID seed_random = getpid(); #else /* ! HAVE_GETPID */ /* okay, I give up */ seed_random = 0xDEADBEEF; #endif /* ! HAVE_GETPID */ #endif /* ! HAVE_TIME */ } _dmalloc_srand(seed_random); if (! silent_b) { (void)printf("Random seed is %u\n", seed_random); } dmalloc_message("random seed is %u\n", seed_random); if (log_trans_b) { dmalloc_track(track_alloc_trxn); } store_flags = dmalloc_debug_current(); /*************************************************/ if (! no_special_b) { /* some special tests to run first thing */ if (! silent_b) { (void)printf("Running initial tests...\n"); } if (check_initial_special()) { if (! silent_b) { (void)printf(" Succeeded.\n"); } } else { if (silent_b) { (void)printf("ERROR: Initial tests failed. Last dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } else { (void)printf(" Failed. Last dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 1; } } /*************************************************/ if (interactive_b) { do_interactive(); } else { if (! silent_b) { (void)printf("Running %ld tests (use -%c for interactive)...\n", default_iter_n, INTER_CHAR); } (void)fflush(stdout); if (do_random(default_iter_n)) { if (! silent_b) { (void)printf(" Succeeded.\n"); } } else { if (silent_b) { (void)printf("ERROR: Random tests failed. Last dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } else { (void)printf(" Failed. Last dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 1; } } /*************************************************/ /* check the special malloc functions but don't allow silent dumps */ if ((! no_special_b) && (! (silent_b && (dmalloc_debug_current() & DEBUG_ERROR_ABORT)))) { if (! silent_b) { (void)printf("Running special tests...\n"); } if (check_special()) { if (! silent_b) { (void)printf(" Succeeded.\n"); } } else { if (silent_b) { (void)printf("ERROR: Running special tests failed. Last dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } else { (void)printf(" Failed. Last dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } final = 1; } } /*************************************************/ dmalloc_debug(store_flags); if (final != 0) { /* * Even if we are silent, we must give the random seed which is * the only way we can reproduce the problem. */ if (silent_b) { (void)printf("Random seed is %u. Final dmalloc error: %s (err %d)\n", seed_random, dmalloc_strerror(dmalloc_errno), dmalloc_errno); } else { (void)printf("Final dmalloc error: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } } argv_cleanup(arg_list); /* last thing is to verify the heap */ ret = dmalloc_verify(NULL /* check all heap */); if (ret != DMALLOC_NOERROR) { (void)printf("Final dmalloc_verify returned failure: %s (err %d)\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); } /* you will need this if you can't auto-shutdown */ #if HAVE_ATEXIT == 0 && HAVE_ON_EXIT == 0 && FINI_DMALLOC == 0 /* shutdown the alloc routines */ malloc_shutdown(); #endif exit(final); } dmalloc-5.5.2/dmalloc_tab_loc.h000640 001751 001751 00000005156 10622115666 016365 0ustar00graygray000000 000000 /* * Local defines for the memory table. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_tab_loc.h,v 1.9 2003/06/08 05:53:52 gray Exp $ */ #ifndef __DMALLOC_TAB_LOC_H__ #define __DMALLOC_TAB_LOC_H__ #include "conf.h" /* * Maximum number of splits. This should mean that these routines can * handle at least 2^128 different values (that's _quite_ a few). And * then you can always increase the value. */ #define MAX_QSORT_SPLITS 128 /* * Maximum number of entries that must be in list for it to be * partitioned. If there are fewer elements then just do our * insertion sort. */ #define MAX_QSORT_PARTITION 8 /* comparison function */ typedef int (*compare_t)(const void *element1_p, const void *element2_p); /* * void HASH_MIX * * DESCRIPTION: * * Mix 3 32-bit values reversibly. For every delta with one or two * bits set, and the deltas of all three high bits or all three low * bits, whether the original value of a,b,c is almost all zero or is * uniformly distributed. * * If HASH_MIX() is run forward or backward, at least 32 bits in a,b,c * have at least 1/4 probability of changing. If mix() is run * forward, every bit of c will change between 1/3 and 2/3 of the * time. (Well, 22/100 and 78/100 for some 2-bit deltas.) * * HASH_MIX() takes 36 machine instructions, but only 18 cycles on a * superscalar machine (like a Pentium or a Sparc). No faster mixer * seems to work, that's the result of my brute-force search. There * were about 2^68 hashes to choose from. I only tested about a * billion of those. */ #define HASH_MIX(a, b, c) \ do { \ a -= b; a -= c; a ^= (c >> 13); \ b -= c; b -= a; b ^= (a << 8); \ c -= a; c -= b; c ^= (b >> 13); \ a -= b; a -= c; a ^= (c >> 12); \ b -= c; b -= a; b ^= (a << 16); \ c -= a; c -= b; c ^= (b >> 5); \ a -= b; a -= c; a ^= (c >> 3); \ b -= c; b -= a; b ^= (a << 10); \ c -= a; c -= b; c ^= (b >> 15); \ } while(0) #endif /* ! __DMALLOC_TAB_LOC_H__ */ dmalloc-5.5.2/dmalloc_tab.h000644 001751 001751 00000007754 10622115666 015542 0ustar00graygray000000 000000 /* * Local defines for the memory table. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_tab.h,v 1.5 2003/06/08 05:53:45 gray Exp $ */ #ifndef __DMALLOC_TAB_H__ #define __DMALLOC_TAB_H__ /* entry in a memory table */ typedef struct mem_table_st { const char *mt_file; /* filename of alloc or ra */ unsigned int mt_line; /* line number of alloc */ unsigned long mt_total_size; /* size bytes alloced */ unsigned long mt_total_c; /* total pointers allocated */ unsigned long mt_in_use_size; /* size currently alloced */ unsigned long mt_in_use_c; /* pointers currently in use */ /* we use this so we can easily un-sort the list */ struct mem_table_st *mt_entry_pos_p; /* pos of entry in table */ } mem_table_t; /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ /* * void _dmalloc_table_clear * * DESCRIPTION: * * Clear out the allocation information in our table. We are going to * be loading it with other info. * * RETURNS: * * None. * * ARGUMENTS: * * mem_table -> Memory table we are working on. * * entry_n -> Number of entries in the memory table. * * entry_cp <-> Pointer to an integer which records how many entries * are in the table. */ extern void _dmalloc_table_clear(mem_table_t *mem_table, const int entry_n, int *entry_cp); /* * void _dmalloc_table_insert * * DESCRIPTION: * * Insert a pointer to the table. * * RETURNS: * * None. * * ARGUMENTS: * * mem_table -> Memory table we are working on. * * entry_n -> Number of entries in the memory table. * * file -> File name or return address of the allocation. * * line -> Line number of the allocation. * * size -> Size in bytes of the allocation. * * entry_cp <-> Pointer to an integer which records how many entries * are in the table. */ extern void _dmalloc_table_insert(mem_table_t *mem_table, const int entry_n, const char *file, const unsigned int line, const unsigned long size, int *entry_cp); /* * void _dmalloc_table_delete * * DESCRIPTION: * * Remove a pointer from the table. * * RETURNS: * * None. * * ARGUMENTS: * * mem_table -> Memory table we are working on. * * entry_n -> Number of entries in the memory table. * * old_file -> File name or return address of the allocation to * delete. * * old_line -> Line number of the allocation to delete. * * size -> Size in bytes of the allocation. */ extern void _dmalloc_table_delete(mem_table_t *mem_table, const int entry_n, const char *old_file, const unsigned int old_line, const DMALLOC_SIZE size); /* * void _dmalloc_table_log_info * * DESCRIPTION: * * Log information from the memory table to the log file. * * RETURNS: * * None. * * ARGUMENTS: * * mem_table -> Memory table we are working on. * * current_n -> Number of current entries in the memory table. * * entry_n -> Number of total possible entries in the memory table. * * log_n -> Number of entries to log to the file. Set to 0 to * display all entries in the table. * * in_use_column_b -> Display the in-use numbers in a column. */ extern void _dmalloc_table_log_info(mem_table_t *mem_table, const int current_n, const int entry_n, const int log_n, const int in_use_column_b); /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __DMALLOC_TAB_H__ */ dmalloc-5.5.2/dmalloc_tab.c000640 001751 001751 00000050625 10622115666 015524 0ustar00graygray000000 000000 /* * Memory table routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_tab.c,v 1.19 2003/06/08 05:53:44 gray Exp $ */ /* * This file contains routines used to maintain and display a memory * table by file and line number of memory usage. * * Inspired by code from PSM. Thanks much. */ #if HAVE_STDLIB_H # include /* for qsort */ #endif #if HAVE_STRING_H # include #endif #include "conf.h" #include "chunk.h" #include "compat.h" #include "dmalloc.h" #include "dmalloc_loc.h" #include "error.h" #include "error_val.h" #include "dmalloc_tab.h" #include "dmalloc_tab_loc.h" /* * static unsigned int hash * * DESCRIPTION: * * Hash a variable-length key into a 32-bit value. Every bit of the * key affects every bit of the return value. Every 1-bit and 2-bit * delta achieves avalanche. About (6 * len + 35) instructions. The * best hash table sizes are powers of 2. There is no need to use mod * (sooo slow!). If you need less than 32 bits, use a bitmask. For * example, if you need only 10 bits, do h = (h & hashmask(10)); In * which case, the hash table should have hashsize(10) elements. * * By Bob Jenkins, 1996. You may use this code any way you wish, * private, educational, or commercial. It's free. See * http://ourworld.compuserve.com/homepages/bob_jenkins/evahash.htm * Use for hash table lookup, or anything where one collision in 2^^32 * is acceptable. Do NOT use for cryptographic purposes. * * RETURNS: * * Returns a 32-bit hash value. * * ARGUMENTS: * * key - Key (the unaligned variable-length array of bytes) that we * are hashing. * * length - Length of the key in bytes. * * init_val - Initialization value of the hash if you need to hash a * number of strings together. For instance, if you are hashing N * strings (unsigned char **)keys, do it like this: * * for (i=0, h=0; i= 12; len -= 12) { a += (key_p[0] + ((unsigned int)key_p[1] << 8) + ((unsigned int)key_p[2] << 16) + ((unsigned int)key_p[3] << 24)); b += (key_p[4] + ((unsigned int)key_p[5] << 8) + ((unsigned int)key_p[6] << 16) + ((unsigned int)key_p[7] << 24)); c += (key_p[8] + ((unsigned int)key_p[9] << 8) + ((unsigned int)key_p[10] << 16) + ((unsigned int)key_p[11] << 24)); HASH_MIX(a,b,c); key_p += 12; } c += length; /* all the case statements fall through to the next */ switch(len) { case 11: c += ((unsigned int)key_p[10] << 24); case 10: c += ((unsigned int)key_p[9] << 16); case 9: c += ((unsigned int)key_p[8] << 8); /* the first byte of c is reserved for the length */ case 8: b += ((unsigned int)key_p[7] << 24); case 7: b += ((unsigned int)key_p[6] << 16); case 6: b += ((unsigned int)key_p[5] << 8); case 5: b += key_p[4]; case 4: a += ((unsigned int)key_p[3] << 24); case 3: a += ((unsigned int)key_p[2] << 16); case 2: a += ((unsigned int)key_p[1] << 8); case 1: a += key_p[0]; /* case 0: nothing left to add */ } HASH_MIX(a, b, c); return c; } /* * static unsigned int which_bucket * * DESCRIPTION: * * Determine the bucket with our file/line and hash function. * * RETURNS: * * Bucket number. * * ARGUMENTS: * * entry_n -> Number of entries in the memory table. * * file -> File name or return address of the allocation. * * line -> Line number of the allocation. */ static unsigned int which_bucket(const int entry_n, const char *file, const unsigned int line) { unsigned int bucket; if (line == 0) { if (file == NULL) { bucket = 0; } else { /* we hash on the address in file -- should be a return-address */ bucket = hash((unsigned char *)&file, sizeof(char *), 0); } } else { bucket = hash((unsigned char *)file, strlen(file), 0); bucket = hash((unsigned char *)&line, sizeof(line), bucket); } bucket %= entry_n - 1; return bucket; } /* * static int entry_cmp * * DESCRIPTION: * * Compare two entries in the memory table for quicksort. * * RETURNS: * * -1, 0, or 1 depending if entry1_p is less-than, equal, or * greater-than entry2_p. * * ARGUMENTS: * * entry1_p -> Pointer to the 1st entry. * * entry2_p -> Pointer to the 2nd entry. */ static int entry_cmp(const void *entry1_p, const void *entry2_p) { unsigned long size1, size2; const mem_table_t *tab1_p = entry1_p, *tab2_p = entry2_p; /* if the entry is blank then force the size to be 0 */ if (tab1_p->mt_file == NULL) { size1 = 0; } else { size1 = tab1_p->mt_total_size; } /* if the entry is blank then force the size to be 0 */ if (tab2_p->mt_file == NULL) { size2 = 0; } else { size2 = tab2_p->mt_total_size; } /* NOTE: we want the top entries to be ahead so we reverse the sort */ if (size1 > size2) { return -1; } else if (size1 == size2) { return 0; } else { return 1; } } /* * static void swap_bytes * * DESCRIPTION: * * Swap the values between two items of a specified size. * * RETURNS: * * None. * * ARGUMENTS: * * item1_p -> Pointer to the first item. * * item2_p -> Pointer to the first item. * * ele_size -> Size of the two items. */ static void swap_bytes(unsigned char *item1_p, unsigned char *item2_p, int ele_size) { unsigned char char_temp; for (; ele_size > 0; ele_size--) { char_temp = *item1_p; *item1_p = *item2_p; *item2_p = char_temp; item1_p++; item2_p++; } } /* * static void insert_sort * * DESCRIPTION: * * Do an insertion sort which is faster for small numbers of items and * better if the items are already sorted. * * RETURNS: * * None. * * ARGUMENTS: * * first_p <-> Start of the list that we are splitting. * * last_p <-> Last entry in the list that we are splitting. * * holder_p <-> Location of hold area we can store an entry. * * ele_size -> Size of the each element in the list. */ static void insert_sort(unsigned char *first_p, unsigned char *last_p, unsigned char *holder_p, const unsigned int ele_size) { unsigned char *inner_p, *outer_p; for (outer_p = first_p + ele_size; outer_p <= last_p; ) { /* look for the place to insert the entry */ for (inner_p = outer_p - ele_size; inner_p >= first_p && entry_cmp(outer_p, inner_p) < 0; inner_p -= ele_size) { } inner_p += ele_size; /* do we need to insert the entry in? */ if (outer_p != inner_p) { /* * Now we shift the entry down into its place in the already * sorted list. */ memcpy(holder_p, outer_p, ele_size); memmove(inner_p + ele_size, inner_p, outer_p - inner_p); memcpy(inner_p, holder_p, ele_size); } outer_p += ele_size; } } /* * static void split * * DESCRIPTION: * * This sorts an array of longs via the quick sort algorithm (it's * pretty quick) * * RETURNS: * * None. * * ARGUMENTS: * * first_p -> Start of the list that we are splitting. * * last_p -> Last entry in the list that we are splitting. * * ele_size -> Size of the each element in the list. */ static void split(unsigned char *first_p, unsigned char *last_p, const unsigned int ele_size) { unsigned char *left_p, *right_p, *pivot_p, *left_last_p, *right_first_p; unsigned char *firsts[MAX_QSORT_SPLITS], *lasts[MAX_QSORT_SPLITS]; mem_table_t pivot; unsigned int width, split_c = 0, min_qsort_size, size1, size2; min_qsort_size = MAX_QSORT_PARTITION * ele_size; while (1) { /* find the left, right, and mid point */ left_p = first_p; right_p = last_p; /* is there a faster way to find this? */ width = (last_p - first_p) / ele_size; pivot_p = first_p + ele_size * (width >> 1); /* * Find which of the left, middle, and right elements is the * median (Knuth vol3 p123). */ if (entry_cmp(first_p, pivot_p) > 0) { swap_bytes(first_p, pivot_p, ele_size); } if (entry_cmp(pivot_p, last_p) > 0) { swap_bytes(pivot_p, last_p, ele_size); if (entry_cmp(first_p, pivot_p) > 0) { swap_bytes(first_p, pivot_p, ele_size); } } /* * save our pivot so we don't have to worry about hitting and * swapping it elsewhere while we iterate across the list below. */ memcpy(&pivot, pivot_p, ele_size); do { /* shift the left side up until we reach the pivot value */ while (entry_cmp(left_p, &pivot) < 0) { left_p += ele_size; } /* shift the right side down until we reach the pivot value */ while (entry_cmp(&pivot, right_p) < 0) { right_p -= ele_size; } /* if we met in the middle then we are done */ if (left_p == right_p) { left_p += ele_size; right_p -= ele_size; break; } else if (left_p < right_p) { /* * swap the left and right since they both were on the wrong * size of the pivot and continue */ swap_bytes(left_p, right_p, ele_size); left_p += ele_size; right_p -= ele_size; } } while (left_p <= right_p); /* Rename variables to make more sense. This will get optimized out. */ right_first_p = left_p; left_last_p = right_p; /* determine the size of the left and right hand parts */ size1 = left_last_p - first_p; size2 = last_p - right_first_p; /* is the 1st half small enough to just insert-sort? */ if (size1 < min_qsort_size) { /* use the pivot as our temporary space */ insert_sort(first_p, left_last_p, (unsigned char *)&pivot, ele_size); /* is the 2nd part small as well? */ if (size2 < min_qsort_size) { /* use the pivot as our temporary space */ insert_sort(right_first_p, last_p, (unsigned char *)&pivot, ele_size); /* pop a partition off our stack */ if (split_c == 0) { /* we are done */ return; } split_c--; first_p = firsts[split_c]; last_p = lasts[split_c]; } else { /* we can just handle the right side immediately */ first_p = right_first_p; /* last_p = last_p */ } } else if (size2 < min_qsort_size) { /* use the pivot as our temporary space */ insert_sort(right_first_p, last_p, (unsigned char *)&pivot, ele_size); /* we can just handle the left side immediately */ /* first_p = first_p */ last_p = left_last_p; } else { /* * neither partition is small, we'll have to push the larger one * of them on the stack */ if (split_c >= MAX_QSORT_SPLITS) { /* sanity check here -- we should never get here */ abort(); } if (size1 > size2) { /* push the left partition on the stack */ firsts[split_c] = first_p; lasts[split_c] = left_last_p; split_c++; /* continue handling the right side */ first_p = right_first_p; /* last_p = last_p */ } else { /* push the right partition on the stack */ firsts[split_c] = right_first_p; lasts[split_c] = last_p; split_c++; /* continue handling the left side */ /* first_p = first_p */ last_p = left_last_p; } } } } /* * static void log_slot * * DESCRIPTION: * * Log the information from the memory slot to the logfile. * * RETURNS: * * None. * * ARGUMENTS: * * tab_p -> Pointer to the memory table entry we are dumping. * * in_use_column_b -> Display the in-use numbers in a column. * * source -> Source description string. */ static void log_entry(const mem_table_t *tab_p, const int in_use_column_b, const char *source) { if (in_use_column_b) { dmalloc_message("%11lu %6lu %11lu %6lu %s\n", tab_p->mt_total_size, tab_p->mt_total_c, tab_p->mt_in_use_size, tab_p->mt_in_use_c, source); } else { dmalloc_message("%11lu %6lu %s\n", tab_p->mt_total_size, tab_p->mt_total_c, source); } } /* * static void add_entry * * DESCRIPTION: * * Add a memory entry into our memory info total. * * RETURNS: * * None. * * ARGUMENTS: * * total_p <-> Pointer to the memory table entry we are using to total * our used size. * tab_p -> Pointer to the memory table entry we are adding into our total. */ static void add_entry(mem_table_t *total_p, const mem_table_t *tab_p) { total_p->mt_total_size += tab_p->mt_total_size; total_p->mt_total_c += tab_p->mt_total_c; total_p->mt_in_use_size += tab_p->mt_in_use_size; total_p->mt_in_use_c += tab_p->mt_in_use_c; } /* * void _dmalloc_table_clear * * DESCRIPTION: * * Clear out the allocation information in our table. We are going to * be loading it with other info. * * RETURNS: * * None. * * ARGUMENTS: * * mem_table -> Memory table we are working on. * * entry_n -> Number of entries in the memory table. * * entry_cp <-> Pointer to an integer which records how many entries * are in the table. */ void _dmalloc_table_clear(mem_table_t *mem_table, const int entry_n, int *entry_cp) { /* clear out our memory table */ memset(mem_table, 0, sizeof(mem_table[0]) * entry_n); SET_POINTER(entry_cp, 0); } /* * void _dmalloc_table_insert * * DESCRIPTION: * * Insert a pointer to the table. * * RETURNS: * * None. * * ARGUMENTS: * * mem_table -> Memory table we are working on. * * entry_n -> Number of entries in the memory table. * * file -> File name or return address of the allocation. * * line -> Line number of the allocation. * * size -> Size in bytes of the allocation. * * entry_cp <-> Pointer to an integer which records how many entries * are in the table. */ void _dmalloc_table_insert(mem_table_t *mem_table, const int entry_n, const char *file, const unsigned int line, const unsigned long size, int *entry_cp) { unsigned int bucket; mem_table_t *tab_p, *tab_end_p, *tab_bounds_p, *tab_other_p; bucket = which_bucket(entry_n, file, line); tab_p = mem_table + bucket; /* the end is if we come around to the start again */ tab_end_p = tab_p; tab_other_p = mem_table + entry_n - 1; /* our boundary for our hash table is the other slot */ tab_bounds_p = tab_other_p; while (1) { if (tab_p->mt_file == file && tab_p->mt_line == line) { /* we found it */ break; } else if (tab_p->mt_file == NULL) { /* we didn't find it */ break; } tab_p++; if (tab_p == tab_bounds_p) { tab_p = mem_table; } /* we shouldn't have gone through the entire table */ if (tab_p == tab_end_p) { } } /* did we not find the pointer? */ if (tab_p->mt_file == NULL) { if (*entry_cp >= MEMORY_TABLE_SIZE) { /* if the table is too full then add info into other_pointers bucket */ tab_p = tab_other_p; } else { /* we found an open slot */ tab_p->mt_file = file; tab_p->mt_line = line; /* remember its position in the table so we can unsort it later */ tab_p->mt_entry_pos_p = tab_p; (*entry_cp)++; } } /* update the info for the entry */ tab_p->mt_total_size += size; tab_p->mt_total_c++; tab_p->mt_in_use_size += size; tab_p->mt_in_use_c++; } /* * void _dmalloc_table_delete * * DESCRIPTION: * * Remove a pointer from the table. * * RETURNS: * * None. * * ARGUMENTS: * * mem_table -> Memory table we are working on. * * entry_n -> Number of entries in the memory table. * * old_file -> File name or return address of the allocation to * delete. * * old_line -> Line number of the allocation to delete. * * size -> Size in bytes of the allocation. */ void _dmalloc_table_delete(mem_table_t *mem_table, const int entry_n, const char *old_file, const unsigned int old_line, const DMALLOC_SIZE size) { unsigned int bucket; int found_b = 0; mem_table_t *tab_p, *tab_end_p, *tab_other_p, *tab_bounds_p; bucket = which_bucket(entry_n, old_file, old_line); tab_p = mem_table + bucket; /* the end is if we come around to the start again */ tab_end_p = tab_p; tab_other_p = mem_table + entry_n - 1; /* our boundary for our hash table is the other slot */ tab_bounds_p = tab_other_p; do { if (tab_p->mt_file == old_file && tab_p->mt_line == old_line) { /* we found it */ found_b = 1; break; } else if (tab_p->mt_file == NULL) { /* we didn't find it */ break; } tab_p++; if (tab_p == tab_bounds_p) { tab_p = mem_table; } } while (tab_p != tab_end_p); /* did we find the pointer? */ if (! found_b) { /* assume that we should take it out of the other_pointers bucket */ tab_p = tab_other_p; } /* update our pointer info if we can */ if (tab_p->mt_in_use_size >= size && tab_p->mt_in_use_c > 0) { tab_p->mt_in_use_size -= size; tab_p->mt_in_use_c--; } } /* * void _dmalloc_table_log_info * * DESCRIPTION: * * Log information from the memory table to the log file. * * RETURNS: * * None. * * ARGUMENTS: * * mem_table -> Memory table we are working on. * * current_n -> Number of current entries in the memory table. * * entry_n -> Number of total possible entries in the memory table. * * log_n -> Number of entries to log to the file. Set to 0 to * display all entries in the table. * * in_use_column_b -> Display the in-use numbers in a column. */ void _dmalloc_table_log_info(mem_table_t *mem_table, const int current_n, const int entry_n, const int log_n, const int in_use_column_b) { mem_table_t *tab_p, *tab_other_p, *tab_bounds_p, total; int entry_c; char source[64]; /* is the table empty */ if (current_n == 0) { dmalloc_message(" memory table is empty"); return; } /* sort the entries by their total-size */ split((unsigned char *)mem_table, (unsigned char *)(mem_table + entry_n - 2), sizeof(mem_table[0])); /* display the column headers */ if (in_use_column_b) { dmalloc_message(" total-size count in-use-size count source"); } else { dmalloc_message(" total-size count source"); } memset(&total, 0, sizeof(total)); tab_other_p = mem_table + entry_n - 1; /* our boundary for our hash table is the other slot */ tab_bounds_p = tab_other_p; entry_c = 0; for (tab_p = mem_table; tab_p < tab_bounds_p; tab_p++) { if (tab_p->mt_file != NULL) { entry_c++; /* can we still print the pointer information? */ if (log_n == 0 || entry_c < log_n) { (void)_dmalloc_chunk_desc_pnt(source, sizeof(source), tab_p->mt_file, tab_p->mt_line); log_entry(tab_p, in_use_column_b, source); } add_entry(&total, tab_p); } } if (current_n >= MEMORY_TABLE_SIZE) { strncpy(source, "Other pointers", sizeof(source)); source[sizeof(source) - 1] = '\0'; log_entry(tab_other_p, in_use_column_b, source); add_entry(&total, tab_other_p); } /* dump our total */ (void)loc_snprintf(source, sizeof(source), "Total of %d", entry_c); log_entry(&total, in_use_column_b, source); /* * If we sorted the array, we have to put it back the way it was if * we want to continue and handle memory transactions. We should be * able to do this in O(N). */ tab_bounds_p = mem_table + entry_n - 1; for (tab_p = mem_table; tab_p < tab_bounds_p;) { mem_table_t swap_entry; /* * If we have a blank slot or if the entry is in the right * position then we can move on to the next one */ if (tab_p->mt_file == NULL || tab_p->mt_entry_pos_p == tab_p) { tab_p++; continue; } /* swap this entry for where it should go and do _not_ increment tab_p */ swap_entry = *tab_p->mt_entry_pos_p; *tab_p->mt_entry_pos_p = *tab_p; *tab_p = swap_entry; } } dmalloc-5.5.2/dmalloc_rand.h000644 001751 001751 00000003016 10622115666 015703 0ustar00graygray000000 000000 /* * Defines for the internal random number generator * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_rand.h,v 1.1 2003/06/04 23:43:45 gray Exp $ */ #ifndef __DMALLOC_RAND_H__ #define __DMALLOC_RAND_H__ /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ /* * static void _dmalloc_srand * * DESCRIPTION: * * Seed the random number generator with the user argument. * * RETURNS: * * None. * * ARGUMENTS: * * seed -> Value to seed the algorithm with. */ extern void _dmalloc_srand(const long seed); /* * static long _dmalloc_rand * * DESCRIPTION: * * Get a pseudo-random number from the random algorithm. * * RETURNS: * * Random number. * * ARGUMENTS: * * None. */ extern long _dmalloc_rand(void); /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __DMALLOC_RAND_H__ */ dmalloc-5.5.2/dmalloc.h.3000644 001751 001751 00000101142 10622115666 015037 0ustar00graygray000000 000000 /* NOTE: start of $Id: dmalloc.h.4,v 1.15 2007/05/14 17:23:37 gray Exp $ */ /* dmalloc version defines */ #define DMALLOC_VERSION_MAJOR 5 /* X.0.0 */ #define DMALLOC_VERSION_MINOR 5 /* 0.X.0 */ #define DMALLOC_VERSION_PATCH 2 /* 0.0.X */ /* this defines what type the standard void memory-pointer is */ #if (defined(__STDC__) && __STDC__ == 1) || defined(__cplusplus) || defined(STDC_HEADERS) || defined(_ISO_STDLIB_ISO_H) #define DMALLOC_PNT void * #define DMALLOC_FREE_RET void #else #define DMALLOC_PNT char * #define DMALLOC_FREE_RET int #endif /* * Malloc function return codes */ #define CALLOC_ERROR 0L /* error from calloc */ #define MALLOC_ERROR 0L /* error from malloc */ #define REALLOC_ERROR 0L /* error from realloc */ /* NOTE: this if for non- __STDC__ systems only */ #define FREE_ERROR 0 /* error from free */ #define FREE_NOERROR 1 /* no error from free */ #define DMALLOC_ERROR 0 /* function failed */ #define DMALLOC_NOERROR 1 /* function succeeded */ #define DMALLOC_VERIFY_ERROR 0 /* function failed */ #define DMALLOC_VERIFY_NOERROR 1 /* function succeeded */ #define MALLOC_VERIFY_ERROR DMALLOC_VERIFY_ERROR #define MALLOC_VERIFY_NOERROR DMALLOC_VERIFY_NOERROR /* * Dmalloc function IDs for the dmalloc_track_t callback function. */ #define DMALLOC_FUNC_MALLOC 10 /* malloc function called */ #define DMALLOC_FUNC_CALLOC 11 /* calloc function called */ #define DMALLOC_FUNC_REALLOC 12 /* realloc function called */ #define DMALLOC_FUNC_RECALLOC 13 /* recalloc called */ #define DMALLOC_FUNC_MEMALIGN 14 /* memalign function called */ #define DMALLOC_FUNC_VALLOC 15 /* valloc function called */ #define DMALLOC_FUNC_STRDUP 16 /* strdup function called */ #define DMALLOC_FUNC_FREE 17 /* free function called */ #define DMALLOC_FUNC_CFREE 18 /* cfree function called */ #define DMALLOC_FUNC_NEW 20 /* new function called */ #define DMALLOC_FUNC_NEW_ARRAY 21 /* new[] function called */ #define DMALLOC_FUNC_DELETE 22 /* delete function called */ #define DMALLOC_FUNC_DELETE_ARRAY 23 /* delete[] function called */ #ifdef __cplusplus extern "C" { #endif typedef void (*dmalloc_track_t)(const char *file, const unsigned int line, const int func_id, const DMALLOC_SIZE byte_size, const DMALLOC_SIZE alignment, const DMALLOC_PNT old_addr, const DMALLOC_PNT new_addr); /* internal dmalloc error number for reference purposes only */ extern int dmalloc_errno; /* logfile for dumping dmalloc info, DMALLOC_LOGFILE env var overrides this */ extern char *dmalloc_logpath; /* * void dmalloc_shutdown * * DESCRIPTION: * * Shutdown the dmalloc library and provide statistics if necessary. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ extern void dmalloc_shutdown(void); #if FINI_DMALLOC /* * void __fini_dmalloc * * DESCRIPTION: * * Automatic function to close dmalloc supported by some operating * systems. Pretty cool OS/compiler hack. By default it is not * necessary because we use atexit() and on_exit() to register the * close functions which are more portable. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ extern void __fini_dmalloc(void); #endif /* if FINI_DMALLOC */ /* * DMALLOC_PNT dmalloc_malloc * * DESCRIPTION: * * Allocate and return a memory block of a certain size. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * size -> Number of bytes requested. * * func_id -> Function-id to identify the type of call. See * dmalloc.h. * * alignment -> To align the new block to a certain number of bytes, * set this to a value greater than 0. * * xalloc_b -> If set to 1 then print an error and exit if we run out * of memory. */ extern DMALLOC_PNT dmalloc_malloc(const char *file, const int line, const DMALLOC_SIZE size, const int func_id, const DMALLOC_SIZE alignment, const int xalloc_b); /* * DMALLOC_PNT dmalloc_realloc * * DESCRIPTION: * * Resizes and old pointer to a new number of bytes. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * old_pnt -> Pointer to an existing memory chunk that we are * resizing. If this is NULL then it basically does a malloc. * * new_size -> New number of bytes requested for the old pointer. * * func_id -> Function-id to identify the type of call. See * dmalloc.h. * * xalloc_b -> If set to 1 then print an error and exit if we run out * of memory. */ extern DMALLOC_PNT dmalloc_realloc(const char *file, const int line, DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size, const int func_id, const int xalloc_b); /* * int dmalloc_free * * DESCRIPTION: * * Release a pointer back into the heap. * * RETURNS: * * Success - FREE_NOERROR * * Failure - FREE_ERROR * * Note: many operating systems define free to return (void) so this * return value may be filtered. Dumb. * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * pnt -> Existing pointer we are freeing. * * func_id -> Function-id to identify the type of call. See * dmalloc.h. */ extern int dmalloc_free(const char *file, const int line, DMALLOC_PNT pnt, const int func_id); /* * DMALLOC_PNT dmalloc_strndup * * DESCRIPTION: * * Allocate and return an allocated block of memory holding a copy of * a string of a certain number of characters. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * string -> String we are duplicating. * * len -> Length of the string we are duplicating. * * xalloc_b -> If set to 1 then print an error and exit if we run out * of memory. */ extern char *dmalloc_strndup(const char *file, const int line, const char *string, const int len, const int xalloc_b); /* * DMALLOC_PNT malloc * * DESCRIPTION: * * Overloading the malloc(3) function. Allocate and return a memory * block of a certain size. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * size -> Number of bytes requested. */ extern DMALLOC_PNT malloc(DMALLOC_SIZE size); /* * DMALLOC_PNT calloc * * DESCRIPTION: * * Overloading the calloc(3) function. Returns a block of zeroed memory. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * num_elements -> Number of elements being allocated. * * size -> The number of bytes in each element. */ extern DMALLOC_PNT calloc(DMALLOC_SIZE num_elements, DMALLOC_SIZE size); /* * DMALLOC_PNT realloc * * DESCRIPTION: * * Overload of realloc(3). Resizes and old pointer to a new number of * bytes. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * old_pnt -> Pointer to an existing memory chunk that we are * resizing. If this is NULL then it basically does a malloc. * * new_size -> New number of bytes requested for the old pointer. */ extern DMALLOC_PNT realloc(DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size); /* * DMALLOC_PNT recalloc * * DESCRIPTION: * * Overload of recalloc(3) which exists on some systems. Resizes and * old pointer to a new number of bytes. If we are expanding, then * any new bytes will be zeroed. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * old_pnt -> Pointer to an existing memory chunk that we are * resizing. * * new_size -> New number of bytes requested for the old pointer. */ extern DMALLOC_PNT recalloc(DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size); /* * DMALLOC_PNT memalign * * DESCRIPTION: * * Overloading the memalign(3) function. Allocate and return a memory * block of a certain size which have been aligned to a certain * alignment. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * alignment -> Value to which the allocation must be aligned. This * should probably be a multiple of 2 with a maximum value equivalent * to the block-size which is often 1k or 4k. * * size -> Number of bytes requested. */ extern DMALLOC_PNT memalign(DMALLOC_SIZE alignment, DMALLOC_SIZE size); /* * DMALLOC_PNT valloc * * DESCRIPTION: * * Overloading the valloc(3) function. Allocate and return a memory * block of a certain size which have been aligned to page boundaries * which are often 1k or 4k. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * size -> Number of bytes requested. */ extern DMALLOC_PNT valloc(DMALLOC_SIZE size); #ifndef DMALLOC_STRDUP_MACRO /* * DMALLOC_PNT strdup * * DESCRIPTION: * * Overload of strdup(3). Allocate and return an allocated block of * memory holding a copy of a string. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * string -> String we are duplicating. */ extern char *strdup(const char *string); #endif /* ifndef DMALLOC_STRDUP_MACRO */ /* * DMALLOC_PNT strndup * * DESCRIPTION: * * Overload of strndup(3). Allocate and return an allocated block of * memory holding a copy of a string with a maximum length. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * string -> String we are duplicating. * * len -> Length of the string to duplicate. */ extern char *strndup(const char *string, const DMALLOC_SIZE len); /* * DMALLOC_FREE_RET free * * DESCRIPTION: * * Release a pointer back into the heap. * * RETURNS: * * Returns FREE_ERROR, FREE_NOERROR or void depending on whether STDC * is defined by your compiler. * * ARGUMENTS: * * pnt -> Existing pointer we are freeing. */ extern DMALLOC_FREE_RET free(DMALLOC_PNT pnt); /* * DMALLOC_FREE_RET cfree * * DESCRIPTION: * * Same as free. * * RETURNS: * * Returns FREE_ERROR, FREE_NOERROR or void depending on whether STDC * is defined by your compiler. * * ARGUMENTS: * * pnt -> Existing pointer we are freeing. */ extern DMALLOC_FREE_RET cfree(DMALLOC_PNT pnt); /* * int dmalloc_verify * * DESCRIPTION: * * Verify a pointer which has previously been allocated by the * library or check the entire heap. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * pnt -> Pointer we are verifying. If 0L then check the entire heap. */ extern int dmalloc_verify(const DMALLOC_PNT pnt); /* * int malloc_verify * * DESCRIPTION: * * Verify a pointer which has previously been allocated by the * library. Same as dmalloc_verify. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * pnt -> Pointer we are verifying. If 0L then check the entire heap. */ extern int malloc_verify(const DMALLOC_PNT pnt); /* * int dmalloc_verify_pnt * * DESCRIPTION: * * This function is mainly used by the arg_check.c functions to verify * specific pointers. This can be used by users to provide more fine * grained tests on pointers. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * file -> File-name or return-address of the caller. You can use * __FILE__ for this argument or 0L for none. * * line -> Line-number of the caller. You can use __LINE__ for this * argument or 0 for none. * * func -> Function string which is checking the pointer. 0L if none. * * pnt -> Pointer we are checking. * * exact_b -> Set to 1 if this pointer was definitely handed back from * a memory allocation. If set to 0 then this pointer can be inside * another allocation or outside the heap altogether. * * strlen_b -> Set to 1 to make sure that this pointer can handle * strlen(pnt) + 1 bytes up to the maximum specified by min_size. If * this is 1 and min_size > 0 then it is in effect a strnlen. * * min_size -> Make sure that pointer can hold at least that many * bytes if inside of the heap. If 0 then don't check the size. */ extern int dmalloc_verify_pnt_strsize(const char *file, const int line, const char *func, const void *pnt, const int exact_b, const int strlen_b, const int min_size); /* * int dmalloc_verify_pnt * * DESCRIPTION: * * This function is mainly used by the arg_check.c functions to verify * specific pointers. This can be used by users to provide more fine * grained tests on pointers. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * file -> File-name or return-address of the caller. You can use * __FILE__ for this argument or 0L for none. * * line -> Line-number of the caller. You can use __LINE__ for this * argument or 0 for none. * * func -> Function string which is checking the pointer. 0L if none. * * pnt -> Pointer we are checking. * * exact_b -> Set to 1 if this pointer was definitely handed back from * a memory allocation. If set to 0 then this pointer can be inside * another allocation or outside the heap altogether. * * min_size -> Make sure that pointer can hold at least that many * bytes if inside of the heap. If -1 then make sure it can handle * strlen(pnt) + 1 bytes (+1 for the \0). If 0 then don't check the * size. If you need strnlen functionality with a maximum on the * strlen, see dmalloc_verify_pnt_strsize. */ extern int dmalloc_verify_pnt(const char *file, const int line, const char *func, const void *pnt, const int exact_b, const int min_size); /* * unsigned int dmalloc_debug * * DESCRIPTION: * * Set the global debug functionality flags. You can also use * dmalloc_debug_setup. * * Note: you cannot add or remove certain flags such as signal * handlers since they are setup at initialization time only. * * RETURNS: * * The old debug flag value. * * ARGUMENTS: * * flags -> Flag value to set. Pass in 0 to disable all debugging. */ extern unsigned int dmalloc_debug(const unsigned int flags); /* * unsigned int dmalloc_debug_current * * DESCRIPTION: * * Returns the current debug functionality flags. This allows you to * save a dmalloc library state to be restored later. * * RETURNS: * * Current debug flags. * * ARGUMENTS: * * None. */ extern unsigned int dmalloc_debug_current(void); /* * void dmalloc_debug_setup * * DESCRIPTION: * * Set the global debugging functionality as an option string. * Normally this would be pased in in the DMALLOC_OPTIONS * environmental variable. This is here to override the env or for * circumstances where modifying the environment is not possible or * does not apply such as servers or cgi-bin programs. * * RETURNS: * * None. * * ARGUMENTS: * * options_str -> Options string to set the library flags. */ extern void dmalloc_debug_setup(const char *options_str); /* * int dmalloc_examine * * DESCRIPTION: * * Examine a pointer and pass back information on its allocation size * as well as the file and line-number where it was allocated. If the * file and line number is not available, then it will pass back the * allocation location's return-address if available. * * RETURNS: * * Success - DMALLOC_NOERROR * * Failure - DMALLOC_ERROR * * ARGUMENTS: * * pnt -> Pointer we are checking. * * user_size_p <- Pointer to a DMALLOC_SIZE type variable which, if * not NULL, will be set to the size of bytes from the pointer. * * total_size_p <- Poiner to a DMALLOC_SIZE type variable which, if * not NULL, will be set to the total size given for this allocation * including administrative overhead. * * file_p <- Pointer to a character pointer which, if not NULL, will * be set to the file where the pointer was allocated. * * line_p <- Pointer to an unsigned integer which, if not NULL, will * be set to the line-number where the pointer was allocated. * * ret_attr_p <- Pointer to a void pointer, if not NULL, will be set * to the return-address where the pointer was allocated. * * used_mark_p <- Poiner to an unsigned integer which, if not NULL, * will be set to the mark of when the pointer was last "used". This * could be when it was allocated, reallocated, or freed. * * seen_p <- Poiner to an unsigned long which, if not NULL, will be * set to the number of times that this pointer has been allocated, * realloced, or freed. NOTE: LOG_PNT_SEEN_COUNT must be set to 1 * otherwise no seen information is available and it will be set to 0. */ extern int dmalloc_examine(const DMALLOC_PNT pnt, DMALLOC_SIZE *user_size_p, DMALLOC_SIZE *total_size_p, char **file_p, unsigned int *line_p, DMALLOC_PNT *ret_attr_p, unsigned long *used_mark_p, unsigned long *seen_p); /* * void dmalloc_track * * DESCRIPTION: * * Register an allocation tracking function which will be called each * time an allocation occurs. * * RETURNS: * * None. * * ARGUMENTS: * * track_func -> Function to register as the tracking function. Set * to NULL to disable. */ extern void dmalloc_track(const dmalloc_track_t track_func); /* * unsigned long dmalloc_mark * * DESCRIPTION: * * Return to the caller the current "mark" which can be used later by * dmalloc_log_changed to log the changed pointers since this point. * Multiple marks can be saved and used. * * This is also the iteration number and can be logged at the front of * each memory transaction in the logfile with the LOG_ITERATION * define in settings.h and can be logged with each pointer with the * LOG_PNT_ITERATION define in settings.h. * * RETURNS: * * Current mark value * * ARGUMENTS: * * None. */ extern unsigned long dmalloc_mark(void); /* * unsigned long dmalloc_memory_allocated * * DESCRIPTION: * * Return the total number of bytes allocated by the program so far. * * RETURNS: * * Total number of bytes allocated by the program so far. * * ARGUMENTS: * * None. */ extern unsigned long dmalloc_memory_allocated(void); /* * unsigned int dmalloc_page_size * * DESCRIPTION: * * Get the page-size being used by dmalloc. * * RETURNS: * * Page size. * * ARGUMENTS: * * None. */ extern unsigned int dmalloc_page_size(void); /* * unsigned long dmalloc_count_changed * * DESCRIPTION: * * Count the changed memory bytes since a particular mark. * * RETURNS: * * Number of bytes since mark. * * ARGUMENTS: * * mark -> Sets the point from which to count the changed memory. You * can use dmalloc_mark to get the current mark value which can later * be passed in here. Pass in 0 to report on the unfreed memory since * the program started. * * not_freed_b -> Set to 1 to count the new pointers that are non-freed. * * free_b -> Set to 1 to count the new pointers that are freed. */ extern unsigned long dmalloc_count_changed(const unsigned long mark, const int not_freed_b, const int free_b); /* * void dmalloc_log_status * * DESCRIPTION: * * Dump dmalloc statistics to logfile. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ extern void dmalloc_log_stats(void); /* * void dmalloc_log_unfreed * * DESCRIPTION: * * Dump unfreed-memory info to logfile. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ extern void dmalloc_log_unfreed(void); /* * void dmalloc_log_changed * * DESCRIPTION: * * Dump the pointers that have changed since a point in time. * * RETURNS: * * mark -> Sets the point to compare against. You can use * dmalloc_mark to get the current mark value which can later be * passed in here. Pass in 0 to log what has changed since the * program started. * * not_freed_b -> Set to 1 to log the new pointers that are non-freed. * * free_b -> Set to 1 to log the new pointers that are freed. * * details_b -> Set to 1 to dump the individual pointers that have * changed otherwise the summaries will be logged. */ extern void dmalloc_log_changed(const unsigned long mark, const int not_freed_b, const int free_b, const int details_b); /* * void dmalloc_vmessage * * DESCRIPTION: * * Message writer with vprintf like arguments which adds a line to the * dmalloc logfile. * * RETURNS: * * None. * * ARGUMENTS: * * format -> Printf-style format statement. * * args -> Already converted pointer to a stdarg list. */ extern void dmalloc_vmessage(const char *format, va_list args); /* * void dmalloc_message * * DESCRIPTION: * * Message writer with printf like arguments which adds a line to the * dmalloc logfile. * * RETURNS: * * None. * * ARGUMENTS: * * format -> Printf-style format statement. * * ... -> Variable argument list. */ extern void dmalloc_message(const char *format, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 1, 2))) #endif ; /* * void dmalloc_get_stats * * DESCRIPTION: * * Return a number of statistics about the current heap. * * RETURNS: * * None. * * ARGUMENTS: * * heap_low_p <- Pointer to pointer which, if not 0L, will be set to * the low address in the heap. * * heap_high_p <- Pointer to pointer which, if not 0L, will be set to * the high address in the heap. * * total_space_p <- Pointer to an unsigned long which, if not 0L, will * be set to the total space managed by the library including user * space, administrative space, and overhead. * * user_space_p <- Pointer to an unsigned long which, if not 0L, will * be set to the space given to the user process (allocated and free). * * current_allocated_p <- Pointer to an unsigned long which, if not * 0L, will be set to the current allocated space given to the user * process. * * current_pnt_np <- Pointer to an unsigned long which, if not 0L, * will be set to the current number of pointers allocated by the user * process. * * max_allocated_p <- Pointer to an unsigned long which, if not 0L, * will be set to the maximum allocated space given to the user * process. * * max_pnt_np <- Pointer to an unsigned long which, if not 0L, will be * set to the maximum number of pointers allocated by the user * process. * * max_one_p <- Pointer to an unsigned long which, if not 0L, will be * set to the maximum allocated with 1 call by the user process. */ extern void dmalloc_get_stats(DMALLOC_PNT *heap_low_p, DMALLOC_PNT *heap_high_p, unsigned long *total_space_p, unsigned long *user_space_p, unsigned long *current_allocated_p, unsigned long *current_pnt_np, unsigned long *max_allocated_p, unsigned long *max_pnt_np, unsigned long *max_one_p); /* * const char *dmalloc_strerror * * DESCRIPTION: * * Convert a dmalloc error code into its string equivalent. * * RETURNS: * * Success - String version of the error * * Failure - The string "unknown error" * * ARGUMENTS: * * error_num -> Error number we are converting. */ extern const char *dmalloc_strerror(const int error_num); #ifdef __cplusplus } #endif /* * alloc macros to provide for memory FILE/LINE debugging information. */ #ifndef DMALLOC_DISABLE #undef malloc #define malloc(size) \ dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0, 0) #undef calloc #define calloc(count, size) \ dmalloc_malloc(__FILE__, __LINE__, (count)*(size), DMALLOC_FUNC_CALLOC, 0, 0) #undef realloc #define realloc(ptr, size) \ dmalloc_realloc(__FILE__, __LINE__, (ptr), (size), DMALLOC_FUNC_REALLOC, 0) #undef recalloc #define recalloc(ptr, size) \ dmalloc_realloc(__FILE__, __LINE__, (ptr), (size), DMALLOC_FUNC_RECALLOC, 0) #undef memalign #define memalign(alignment, size) \ dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MEMALIGN, \ (alignment), 0 /* no xalloc */) #undef valloc #define valloc(size) \ dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_VALLOC, \ 0 /* special case */, 0 /* no xalloc */) #ifndef DMALLOC_STRDUP_MACRO #undef strdup #define strdup(str) \ dmalloc_strndup(__FILE__, __LINE__, (str), -1, 0) #endif #undef strndup #define strndup(str, len) \ dmalloc_strndup(__FILE__, __LINE__, (str), (len), 0) #undef free #define free(ptr) \ dmalloc_free(__FILE__, __LINE__, (ptr), DMALLOC_FUNC_FREE) #undef xmalloc #define xmalloc(size) \ dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0, 1) #undef xcalloc #define xcalloc(count, size) \ dmalloc_malloc(__FILE__, __LINE__, (count)*(size), DMALLOC_FUNC_CALLOC, 0, 1) #undef xrealloc #define xrealloc(ptr, size) \ dmalloc_realloc(__FILE__, __LINE__, (ptr), (size), DMALLOC_FUNC_REALLOC, 1) #undef xrecalloc #define xrecalloc(ptr, size) \ dmalloc_realloc(__FILE__, __LINE__, (ptr), (size), DMALLOC_FUNC_RECALLOC, 1) #undef xmemalign #define xmemalign(alignment, size) \ dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MEMALIGN, \ (alignment), 1) #undef xvalloc #define xvalloc(size) \ dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_VALLOC, 0, 1) #undef xstrdup #define xstrdup(str) \ dmalloc_strndup(__FILE__, __LINE__, (str), -1, 1) #undef xstrndup #define xstrndup(str, len) \ dmalloc_strndup(__FILE__, __LINE__, (str), (len), 1) #undef xfree #define xfree(ptr) \ dmalloc_free(__FILE__, __LINE__, (ptr), DMALLOC_FUNC_FREE) #ifdef DMALLOC_FUNC_CHECK /* * do debugging on the following functions. this may cause compilation or * other problems depending on your architecture. */ #undef atoi #define atoi(str) \ _dmalloc_atoi(__FILE__, __LINE__, (str)) #undef atol #define atol(str) \ _dmalloc_atol(__FILE__, __LINE__, (str)) #undef bcmp #define bcmp(b1, b2, len) \ _dmalloc_bcmp(__FILE__, __LINE__, (b1), (b2), (len)) #undef bcopy #define bcopy(from, to, len) \ _dmalloc_bcopy(__FILE__, __LINE__, (from), (to), (len)) #undef bzero #define bzero(buf, len) \ _dmalloc_bzero(__FILE__, __LINE__, (buf), (len)) #undef memcmp #define memcmp(b1, b2, len) \ _dmalloc_memcmp(__FILE__, __LINE__, (b1), (b2), (len)) #undef memcpy #define memcpy(to, from, len) \ _dmalloc_memcpy(__FILE__, __LINE__, (to), (from), (len)) #undef memmove #define memmove(to, from, len) \ _dmalloc_memmove(__FILE__, __LINE__, (to), (from), (len)) #undef memset #define memset(buf, ch, len) \ _dmalloc_memset(__FILE__, __LINE__, (buf), (ch), (len)) #undef index #define index(str, ch) \ _dmalloc_index(__FILE__, __LINE__, (str), (ch)) #undef rindex #define rindex(str, ch) \ _dmalloc_rindex(__FILE__, __LINE__, (str), (ch)) #undef strcat #define strcat(to, from) \ _dmalloc_strcat(__FILE__, __LINE__, (to), (from)) #undef strcmp #define strcmp(s1, s2) \ _dmalloc_strcmp(__FILE__, __LINE__, (s1), (s2)) #undef strlen #define strlen(str) \ _dmalloc_strlen(__FILE__, __LINE__, (str)) #undef strtok #define strtok(str, sep) \ _dmalloc_strtok(__FILE__, __LINE__, (str), (sep)) #undef memccpy #define memccpy(s1, s2, ch, len) \ _dmalloc_memccpy(__FILE__, __LINE__, (s1), (s2),(ch),(len)) #undef memchr #define memchr(s1, ch, len) \ _dmalloc_memchr(__FILE__, __LINE__, (s1), (ch), (len)) #undef strchr #define strchr(str, ch) \ _dmalloc_strchr(__FILE__, __LINE__, (str), (ch)) #undef strrchr #define strrchr(str, ch) \ _dmalloc_strrchr(__FILE__, __LINE__, (str), (ch)) #undef strcpy #define strcpy(to, from) \ _dmalloc_strcpy(__FILE__, __LINE__, (to), (from)) #undef strncpy #define strncpy(to, from, len) \ _dmalloc_strncpy(__FILE__, __LINE__, (to), (from), (len)) #undef strcasecmp #define strcasecmp(s1, s2) \ _dmalloc_strcasecmp(__FILE__, __LINE__, (s1), (s2)) #undef strncasecmp #define strncasecmp(s1, s2, len) \ _dmalloc_strncasecmp(__FILE__, __LINE__, (s1), (s2), (len)) #undef strspn #define strspn(str, list) \ _dmalloc_strspn(__FILE__, __LINE__, (str), (list)) #undef strcspn #define strcspn(str, list) \ _dmalloc_strcspn(__FILE__, __LINE__, (str), (list)) #undef strncat #define strncat(to, from, len) \ _dmalloc_strncat(__FILE__, __LINE__, (to), (from), (len)) #undef strncmp #define strncmp(s1, s2, len) \ _dmalloc_strncmp(__FILE__, __LINE__, (s1), (s2), (len)) #undef strpbrk #define strpbrk(str, list) \ _dmalloc_strpbrk(__FILE__, __LINE__, (str), (list)) #undef strstr #define strstr(str, pat) \ _dmalloc_strstr(__FILE__, __LINE__, (str), (pat)) #endif /* DMALLOC_FUNC_CHECK */ #endif /* ! DMALLOC_DISABLE */ /* * feel free to add your favorite functions here and to arg_check.[ch] */ #ifdef __cplusplus extern "C" { #endif /* * Dummy function for checking atoi's arguments. */ extern int _dmalloc_atoi(const char *file, const int line, const char *str); /* * Dummy function for checking atol's arguments. */ extern long _dmalloc_atol(const char *file, const int line, const char *str); /* * Dummy function for checking bcmp's arguments. */ extern int _dmalloc_bcmp(const char *file, const int line, const void *b1, const void *b2, const DMALLOC_SIZE len); /* * Dummy function for checking bcopy's arguments. */ extern void _dmalloc_bcopy(const char *file, const int line, const void *from, void *to, const DMALLOC_SIZE len); /* * Dummy function for checking bzero's arguments. */ extern void _dmalloc_bzero(const char *file, const int line, void *buf, const DMALLOC_SIZE len); /* * Dummy function for checking index's arguments. */ extern char *_dmalloc_index(const char *file, const int line, const char *str, const char ch); /* * Dummy function for checking memccpy's arguments. */ extern void *_dmalloc_memccpy(const char *file, const int line, void *dest, const void *src, const int ch, const DMALLOC_SIZE len); /* * Dummy function for checking memchr's arguments. */ extern void *_dmalloc_memchr(const char *file, const int line, const void *s1, const int ch, const DMALLOC_SIZE len); /* * Dummy function for checking memcmp's arguments. */ extern int _dmalloc_memcmp(const char *file, const int line, const void *b1, const void *b2, const DMALLOC_SIZE len); /* * Dummy function for checking memcpy's arguments. */ extern void *_dmalloc_memcpy(const char *file, const int line, void *to, const void *from, const DMALLOC_SIZE len); /* * Dummy function for checking memmove's arguments. */ extern void *_dmalloc_memmove(const char *file, const int line, void *to, const void *from, const DMALLOC_SIZE len); /* * Dummy function for checking memset's arguments. */ extern void *_dmalloc_memset(const char *file, const int line, void *buf, const int ch, const DMALLOC_SIZE len); /* * Dummy function for checking rindex's arguments. */ extern char *_dmalloc_rindex(const char *file, const int line, const char *str, const char ch); /* * Dummy function for checking strcasecmp's arguments. */ extern int _dmalloc_strcasecmp(const char *file, const int line, const char *s1, const char *s2); /* * Dummy function for checking strcat's arguments. */ extern char *_dmalloc_strcat(const char *file, const int line, char *to, const char *from); /* * Dummy function for checking strchr's arguments. */ extern char *_dmalloc_strchr(const char *file, const int line, const char *str, const int ch); /* * Dummy function for checking strcmp's arguments. */ extern int _dmalloc_strcmp(const char *file, const int line, const char *s1, const char *s2); /* * Dummy function for checking strcpy's arguments. */ extern char *_dmalloc_strcpy(const char *file, const int line, char *to, const char *from); /* * Dummy function for checking strcspn's arguments. */ extern int _dmalloc_strcspn(const char *file, const int line, const char *str, const char *list); /* * Dummy function for checking strlen's arguments. */ extern DMALLOC_SIZE _dmalloc_strlen(const char *file, const int line, const char *str); /* * Dummy function for checking strncasecmp's arguments. */ extern int _dmalloc_strncasecmp(const char *file, const int line, const char *s1, const char *s2, const DMALLOC_SIZE len); /* * Dummy function for checking strncat's arguments. */ extern char *_dmalloc_strncat(const char *file, const int line, char *to, const char *from, const DMALLOC_SIZE len); /* * Dummy function for checking strncmp's arguments. */ extern int _dmalloc_strncmp(const char *file, const int line, const char *s1, const char *s2, const DMALLOC_SIZE len); /* * Dummy function for checking strncpy's arguments. */ extern char *_dmalloc_strncpy(const char *file, const int line, char *to, const char *from, const DMALLOC_SIZE len); /* * Dummy function for checking strpbrk's arguments. */ extern char *_dmalloc_strpbrk(const char *file, const int line, const char *str, const char *list); /* * Dummy function for checking strrchr's arguments. */ extern char *_dmalloc_strrchr(const char *file, const int line, const char *str, const int ch); /* * Dummy function for checking strspn's arguments. */ extern int _dmalloc_strspn(const char *file, const int line, const char *str, const char *list); /* * Dummy function for checking strstr's arguments. */ extern char *_dmalloc_strstr(const char *file, const int line, const char *str, const char *pat); /* * Dummy function for checking strtok's arguments. */ extern char *_dmalloc_strtok(const char *file, const int line, char *str, const char *sep); #ifdef __cplusplus } #endif #endif /* ! __DMALLOC_H__ */ dmalloc-5.5.2/dmalloc_rand.c000644 001751 001751 00000005072 10622115666 015702 0ustar00graygray000000 000000 /* * Internal random number generator * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author of dmalloc may be contacted via http://dmalloc.com/ * * $Id: dmalloc_rand.c,v 1.3 2004/07/08 04:53:27 gray Exp $ */ /* * Minimal Standard Pseudo-Random Number Generator * * Author: Fuat C. Baran, Columbia University, 1988 * * Based on code in "Random Number Generators: Good Ones are Hard to * Find", by Stephen K. Park and Keith W. Miller in Communications of * the ACM, 31, 10 (Oct. 1988) pp. 1192-1201. * * Requirements: MAXINT must be 2 ^ 31 - 1 or larger * * Auto-seeding random number generator. Just start to call random * and it will take care of seeding, etc. */ #include "dmalloc_rand.h" #define MAGIC_A 16807 /* magic number */ #define MERSENNE_PRIME 2147483647UL /* mersenne prime 2^31 -1 */ #define MAGIC_QUOTIENT 127773 /* M div A (M / A) */ #define MAGIC_REMAINDER 2836 /* M mod A (M % A) */ /* local variables */ static long value = 0; /* our random value */ /* * static void auto_seed * * DESCRIPTION: * * Automatically seed the random number generation algorithm. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ static void auto_seed(void) { /* set the seed to a constant so we don't produce random addresses */ value = 0xDEADBEEF; } /* * static void _dmalloc_srand * * DESCRIPTION: * * Seed the random number generator with the user argument. * * RETURNS: * * None. * * ARGUMENTS: * * seed -> Value to seed the algorithm with. */ void _dmalloc_srand(const long seed) { value = seed; } /* * static long _dmalloc_rand * * DESCRIPTION: * * Get a pseudo-random number from the random algorithm. * * RETURNS: * * Random number. * * ARGUMENTS: * * None. */ long _dmalloc_rand(void) { if (value == 0) { auto_seed(); } /* do the magic seed calculation */ value = MAGIC_A * (value % MAGIC_QUOTIENT) - MAGIC_REMAINDER * (value / MAGIC_QUOTIENT); if (value <= 0) { value += MERSENNE_PRIME; } return value; } dmalloc-5.5.2/dmalloc_loc.h000640 001751 001751 00000004404 10622115666 015532 0ustar00graygray000000 000000 /* * Local definitions for the user allocation level * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc_loc.h,v 1.46 2000/05/16 18:35:57 gray Exp $ */ #ifndef __DMALLOC_LOC_H__ #define __DMALLOC_LOC_H__ #include "conf.h" /* for HAVE_BCMP and BASIC_BLOCK */ /* * env variable(s) */ #define OPTIONS_ENVIRON "DMALLOC_OPTIONS" /* * web home directory */ #define DMALLOC_HOME "http://dmalloc.com/" /* * generic constants */ /* special consideration for NULL. some compilers bitch if I redefine it */ #ifndef NULL #define NULL 0L #endif /* * standard i/o file descriptors */ #undef STDIN #define STDIN 0 /* fileno(stdin) */ #undef STDOUT #define STDOUT 1 /* fileno(stdout) */ #undef STDERR #define STDERR 2 /* fileno(stderr) */ /* * Default values for the file and line variables. */ #define DMALLOC_DEFAULT_FILE 0L #define DMALLOC_DEFAULT_LINE 0 /* * Min/max macros * * WARNING: these use their arguments multiple times which may be bad */ #undef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #undef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) /* * bitflag tools for Variable and a Flag */ #undef BIT_FLAG #define BIT_FLAG(x) (1 << (x)) #undef BIT_SET #define BIT_SET(v,f) (v) |= (f) #undef BIT_CLEAR #define BIT_CLEAR(v,f) (v) &= ~(f) #undef BIT_IS_SET #define BIT_IS_SET(v,f) ((v) & (f)) /* * set pointer macro */ #define SET_POINTER(pnt, val) \ do { \ if ((pnt) != NULL) { \ (*(pnt)) = (val); \ } \ } while(0) /* * Global malloc defines */ #define BLOCK_SIZE (int)(1 << BASIC_BLOCK) /* size of a block */ #endif /* ! __DMALLOC_LOC_H__ */ dmalloc-5.5.2/dmalloc.h.1000640 001751 001751 00000001545 10622115666 015037 0ustar00graygray000000 000000 /* * Defines for the dmalloc library * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for any * purpose and without fee is hereby granted, provided * that the above copyright notice and this permission notice appear * in all copies, and that the name of Gray Watson not be used in * advertising or publicity pertaining to distribution of the document * or software without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc.h.1,v 1.13 2000/03/21 18:19:10 gray Exp $ */ #ifndef __DMALLOC_H__ #define __DMALLOC_H__ dmalloc-5.5.2/dmalloc.c000640 001751 001751 00000070445 10622115666 014700 0ustar00graygray000000 000000 /* * program that handles the dmalloc variables. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: dmalloc.c,v 1.120 2007/05/14 17:09:20 gray Exp $ */ /* * This is the dmalloc program which is designed to enable the user to * easily set the environmental variables that control the dmalloc * library capabilities. */ /* * NOTE: all standard-output from this program is designed to be run * through a shell evaluation command by default. Any messages for * the user should therefore be send to stderr. */ #include /* for stderr */ #define DMALLOC_DISABLE #if HAVE_STRING_H # include #endif #if HAVE_STDLIB_H # include #endif #include "conf.h" #include "dmalloc_argv.h" /* for argument processing */ #include "dmalloc.h" #include "compat.h" #include "debug_tok.h" #include "debug_tok.h" #include "env.h" #include "error_val.h" #include "dmalloc_loc.h" #include "version.h" #define HOME_ENVIRON "HOME" /* home directory */ #define SHELL_ENVIRON "SHELL" /* for the type of shell */ #define DEFAULT_CONFIG ".dmallocrc" /* default config file */ #define TOKENIZE_EQUALS " \t=" /* for tag lines */ #define TOKENIZE_CHARS " \t," /* for tag lines */ #define DEBUG_ARG 'd' /* debug argument */ #define INTERVAL_ARG 'i' /* interval argument */ #define THREAD_LOCK_ON_ARG 'o' /* lock-on argument */ #define LIMIT_ARG 'M' /* memory-limit argument */ #define LINE_WIDTH 75 /* num debug toks per line */ #define FILE_NOT_FOUND 1 #define FILE_FOUND 2 #define TOKEN_FOUND 3 /* * default flag information */ typedef struct { char *de_string; /* default name */ long de_flags; /* default settings */ } default_t; #define RUNTIME_FLAGS (DEBUG_LOG_STATS | DEBUG_LOG_NONFREE | \ DEBUG_LOG_BAD_SPACE | \ DEBUG_CHECK_FENCE | \ DEBUG_CATCH_NULL) #define LOW_FLAGS (RUNTIME_FLAGS | \ DEBUG_LOG_ELAPSED_TIME | \ DEBUG_CHECK_SHUTDOWN | \ DEBUG_FREE_BLANK | DEBUG_ERROR_ABORT | \ DEBUG_ALLOC_BLANK) #define MEDIUM_FLAGS (LOW_FLAGS | \ DEBUG_CHECK_HEAP | \ DEBUG_REALLOC_COPY) #define HIGH_FLAGS (MEDIUM_FLAGS | \ DEBUG_CHECK_BLANK | DEBUG_CHECK_FUNCS) #define ALL_FLAGS (HIGH_FLAGS | \ DEBUG_LOG_TRANS | DEBUG_LOG_ADMIN | \ DEBUG_NEVER_REUSE) /* NOTE: print-messages is not in this list because it is special */ static default_t defaults[] = { { "none", 0 }, { "runtime", RUNTIME_FLAGS }, { "run", RUNTIME_FLAGS }, { "low", LOW_FLAGS }, { "med", MEDIUM_FLAGS }, { "medium", MEDIUM_FLAGS }, { "high", HIGH_FLAGS }, { "all", ALL_FLAGS }, { NULL } }; /* argument variables */ static int bourne_b = 0; /* set bourne shell output */ static int cshell_b = 0; /* set c-shell output */ static int gdb_b = 0; /* set gdb output */ static int rcshell_b = 0; /* set rc shell output */ static char *address = NULL; /* for ADDRESS */ static int clear_b = 0; /* clear variables */ static int debug = 0; /* for DEBUG */ static int errno_to_print = 0; /* to print the error string */ static int help_b = 0; /* print help message */ static char *inpath = NULL; /* for config-file path */ static unsigned long interval = 0; /* for setting INTERVAL */ static int thread_lock_on = 0; /* for setting LOCK_ON */ static int keep_b = 0; /* keep settings override -r */ static int list_tags_b = 0; /* list rc tags */ static int debug_tokens_b = 0; /* list debug tokens */ static char *logpath = NULL; /* for LOGFILE setting */ static int long_tokens_b = 0; /* long-tok output */ static argv_array_t minus; /* tokens to remove */ static unsigned long limit_arg = 0; /* memory limit */ static int make_changes_b = 1; /* make no changes to env */ static argv_array_t plus; /* tokens to add */ static int remove_auto_b = 0; /* auto-remove settings */ static char *start_file = NULL; /* for START settings */ static unsigned long start_iter = 0; /* for START settings */ static unsigned long start_size = 0; /* for START settings */ static int usage_b = 0; /* usage messages */ static int verbose_b = 0; /* verbose flag */ static int very_verbose_b = 0; /* very-verbose flag */ static int version_b = 0; /* print version string */ static char *tag = NULL; /* maybe a tag argument */ static argv_t args[] = { { 'b', "bourne-shell", ARGV_BOOL_INT, &bourne_b, NULL, "set output for bourne shells" }, { ARGV_OR }, { 'C', "c-shell", ARGV_BOOL_INT, &cshell_b, NULL, "set output for C-type shells" }, { ARGV_OR }, { 'g', "gdb", ARGV_BOOL_INT, &gdb_b, NULL, "set output for gdb parsing" }, { ARGV_OR }, { 'R', "rc-shell", ARGV_BOOL_INT, &rcshell_b, NULL, "set output for rc shell" }, { 'a', "address", ARGV_CHAR_P, &address, "address:#", "stop when malloc sees address" }, { 'c', "clear", ARGV_BOOL_INT, &clear_b, NULL, "clear all variables not set" }, { DEBUG_ARG, "debug-mask", ARGV_HEX, &debug, "value", "hex flag to set debug mask" }, { 'D', "debug-tokens", ARGV_BOOL_INT, &debug_tokens_b, NULL, "list debug tokens" }, { 'e', "errno", ARGV_INT, &errno_to_print, "errno", "print error string for errno" }, { 'f', "file", ARGV_CHAR_P, &inpath, "path", "config if not $HOME/.dmallocrc" }, { 'h', "help", ARGV_BOOL_INT, &help_b, NULL, "print help message" }, { INTERVAL_ARG, "interval", ARGV_U_LONG, &interval, "value", "check heap every number times" }, { 'k', "keep", ARGV_BOOL_INT, &keep_b, NULL, "keep settings (override -r)" }, { 'l', "logfile", ARGV_CHAR_P, &logpath, "path", "file to log messages to" }, { 'L', "long-tokens", ARGV_BOOL_INT, &long_tokens_b, NULL, "set env with tokens not 0x..." }, { 'm', "minus", ARGV_CHAR_P | ARGV_FLAG_ARRAY, &minus, "token(s)", "del tokens from current debug" }, { LIMIT_ARG, "memory-limit", ARGV_U_SIZE, &limit_arg, "value", "limit allocations to this amount" }, { 'n', "no-changes", ARGV_BOOL_NEG, &make_changes_b, NULL, "make no changes to the env" }, { THREAD_LOCK_ON_ARG, "lock-on", ARGV_INT, &thread_lock_on, "number", "number of times to not lock" }, { 'p', "plus", ARGV_CHAR_P | ARGV_FLAG_ARRAY, &plus, "token(s)", "add tokens to current debug" }, { 'r', "remove", ARGV_BOOL_INT, &remove_auto_b, NULL, "remove other settings if tag" }, { 's', "start-file", ARGV_CHAR_P, &start_file, "file:line", "check heap after this location" }, { ARGV_OR }, { 'S', "start-iter", ARGV_U_LONG, &start_iter, "number", "check heap after this iteration" }, { ARGV_OR }, { '\0', "start-size", ARGV_U_SIZE, &start_size, "size", "check heap after this mem size" }, { 't', "list-tags", ARGV_BOOL_INT, &list_tags_b, NULL, "list tags in rc file" }, { 'u', "usage", ARGV_BOOL_INT, &usage_b, NULL, "print usage messages" }, { 'v', "verbose", ARGV_BOOL_INT, &verbose_b, NULL, "turn on verbose output" }, { 'V', "very-verbose", ARGV_BOOL_INT, &very_verbose_b, NULL, "turn on very-verbose output" }, { '\0', "version", ARGV_BOOL_INT, &version_b, NULL, "display version string" }, { ARGV_MAYBE, NULL, ARGV_CHAR_P, &tag, "tag", "debug token, internal or from rc file" }, { ARGV_LAST } }; /* * list of bourne shells */ static char *sh_shells[] = { "sh", "ash", "bash", "ksh", "zsh", NULL }; /* * try a check out the shell env variable to see what form of shell * commands we should output */ static void choose_shell(void) { const char *shell, *shell_p; int shell_c; shell = getenv(SHELL_ENVIRON); if (shell == NULL) { /* oh well, we just guess on c-shell */ cshell_b = 1; return; } shell_p = strrchr(shell, '/'); if (shell_p == NULL) { shell_p = shell; } else { shell_p++; } /* look for the rc shell specifically */ if (strcmp("rc", shell_p) == 0) { rcshell_b = 1; return; } /* look for the shells which are bourne-shell compatible */ for (shell_c = 0; sh_shells[shell_c] != NULL; shell_c++) { if (strcmp(sh_shells[shell_c], shell_p) == 0) { bourne_b = 1; return; } } /* otherwise set to c-shell */ cshell_b = 1; } /* * dump the current flags set in the debug variable VAL */ static void dump_debug(const unsigned long val) { attr_t *attr_p; char *str; unsigned long work = val; int col_c = 0, len; for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) { /* the below test for work == 0 is necessary to handle the 'none' token */ if ((work == 0 && attr_p->at_value == 0) || (attr_p->at_value != 0 && BIT_IS_SET(work, attr_p->at_value))) { BIT_CLEAR(work, attr_p->at_value); if (col_c == 0) { (void)fprintf(stderr, " "); col_c += 3; } if (very_verbose_b) { (void)fprintf(stderr, "%s -- %s (%#lx)\n", attr_p->at_string, attr_p->at_desc, attr_p->at_value); col_c = 0; } else { str = attr_p->at_string; len = strlen(str); if (col_c + len + 2 > LINE_WIDTH) { (void)fprintf(stderr, "\n"); (void)fprintf(stderr, " "); col_c = 3; } (void)fprintf(stderr, "%s", str); col_c += len; /* if we've got more to go then print the , */ if (work != 0) { (void)fprintf(stderr, ", "); col_c += 2; } } if (work == 0) { break; } } } if (col_c != 0) { (void)fprintf(stderr, "\n"); } if (work != 0) { (void)fprintf(stderr, "%s: warning, unknown debug flag(s): %#lx\n", argv_program, work); } } /* * translate TOK into its proper value which is returned */ static long token_to_value(const char *tok) { attr_t *attr_p; /* find the matching attribute string */ for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) { if (strcmp(tok, attr_p->at_string) == 0) { break; } } if (attr_p->at_string == NULL) { (void)fprintf(stderr, "%s: unknown token '%s'\n", argv_program, tok); return 0; } /* if we have a 0 value and not none then this is a disabled token */ if (attr_p->at_value == 0 && strcmp(tok, "none") != 0) { (void)fprintf(stderr, "%s: token '%s' has been disabled: %s\n", argv_program, tok, attr_p->at_desc); return 0; } return attr_p->at_value; } /* * Read in the next token from INFILE. It passes back the returned * debug value in DEBUG_P. Passes back the matching TOKEN of * TOKEN_SIZE. Returns 1 if there was a next else 0. */ static int read_next_token(FILE *infile, long *debug_p, char *token, const int token_size) { int cont_b = 0, found_b = 0; long new_debug = 0; char buf[1024], *tok_p, *buf_p; while (fgets(buf, sizeof(buf), infile) != NULL) { /* ignore comments and empty lines */ if (buf[0] == '#' || buf[0] == '\n') { continue; } /* chop off the ending \n */ buf_p = strrchr(buf, '\n'); SET_POINTER(buf_p, '\0'); buf_p = buf; /* if we're not continuing then we need to process a tag */ if (! cont_b) { /* get the first token on the line */ tok_p = strsep(&buf_p, TOKENIZE_EQUALS); if (tok_p == NULL) { continue; } if (*tok_p == '\0') { (void)fprintf(stderr, "Invalid start of line: %s\n", buf_p); continue; } /* save the token */ if (token != NULL) { (void)strncpy(token, tok_p, token_size); token[token_size - 1] = '\0'; } found_b = 1; } cont_b = 0; while (1) { /* get the next token */ tok_p = strsep(&buf_p, TOKENIZE_CHARS); if (tok_p == NULL) { break; } if (*tok_p == '\0') { continue; } /* do we have a continuation character? */ if (strcmp(tok_p, "\\") == 0) { cont_b = 1; break; } new_debug |= token_to_value(tok_p); } /* are we done? */ if (! cont_b) { break; } } SET_POINTER(debug_p, new_debug); if (found_b) { return 1; } else { return 0; } } /* * Read in a rc file from PATH and process it looking for the * specified DEBUG_VALUE or TAG_FIND token. It passes back the * returned debug value in DEBUG_P. Passes back the matching TOKEN of * TOKEN_SIZE. * * Returns FILE_NOT_FOUND, FILE_FOUND, or TOKEN_FOUND. */ static int read_rc_file(const char *path, const long debug_value, const char *tag_find, long *debug_p, char *token, const int token_size) { FILE *infile; int found_b = 0; char next_token[64]; long new_debug; /* open the path */ infile = fopen(path, "r"); if (infile == NULL) { return FILE_NOT_FOUND; } /* run through the tokens, looking for a match */ while (read_next_token(infile, &new_debug, next_token, sizeof(next_token)) == 1) { /* are we looking for a tag? */ if (tag_find != NULL && strcmp(tag_find, next_token) == 0) { found_b = 1; break; } /* are we looking for a debug-value? */ if (debug_value > 0 && debug_value == new_debug) { found_b = 1; break; } } (void)fclose(infile); SET_POINTER(debug_p, new_debug); if (token != NULL) { (void)loc_snprintf(token, token_size, "config file token: %s", next_token); } if (found_b) { return TOKEN_FOUND; } else { return FILE_FOUND; } } /* * Process the user configuration looking for the TAG_FIND. If it is * null then look for DEBUG_VALUE in the file and copy the token found * into TOKEN of TOKEN_SIZE. Routine returns the new debug value * matching tag. */ static long find_tag(const long debug_value, const char *tag_find, char *token, const int token_size) { char path[1024], *path_p; default_t *def_p; const char *home_p; int ret; long new_debug = 0; /* do we need to have a home variable? */ if (inpath == NULL) { /* first we try to read the RC file from the current directory */ ret = read_rc_file(DEFAULT_CONFIG, debug_value, tag_find, &new_debug, token, token_size); /* did we find the correct value in the file? */ if (ret == TOKEN_FOUND) { return new_debug; } /* if we did not find the file, check the home directory */ if (ret == FILE_FOUND) { path_p = DEFAULT_CONFIG; } else { /* find our home directory */ home_p = getenv(HOME_ENVIRON); if (home_p == NULL) { (void)fprintf(stderr, "%s: could not find variable '%s'\n", argv_program, HOME_ENVIRON); exit(1); } (void)loc_snprintf(path, sizeof(path), "%s/%s", home_p, DEFAULT_CONFIG); /* read in the file from our home directory */ ret = read_rc_file(path, debug_value, tag_find, &new_debug, token, token_size); /* did we find the correct value in the file? */ if (ret == TOKEN_FOUND) { return new_debug; } if (ret == FILE_FOUND) { path_p = path; } else { path_p = NULL; } } } else { /* read in the specified file */ ret = read_rc_file(inpath, debug_value, tag_find, &new_debug, token, token_size); /* did we find the correct value in the file? */ if (ret == TOKEN_FOUND) { return new_debug; } /* if the specified was not found, return error */ if (ret != FILE_FOUND) { (void)fprintf(stderr, "%s: could not read '%s': ", argv_program, inpath); perror(""); exit(1); } path_p = inpath; } /* if tag-find is NULL we assume we are looking for a debug-value */ if (tag_find == NULL) { /* now look for the value in the default token list */ if (token != NULL) { for (def_p = defaults; def_p->de_string != NULL; def_p++) { if (def_p->de_flags == debug_value) { (void)loc_snprintf(token, token_size, "internal token: %s", def_p->de_string); new_debug = def_p->de_flags; break; } } if (def_p->de_string == NULL) { (void)loc_snprintf(token, token_size, "unknown token"); new_debug = 0; } } } else { /* now look for the token in the default token list */ for (def_p = defaults; def_p->de_string != NULL; def_p++) { if (strcmp(tag_find, def_p->de_string) == 0) { new_debug = def_p->de_flags; break; } } /* did we not find the token? */ if (def_p->de_string == NULL) { if (path_p == NULL) { (void)fprintf(stderr, "%s: unknown tag '%s'\n", argv_program, tag_find); } else { (void)fprintf(stderr, "%s: could not find tag '%s' in '%s'\n", argv_program, tag_find, path_p); } exit(1); } } return new_debug; } /* * List the tags that in the files. */ static void list_tags(void) { char path[1024], *path_p, token[80]; default_t *def_p; const char *home_p; long new_debug = 0; FILE *rc_file; /* do we need to have a home variable? */ if (inpath == NULL) { /* first we try to read the RC file from the current directory */ rc_file = fopen(DEFAULT_CONFIG, "r"); if (rc_file == NULL) { /* if no file in current directory, try home directory */ home_p = getenv(HOME_ENVIRON); if (home_p == NULL) { (void)fprintf(stderr, "%s: could not find variable '%s'\n", argv_program, HOME_ENVIRON); exit(1); } (void)loc_snprintf(path, sizeof(path), "%s/%s", home_p, DEFAULT_CONFIG); path_p = path; rc_file = fopen(path, "r"); /* we don't check for error right here */ } else { path_p = DEFAULT_CONFIG; } } else { /* open the specified file */ rc_file = fopen(inpath, "r"); /* we assume that if the file was specified, it must be there */ if (rc_file == NULL) { (void)fprintf(stderr, "%s: could not read '%s': ", argv_program, inpath); perror(""); exit(1); } path_p = inpath; } if (rc_file != NULL) { (void)fprintf(stderr, "Tags available from '%s':\n", path_p); while (read_next_token(rc_file, &new_debug, token, sizeof(token)) == 1) { if (verbose_b) { (void)fprintf(stderr, "%s (%#lx):\n", token, new_debug); dump_debug(new_debug); } else { (void)fprintf(stderr, "%s\n", token); } } (void)fclose(rc_file); } (void)fprintf(stderr, "\n"); (void)fprintf(stderr, "Tags available by default:\n"); for (def_p = defaults; def_p->de_string != NULL; def_p++) { if (verbose_b) { (void)fprintf(stderr, "%s (%#lx):\n", def_p->de_string, def_p->de_flags); dump_debug(def_p->de_flags); } else { (void)fprintf(stderr, "%s\n", def_p->de_string); } } } /* * dump the current settings of the malloc variables */ static void dump_current(void) { char *log_path, *loc_start_file, token[64]; const char *env_str; DMALLOC_PNT addr; unsigned long inter, limit_val, loc_start_size, loc_start_iter; long addr_count; int lock_on, loc_start_line; unsigned int flags; /* get the options flag */ env_str = getenv(OPTIONS_ENVIRON); if (env_str == NULL) { env_str = ""; } _dmalloc_environ_process(env_str, &addr, &addr_count, &flags, &inter, &lock_on, &log_path, &loc_start_file, &loc_start_line, &loc_start_iter, &loc_start_size, &limit_val); if (flags == 0) { (void)fprintf(stderr, "Debug-Flags not-set\n"); } else { (void)find_tag(flags, NULL, token, sizeof(token)); (void)fprintf(stderr, "Debug-Flags %#x (%u) (%s)\n", flags, flags, token); if (verbose_b) { dump_debug(flags); } } if (addr == NULL) { (void)fprintf(stderr, "Address not-set\n"); } else { if (addr_count == 0) { (void)fprintf(stderr, "Address %#lx\n", (long)addr); } else { (void)fprintf(stderr, "Address %#lx, count = %lu\n", (long)addr, addr_count); } } if (inter == 0) { (void)fprintf(stderr, "Interval not-set\n"); } else { (void)fprintf(stderr, "Interval %lu\n", inter); } if (lock_on == 0) { (void)fprintf(stderr, "Lock-On not-set\n"); } else { (void)fprintf(stderr, "Lock-On %d\n", lock_on); } if (log_path == NULL) { (void)fprintf(stderr, "Logpath not-set\n"); } else { (void)fprintf(stderr, "Logpath '%s'\n", log_path); } if (limit_val == 0) { (void)fprintf(stderr, "Mem-Limit not-set\n"); } else { (void)fprintf(stderr, "Mem-Limit %lu\n", limit_val); } if (loc_start_file != NULL) { (void)fprintf(stderr, "Start-File '%s', line = %d\n", loc_start_file, loc_start_line); } else if (loc_start_iter > 0) { (void)fprintf(stderr, "Start-Count %lu\n", loc_start_iter); } else if (loc_start_size > 0) { (void)fprintf(stderr, "Start-Size %lu\n", loc_start_size); } else { (void)fprintf(stderr, "Start not-set\n"); } (void)fprintf(stderr, "\n"); (void)fprintf(stderr, "Debug Malloc Utility: http://dmalloc.com/\n"); (void)fprintf(stderr, " For a list of the command-line options enter: %s --usage\n", argv_argv[0]); } /* * output the code to set env VAR to VALUE */ static void set_variable(const char *var, const char *value) { char comm[1024]; if (value == NULL || *value == '\0') { (void)loc_snprintf(comm, sizeof(comm), "unset %s\n", var); } else if (bourne_b) { (void)loc_snprintf(comm, sizeof(comm), "%s=%s\nexport %s\n", var, value, var); } else if (rcshell_b) { (void)loc_snprintf(comm, sizeof(comm), "%s='%s'\n", var, value); } else if (gdb_b) { (void)loc_snprintf(comm, sizeof(comm), "set env %s %s\n", var, value); } else { (void)loc_snprintf(comm, sizeof(comm), "setenv %s %s\n", var, value); } if (make_changes_b) { (void)printf("%s", comm); } if ((! make_changes_b) || verbose_b) { (void)fprintf(stderr, "Outputed:\n"); (void)fprintf(stderr, "%s", comm); } } /* * Returns the string for ERROR_NUM. */ static char *local_strerror(const int error_num) { error_str_t *err_p; for (err_p = error_list; err_p->es_error != 0; err_p++) { if (err_p->es_error == error_num) { return err_p->es_string; } } return INVALID_ERROR; } /* * static void header * * DESCRIPTION: * * Print out a little usage header to the user. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ static void header(void) { (void)fprintf(stderr, "Debug Malloc Utility: http://dmalloc.com/\n"); (void)fprintf(stderr, " This utility helps set the Debug Malloc environment variables.\n"); } int main(int argc, char **argv) { char buf[1024]; int set_b = 0; char *log_path, *loc_start_file; const char *env_str; DMALLOC_PNT addr; unsigned long inter, limit_val, loc_start_size, loc_start_iter; unsigned long addr_count; int lock_on; int loc_start_line; unsigned int flags; argv_help_string = "Sets dmalloc library env variables. Also try --usage."; argv_version_string = dmalloc_version; argv_usage_type = ARGV_USAGE_LONG; argv_error_type = ARGV_USAGE_SHORT_REM; argv_process(args, argc, argv); if (help_b) { header(); (void)fprintf(stderr, " For a list of the command-line options enter: %s --usage\n", argv_argv[0]); exit(0); } if (usage_b) { header(); argv_usage(args, argv_usage_type); exit(0); } if (version_b) { (void)fprintf(stderr, "Dmalloc utility version string is: %s\n", argv_version_string); (void)fprintf(stderr, " NOTE: Library linked with your application may be a different version.\n"); (void)fprintf(stderr, " Check top of logfile after application is run for library version.\n"); exit(0); } if (very_verbose_b) { verbose_b = 1; } /* try to figure out the shell we are using */ if ((! bourne_b) && (! cshell_b) && (! gdb_b) && (! rcshell_b)) { choose_shell(); } /* get the current debug information from the env variable */ env_str = getenv(OPTIONS_ENVIRON); if (env_str == NULL) { env_str = ""; } _dmalloc_environ_process(env_str, &addr, &addr_count, &flags, &inter, &lock_on, &log_path, &loc_start_file, &loc_start_line, &loc_start_iter, &loc_start_size, &limit_val); /* * So, if a tag was specified on the command line then we set the * debug from it. If it was not then we see if the debug flags were * set as a hex value from the -d. If this was not used then take * the current value. */ if (tag == NULL) { if (argv_was_used(args, DEBUG_ARG)) { set_b = 1; /* should we clear the rest? */ if (remove_auto_b && (! keep_b)) { clear_b = 1; } } else { debug = flags; } } else { if (argv_was_used(args, DEBUG_ARG)) { (void)fprintf(stderr, "%s: warning -d ignored, processing tag '%s'\n", argv_program, tag); } set_b = 1; debug = find_tag(0L, tag, NULL, 0); /* should we clear the rest? */ if (remove_auto_b && (! keep_b)) { clear_b = 1; } } if (plus.aa_entry_n > 0) { int plus_c; for (plus_c = 0; plus_c < plus.aa_entry_n; plus_c++) { BIT_SET(debug, token_to_value(ARGV_ARRAY_ENTRY(plus, char *, plus_c))); set_b = 1; } } if (minus.aa_entry_n > 0) { int minus_c; for (minus_c = 0; minus_c < minus.aa_entry_n; minus_c++) { BIT_CLEAR(debug, token_to_value(ARGV_ARRAY_ENTRY(minus, char *, minus_c))); set_b = 1; } } if (address != NULL) { _dmalloc_address_break(address, &addr, &addr_count); set_b = 1; } else if (clear_b) { addr = NULL; } if (argv_was_used(args, INTERVAL_ARG)) { inter = interval; set_b = 1; } else if (clear_b) { inter = 0; } /* * NOTE: this should be after the debug setting which this tests. */ if (argv_was_used(args, THREAD_LOCK_ON_ARG)) { lock_on = thread_lock_on; set_b = 1; } else if (clear_b) { lock_on = 0; } if (logpath != NULL) { log_path = logpath; set_b = 1; } else if (clear_b) { log_path = NULL; } if (start_file != NULL) { _dmalloc_start_break(start_file, &loc_start_file, &loc_start_line, &loc_start_iter, &loc_start_size); set_b = 1; } else if (start_iter > 0) { loc_start_file = NULL; loc_start_line = 0; loc_start_iter = start_iter; loc_start_size = 0; set_b = 1; } else if (start_size > 0) { loc_start_file = NULL; loc_start_line = 0; loc_start_iter = 0; loc_start_size = start_size; set_b = 1; } else if (clear_b) { loc_start_file = NULL; loc_start_line = 0; loc_start_iter = 0; loc_start_size = 0; } if (argv_was_used(args, LIMIT_ARG)) { limit_val = limit_arg; set_b = 1; } if (errno_to_print > 0) { (void)fprintf(stderr, "%s: dmalloc_errno value '%d' = \n", argv_program, errno_to_print); (void)fprintf(stderr, " '%s'\n", local_strerror(errno_to_print)); } if (list_tags_b) { list_tags(); } if (debug_tokens_b) { attr_t *attr_p; unsigned int left = 0x7fffffff; (void)fprintf(stderr, "Debug Tokens:\n"); for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) { /* skip any disabled tokens */ if (attr_p->at_value == 0 && strcmp(attr_p->at_string, "none") != 0) { continue; } if (attr_p->at_value != 0 && (! BIT_IS_SET(left, attr_p->at_value))) { /* skip any tokens we've seen before */ continue; } if (very_verbose_b) { (void)fprintf(stderr, "%s -- %s (%#lx)\n", attr_p->at_string, attr_p->at_desc, attr_p->at_value); } else if (verbose_b) { (void)fprintf(stderr, "%s -- %s\n", attr_p->at_string, attr_p->at_desc); } else { (void)fprintf(stderr, "%s\n", attr_p->at_string); } BIT_CLEAR(left, attr_p->at_value); } } if (clear_b || set_b) { _dmalloc_environ_set(buf, sizeof(buf), long_tokens_b, addr, addr_count, debug, inter, lock_on, log_path, loc_start_file, loc_start_line, loc_start_iter, loc_start_size, limit_val); set_variable(OPTIONS_ENVIRON, buf); } else if (errno_to_print == 0 && (! list_tags_b) && (! debug_tokens_b)) { dump_current(); } argv_cleanup(args); exit(0); } dmalloc-5.5.2/malloc.c000640 001751 001751 00000144236 10622115666 014534 0ustar00graygray000000 000000 /* * user-level memory-allocation routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: malloc.c,v 1.189 2007/03/25 18:53:41 gray Exp $ */ /* * This file contains the user-level calls to the memory allocation * routines. It handles a lot of the miscellaneous support garbage for * chunk.c which is the real heap manager. */ #include /* for sprintf sometimes */ #if HAVE_STDLIB_H # include /* for atexit */ #endif #if HAVE_STRING_H # include /* for strlen */ #endif #if HAVE_UNISTD_H # include /* for write */ #endif /* * cygwin includes */ #if HAVE_SYS_CYGWIN_H # include #endif #if HAVE_STDARG_H # include #endif #if HAVE_W32API_WINDEF_H # include #endif #if HAVE_W32API_WINBASE_H # include #endif #include "conf.h" /* up here for _INCLUDE */ #if LOG_PNT_TIMEVAL # ifdef TIMEVAL_INCLUDE # include TIMEVAL_INCLUDE # endif #else # if HAVE_TIME /* NOT LOG_PNT_TIME */ # ifdef TIME_INCLUDE # include TIME_INCLUDE # endif # endif #endif #if LOCK_THREADS #if HAVE_PTHREAD_H #include #endif #if HAVE_PTHREADS_H #include #endif #endif #if SIGNAL_OKAY && HAVE_SIGNAL_H #include #endif #define DMALLOC_DISABLE #include "dmalloc.h" #include "chunk.h" #include "compat.h" #include "debug_tok.h" #include "env.h" #include "error.h" #include "error_val.h" #include "heap.h" #include "dmalloc_loc.h" #include "malloc_funcs.h" #include "return.h" #if LOCK_THREADS #if IDENT_WORKS #ident "@(#) $Information: lock-threads is enabled $" #else static char *information = "@(#) $Information: lock-threads is enabled $"; #endif #endif /* exported variables */ /* internal dmalloc error number for reference purposes only */ int dmalloc_errno = ERROR_NONE; /* logfile for dumping dmalloc info, DMALLOC_LOGFILE env var overrides this */ char *dmalloc_logpath = NULL; /* local variables */ static int enabled_b = 0; /* have we started yet? */ static int in_alloc_b = 0; /* can't be here twice */ static int do_shutdown_b = 0; /* execute shutdown soon */ static int memalign_warn_b = 0; /* memalign warning printed?*/ static dmalloc_track_t tracking_func = NULL; /* memory trxn tracking func */ /* debug variables */ static char *start_file = NULL; /* file to start at */ static int start_line = 0; /* line to start */ static unsigned long start_iter = 0; /* start after X iterations */ static unsigned long start_size = 0; /* start after X bytes */ static int thread_lock_c = 0; /* lock counter */ /****************************** thread locking *******************************/ #if LOCK_THREADS #ifdef THREAD_MUTEX_T /* * Define a global variable we use as a lock counter. * * NOTE: we do not use the PTHREAD_MUTEX_INITIALIZER since this * basically delays the pthread_mutex_init call to when * pthread_mutex_lock is called for the first time (at least on * freebsd). Since we don't want to go recursive into the pthread * library when we go to lock our mutex variable, we want to force the * initialization to happen beforehand with a call to * pthread_mute_init. */ static THREAD_MUTEX_T dmalloc_mutex; #else #error We need to have THREAD_MUTEX_T defined by the configure script #endif #endif /* * THREADS LOCKING: * * Because we need to protect for multiple threads making calls into * the dmalloc library at the same time, we need to initialize and use * a thread mutex variable. The problem is that most thread libraries * uses malloc itself and do not like to go recursive. * * There are two places where we may have this problem. One is when * we try to use our mutex-lock variable when pthreads is starting up * in a shaky state. The thread library allocates some space, the * dmalloc library needs to lock its mutex variable so calls back into * the pthread library before it is ready for a call, and a core dump * is probably the result. * * We hopefully solve this by having the dmalloc library not lock * during the first couple of memory transactions. The number is * controlled by lock-on dmalloc program environmental setting (set * with ``dmalloc -o X''). You will have to play with the value. Too * many will cause two threads to march into the dmalloc code at the * same time generating a ERROR_IN_TWICE error. Too few and you will * get a core dump in the pthreads initialization code. * * The second place where we might go recursive is when we go to * actually initialize our mutex-lock before we can use it. The * THREAD_INIT_LOCK variable (in settings.h) defines that the * initialization happens 2 memory transactions before the library * begins to use the mutex (lock-on - 2). It we waited to initialize * the variable right before we used it, the pthread library might * want to allocate some memory for the variable causing a recursive * call and probably a seg-fault -- at least in OSF. If people need * to have this variable also be runtime configurable or would like to * present an alternative default, please let me know. */ #if LOCK_THREADS /* * mutex lock the malloc library */ static void lock_thread(void) { /* we only lock if the lock-on counter has reached 0 */ if (thread_lock_c == 0) { #if HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&dmalloc_mutex); #endif } } /* * mutex unlock the malloc library */ static void unlock_thread(void) { /* if the lock-on counter has not reached 0 then count it down */ if (thread_lock_c > 0) { thread_lock_c--; /* * As we approach the time when we start mutex locking the * library, we need to init the mutex variable. This sets how * many times before we start locking should we init the variable * taking in account that the init itself might generate a call * into the library. Ugh. */ if (thread_lock_c == THREAD_INIT_LOCK) { #if HAVE_PTHREAD_MUTEX_INIT /* * NOTE: we do not use the PTHREAD_MUTEX_INITIALIZER since this * basically delays the pthread_mutex_init call to when * pthread_mutex_lock is called for the first time (at least on * freebsd). Since we don't want to go recursive into the * pthread library when we go to lock our mutex variable, we * want to force the initialization to happen beforehand with a * call to pthread_mute_init. */ pthread_mutex_init(&dmalloc_mutex, THREAD_LOCK_INIT_VAL); #endif } } else if (thread_lock_c == 0) { #if HAVE_PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock(&dmalloc_mutex); #endif } } #endif /****************************** local utilities ******************************/ /* * check out a pointer to see if we were looking for it. this should * be re-entrant and it may not return. */ static void check_pnt(const char *file, const int line, const void *pnt, const char *label) { static unsigned long addr_c = 0; char where_buf[64]; if (_dmalloc_address == NULL || pnt != _dmalloc_address) { return; } addr_c++; dmalloc_message("address '%#lx' found in '%s' at pass %ld from '%s'", (unsigned long)pnt, label, addr_c, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), file, line)); /* NOTE: if address_seen_n == 0 then never quit */ if (_dmalloc_address_seen_n > 0 && addr_c >= _dmalloc_address_seen_n) { dmalloc_errno = ERROR_IS_FOUND; dmalloc_error("check_pnt"); } } /* * process the values of dmalloc environ variables */ static void process_environ(const char *option_str) { /* * we have a static here so we can store the string without getting * into problems */ static char options[1024]; /* process the options flag */ if (option_str == NULL) { options[0] = '\0'; } else { strncpy(options, option_str, sizeof(options)); options[sizeof(options) - 1] = '\0'; } _dmalloc_environ_process(options, &_dmalloc_address, (long *)&_dmalloc_address_seen_n, &_dmalloc_flags, &_dmalloc_check_interval, &_dmalloc_lock_on, &dmalloc_logpath, &start_file, &start_line, &start_iter, &start_size, &_dmalloc_memory_limit); thread_lock_c = _dmalloc_lock_on; /* if we set the start stuff, then check-heap comes on later */ if (start_iter > 0 || start_size > 0) { BIT_CLEAR(_dmalloc_flags, DEBUG_CHECK_HEAP); } /* indicate that we should reopen the logfile if we need to */ _dmalloc_reopen_log(); #if LOCK_THREADS == 0 /* was thread-lock-on specified but not configured? */ if (_dmalloc_lock_on > 0) { dmalloc_errno = ERROR_LOCK_NOT_CONFIG; _dmalloc_die(0); } #endif } /************************** startup/shutdown calls ***************************/ #if SIGNAL_OKAY /* * signal catcher */ static RETSIGTYPE signal_handler(const int sig) { dmalloc_message("caught signal %d", sig); /* if we are already inside malloc then do the shutdown later */ if (in_alloc_b) { do_shutdown_b = 1; } else { dmalloc_shutdown(); } } #endif /* * startup the memory-allocation module */ static int dmalloc_startup(const char *debug_str) { static int some_up_b = 0; const char *env_str; #ifdef __CYGWIN__ char env_buf[256]; #endif /* have we started already? */ if (enabled_b) { return 0; } if (! some_up_b) { /* set this up here so if an error occurs below, it will not try again */ some_up_b = 1; #if LOG_PNT_TIMEVAL GET_TIMEVAL(_dmalloc_start); #else #if HAVE_TIME /* NOT LOG_PNT_TIME */ _dmalloc_start = time(NULL); #endif #endif /* * If we are running under Cygwin then getenv may not be safe. We * try to use the GetEnvironmentVariableA function instead. */ #if defined(__CYGWIN__) && HAVE_GETENVIRONMENTVARIABLEA /* use this function instead of getenv */ GetEnvironmentVariableA(OPTIONS_ENVIRON, env_buf, sizeof(env_buf)); env_str = env_buf; #else /* ! __CYGWIN__ */ #if GETENV_SAFE /* get the options flag */ if (debug_str == NULL) { env_str = getenv(OPTIONS_ENVIRON); } else { env_str = debug_str; } #else /* oh, well. no idea how to get the environmental variables */ env_str = ""; #endif /* GETENV_SAFE */ #endif /* ! __CYGWIN__ */ /* process the environmental variable(s) */ process_environ(env_str); /* * Tune the environment here. If we have a start-file, * start-count, or interval enabled then make sure the check-heap * flag is cleared. */ if (start_file != NULL || start_iter > 0 || start_size > 0 || _dmalloc_check_interval > 0) { BIT_CLEAR(_dmalloc_flags, DEBUG_CHECK_HEAP); } /* startup heap code */ if (! _dmalloc_heap_startup()) { return 0; } /* startup the chunk lower-level code */ if (! _dmalloc_chunk_startup()) { return 0; } } #if LOCK_THREADS if (thread_lock_c > 0) { return 1; } #endif /* * We have initialized all of our code. * * NOTE: set this up here so if an error occurs below, it will not * try again */ enabled_b = 1; /* * NOTE: we may go recursive below here becasue atexit or on_exit * may ask for memory to be allocated. We won't worry about it and * will just give it to them. We hope that atexit didn't start the * allocating. Ugh. */ #if AUTO_SHUTDOWN /* NOTE: I use the else here in case some dumb systems has both */ #if HAVE_ATEXIT (void)atexit(dmalloc_shutdown); #else #if HAVE_ON_EXIT (void)on_exit(dmalloc_shutdown, NULL); #endif /* HAVE_ON_EXIT */ #endif /* ! HAVE_ATEXIT */ #endif /* AUTO_SHUTDOWN */ #if SIGNAL_OKAY if (BIT_IS_SET(_dmalloc_flags, DEBUG_CATCH_SIGNALS)) { #ifdef SIGNAL1 (void)signal(SIGNAL1, signal_handler); #endif #ifdef SIGNAL2 (void)signal(SIGNAL2, signal_handler); #endif #ifdef SIGNAL3 (void)signal(SIGNAL3, signal_handler); #endif #ifdef SIGNAL4 (void)signal(SIGNAL4, signal_handler); #endif #ifdef SIGNAL5 (void)signal(SIGNAL5, signal_handler); #endif #ifdef SIGNAL6 (void)signal(SIGNAL6, signal_handler); #endif } #endif /* SIGNAL_OKAY */ return 1; } /* * static int dmalloc_in * * DESCRIPTION: * * Call to the alloc routines has been made. Do some initialization, * locking, and check some debug variables. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * check_heap_b -> Set to 1 if it is okay to check the heap. If set * to 0 then the caller will check it itself or it is a non-invasive * call. */ static int dmalloc_in(const char *file, const int line, const int check_heap_b) { if (_dmalloc_aborting_b) { return 0; } /* * NOTE: we need to do this outside of lock to get env vars * otherwise our _dmalloc_lock_on variable won't be initialized and * the THREAD_LOCK will flip. */ if (! enabled_b) { if (! dmalloc_startup(NULL /* no options string */)) { return 0; } } #if LOCK_THREADS lock_thread(); #endif if (in_alloc_b) { dmalloc_errno = ERROR_IN_TWICE; dmalloc_error("dmalloc_in"); /* NOTE: dmalloc_error may die already */ _dmalloc_die(0); /*NOTREACHED*/ } in_alloc_b = 1; /* increment our interval */ _dmalloc_iter_c++; /* check start file/line specifications */ if ((! BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_HEAP)) && start_file != NULL && file != DMALLOC_DEFAULT_FILE && line != DMALLOC_DEFAULT_LINE && strcmp(start_file, file) == 0 && (start_line == 0 || start_line == line)) { BIT_SET(_dmalloc_flags, DEBUG_CHECK_HEAP); /* * we disable the start file so we won't check this again and the * interval can go on/off */ start_file = NULL; } /* start checking heap after X times */ else if (start_iter > 0) { if (--start_iter == 0) { BIT_SET(_dmalloc_flags, DEBUG_CHECK_HEAP); /* * this is automatically disabled since it goes to 0 so the * interval can go on/off */ } } else if (start_size > 0 && start_size >= _dmalloc_alloc_total) { BIT_SET(_dmalloc_flags, DEBUG_CHECK_HEAP); start_size = 0; /* disable this check so the interval can go on/off */ } /* checking heap every X times */ else if (_dmalloc_check_interval > 0) { if (_dmalloc_iter_c % _dmalloc_check_interval == 0) { BIT_SET(_dmalloc_flags, DEBUG_CHECK_HEAP); } else { BIT_CLEAR(_dmalloc_flags, DEBUG_CHECK_HEAP); } } /* after all that, do we need to check the heap? */ if (check_heap_b && BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_HEAP)) { (void)_dmalloc_chunk_heap_check(); } return 1; } /* * Going out of the alloc routines back to user space. */ static void dmalloc_out(void) { in_alloc_b = 0; #if LOCK_THREADS unlock_thread(); #endif if (do_shutdown_b) { dmalloc_shutdown(); } } /***************************** exported routines *****************************/ /* * void dmalloc_shutdown * * DESCRIPTION: * * Shutdown the dmalloc library and provide statistics if necessary. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ void dmalloc_shutdown(void) { /* NOTE: do not generate errors for IN_TWICE here */ /* if we're already in die mode leave fast and quietly */ if (_dmalloc_aborting_b) { return; } /* * Make sure that the log file is open. We do this here because we * might cause an allocation in the open() and don't want to go * recursive. */ _dmalloc_open_log(); /* if we've died in dmalloc somewhere then leave fast and quietly */ if (in_alloc_b) { return; } #if LOCK_THREADS lock_thread(); #endif /* we do it again in case the lock synced the flag to true now */ if (in_alloc_b) { #if LOCK_THREADS unlock_thread(); #endif return; } in_alloc_b = 1; /* * Check the heap since we are dumping info from it. We check it * when check-blank is enabled do make sure all of the areas have * not been overwritten. Thanks Randell. */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_HEAP) || BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_BLANK) || BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_SHUTDOWN)) { (void)_dmalloc_chunk_heap_check(); } /* dump some statistics to the logfile */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_STATS)) { _dmalloc_chunk_log_stats(); } /* report on non-freed pointers */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_NONFREE)) { _dmalloc_chunk_log_changed(0, 1, 0, #if DUMP_UNFREED_SUMMARY_ONLY 0 #else 1 #endif ); } #if LOG_PNT_TIMEVAL { TIMEVAL_TYPE now; char time_buf1[64], time_buf2[64]; GET_TIMEVAL(now); dmalloc_message("ending time = %s, elapsed since start = %s", _dmalloc_ptimeval(&now, time_buf1, sizeof(time_buf1), 0), _dmalloc_ptimeval(&now, time_buf2, sizeof(time_buf2), 1)); } #else #if HAVE_TIME /* NOT LOG_PNT_TIME */ { TIME_TYPE now; char time_buf1[64], time_buf2[64]; now = time(NULL); dmalloc_message("ending time = %s, elapsed since start = %s", _dmalloc_ptime(&now, time_buf1, sizeof(time_buf1), 0), _dmalloc_ptime(&now, time_buf2, sizeof(time_buf2), 1)); } #endif #endif in_alloc_b = 0; #if LOCK_THREADS unlock_thread(); #endif /* NOTE: do not set enabled_b to false here */ } #if FINI_DMALLOC /* * void __fini_dmalloc * * DESCRIPTION: * * Automatic function to close dmalloc supported by some operating * systems. Pretty cool OS/compiler hack. By default it is not * necessary because we use atexit() and on_exit() to register the * close functions which are more portable. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ void __fini_dmalloc(void) { dmalloc_shutdown(); } #endif /* * DMALLOC_PNT dmalloc_malloc * * DESCRIPTION: * * Allocate and return a memory block of a certain size. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * size -> Number of bytes requested. * * func_id -> Function-id to identify the type of call. See * dmalloc.h. * * alignment -> To align the new block to a certain number of bytes, * set this to a value greater than 0. * * xalloc_b -> If set to 1 then print an error and exit if we run out * of memory. */ DMALLOC_PNT dmalloc_malloc(const char *file, const int line, const DMALLOC_SIZE size, const int func_id, const DMALLOC_SIZE alignment, const int xalloc_b) { void *new_p; DMALLOC_SIZE align; #if DMALLOC_SIZE_UNSIGNED == 0 if (size < 0) { dmalloc_errno = ERROR_BAD_SIZE; dmalloc_error("malloc"); if (tracking_func != NULL) { tracking_func(file, line, func_id, size, alignment, NULL, NULL); } return MALLOC_ERROR; } #endif if (! dmalloc_in(file, line, 1)) { if (tracking_func != NULL) { tracking_func(file, line, func_id, size, alignment, NULL, NULL); } return MALLOC_ERROR; } if (alignment == 0) { if (func_id == DMALLOC_FUNC_VALLOC) { align = BLOCK_SIZE; } else { align = 0; } } else if (alignment >= BLOCK_SIZE) { align = BLOCK_SIZE; } else { /* * NOTE: Currently, there is no support in the library for * memalign on less than block boundaries. It will be non-trivial * to support valloc with fence-post checking and the lack of the * flag width for dblock allocations. */ if (! memalign_warn_b) { dmalloc_message("WARNING: memalign called without library support"); memalign_warn_b = 1; } align = 0; /* align = alignment */ } new_p = _dmalloc_chunk_malloc(file, line, size, func_id, align); check_pnt(file, line, new_p, "malloc"); dmalloc_out(); if (tracking_func != NULL) { tracking_func(file, line, func_id, size, alignment, NULL, new_p); } if (xalloc_b && new_p == NULL) { char mess[1024], desc[128]; (void)loc_snprintf(mess, sizeof(mess), "Out of memory while allocating %d bytes from '%s'\n", size, _dmalloc_chunk_desc_pnt(desc, sizeof(desc), file, line)); (void)write(STDERR, mess, strlen(mess)); _exit(1); } return new_p; } /* * DMALLOC_PNT dmalloc_realloc * * DESCRIPTION: * * Resizes and old pointer to a new number of bytes. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * old_pnt -> Pointer to an existing memory chunk that we are * resizing. If this is NULL then it basically does a malloc. * * new_size -> New number of bytes requested for the old pointer. * * func_id -> Function-id to identify the type of call. See * dmalloc.h. * * xalloc_b -> If set to 1 then print an error and exit if we run out * of memory. */ DMALLOC_PNT dmalloc_realloc(const char *file, const int line, DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size, const int func_id, const int xalloc_b) { void *new_p; #if DMALLOC_SIZE_UNSIGNED == 0 if (new_size < 0) { dmalloc_errno = ERROR_BAD_SIZE; dmalloc_error("realloc"); if (tracking_func != NULL) { tracking_func(file, line, func_id, new_size, 0, old_pnt, NULL); } return MALLOC_ERROR; } #endif if (! dmalloc_in(file, line, 1)) { if (tracking_func != NULL) { tracking_func(file, line, func_id, new_size, 0, old_pnt, NULL); } return REALLOC_ERROR; } check_pnt(file, line, old_pnt, "realloc-in"); #if ALLOW_REALLOC_NULL if (old_pnt == NULL) { int new_func_id; /* shift the function id to be calloc or malloc */ if (func_id == DMALLOC_FUNC_RECALLOC) { new_func_id = DMALLOC_FUNC_CALLOC; } else { new_func_id = DMALLOC_FUNC_MALLOC; } new_p = _dmalloc_chunk_malloc(file, line, new_size, new_func_id, 0); } else #endif #if ALLOW_REALLOC_SIZE_ZERO if (new_size == 0) { /* * If realloc(old_pnt, 0) then free(old_pnt). Thanks to Stefan * Froehlich for patiently pointing that the realloc in just * about every Unix has this functionality. */ (void)_dmalloc_chunk_free(file, line, old_pnt, func_id); new_p = NULL; } else #endif new_p = _dmalloc_chunk_realloc(file, line, old_pnt, new_size, func_id); if (new_p != NULL) { check_pnt(file, line, new_p, "realloc-out"); } dmalloc_out(); if (tracking_func != NULL) { tracking_func(file, line, func_id, new_size, 0, old_pnt, new_p); } if (xalloc_b && new_p == NULL) { char mess[1024], desc[128]; (void)loc_snprintf(mess, sizeof(mess), "Out of memory while reallocating %d bytes from '%s'\n", new_size, _dmalloc_chunk_desc_pnt(desc, sizeof(desc), file, line)); (void)write(STDERR, mess, strlen(mess)); _exit(1); } return new_p; } /* * int dmalloc_free * * DESCRIPTION: * * Release a pointer back into the heap. * * RETURNS: * * Success - FREE_NOERROR * * Failure - FREE_ERROR * * Note: many operating systems define free to return (void) so this * return value may be filtered. Dumb. * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * pnt -> Existing pointer we are freeing. * * func_id -> Function-id to identify the type of call. See * dmalloc.h. */ int dmalloc_free(const char *file, const int line, DMALLOC_PNT pnt, const int func_id) { int ret; if (! dmalloc_in(file, line, 1)) { if (tracking_func != NULL) { tracking_func(file, line, func_id, 0, 0, pnt, NULL); } return FREE_ERROR; } check_pnt(file, line, pnt, "free"); ret = _dmalloc_chunk_free(file, line, pnt, func_id); dmalloc_out(); if (tracking_func != NULL) { tracking_func(file, line, DMALLOC_FUNC_FREE, 0, 0, pnt, NULL); } return ret; } /* * DMALLOC_PNT dmalloc_strndup * * DESCRIPTION: * * Allocate and return an allocated block of memory holding a copy of * a string of a certain number of characters. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * file -> File-name or return-address of the caller. * * line -> Line-number of the caller. * * string -> String we are duplicating. * * len -> Length of the string we are duplicating. * * xalloc_b -> If set to 1 then print an error and exit if we run out * of memory. */ char *dmalloc_strndup(const char *file, const int line, const char *string, const int len, const int xalloc_b) { DMALLOC_SIZE size; char *new_string; const char *string_p; /* check the arguments */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { /* we check for pointer plus \0 */ if (! dmalloc_verify_pnt_strsize(file, line, "strdup", string, 0 /* not exact */, 1 /* strlen */, len)) { dmalloc_message("bad pointer argument found in strdup"); } } /* so we have to figure out the max length of the string directly */ if (len < 0) { size = strlen(string); } else { for (string_p = string; string_p < string + len; string_p++) { if (*string_p == '\0') { break; } } size = string_p - string; } /* allocate space for the \0 */ new_string = dmalloc_malloc(file, line, size + 1, DMALLOC_FUNC_STRDUP, 0 /* no alignment */, xalloc_b); if (new_string != NULL) { strncpy(new_string, string, size); new_string[size] = '\0'; } return new_string; } /*************************** external memory calls ***************************/ /* * DMALLOC_PNT malloc * * DESCRIPTION: * * Overloading the malloc(3) function. Allocate and return a memory * block of a certain size. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * size -> Number of bytes requested. */ #undef malloc DMALLOC_PNT malloc(DMALLOC_SIZE size) { char *file; GET_RET_ADDR(file); return dmalloc_malloc(file, DMALLOC_DEFAULT_LINE, size, DMALLOC_FUNC_MALLOC, 0 /* no alignment */, 0 /* no xalloc messages */); } /* * DMALLOC_PNT calloc * * DESCRIPTION: * * Overloading the calloc(3) function. Returns a block of zeroed memory. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * num_elements -> Number of elements being allocated. * * size -> The number of bytes in each element. */ #undef calloc DMALLOC_PNT calloc(DMALLOC_SIZE num_elements, DMALLOC_SIZE size) { DMALLOC_SIZE len = num_elements * size; char *file; GET_RET_ADDR(file); return dmalloc_malloc(file, DMALLOC_DEFAULT_LINE, len, DMALLOC_FUNC_CALLOC, 0 /* no alignment */, 0 /* no xalloc messages */); } /* * DMALLOC_PNT realloc * * DESCRIPTION: * * Overload of realloc(3). Resizes and old pointer to a new number of * bytes. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * old_pnt -> Pointer to an existing memory chunk that we are * resizing. If this is NULL then it basically does a malloc. * * new_size -> New number of bytes requested for the old pointer. */ #undef realloc DMALLOC_PNT realloc(DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size) { char *file; GET_RET_ADDR(file); return dmalloc_realloc(file, DMALLOC_DEFAULT_LINE, old_pnt, new_size, DMALLOC_FUNC_REALLOC, 0 /* no xalloc messages */); } /* * DMALLOC_PNT recalloc * * DESCRIPTION: * * Overload of recalloc(3) which exists on some systems. Resizes and * old pointer to a new number of bytes. If we are expanding, then * any new bytes will be zeroed. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * old_pnt -> Pointer to an existing memory chunk that we are * resizing. * * new_size -> New number of bytes requested for the old pointer. */ #undef recalloc DMALLOC_PNT recalloc(DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size) { char *file; GET_RET_ADDR(file); return dmalloc_realloc(file, DMALLOC_DEFAULT_LINE, old_pnt, new_size, DMALLOC_FUNC_RECALLOC, 0 /* no xalloc messages */); } /* * DMALLOC_PNT memalign * * DESCRIPTION: * * Overloading the memalign(3) function. Allocate and return a memory * block of a certain size which have been aligned to a certain * alignment. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * alignment -> Value to which the allocation must be aligned. This * should probably be a multiple of 2 with a maximum value equivalent * to the block-size which is often 1k or 4k. * * size -> Number of bytes requested. */ #undef memalign DMALLOC_PNT memalign(DMALLOC_SIZE alignment, DMALLOC_SIZE size) { char *file; GET_RET_ADDR(file); return dmalloc_malloc(file, DMALLOC_DEFAULT_LINE, size, DMALLOC_FUNC_MEMALIGN, alignment, 0 /* no xalloc messages */); } /* * DMALLOC_PNT valloc * * DESCRIPTION: * * Overloading the valloc(3) function. Allocate and return a memory * block of a certain size which have been aligned to page boundaries * which are often 1k or 4k. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * size -> Number of bytes requested. */ #undef valloc DMALLOC_PNT valloc(DMALLOC_SIZE size) { char *file; GET_RET_ADDR(file); return dmalloc_malloc(file, DMALLOC_DEFAULT_LINE, size, DMALLOC_FUNC_VALLOC, BLOCK_SIZE, 0 /* no xalloc messages */); } #ifndef DMALLOC_STRDUP_MACRO /* * DMALLOC_PNT strdup * * DESCRIPTION: * * Overload of strdup(3). Allocate and return an allocated block of * memory holding a copy of a string. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * string -> String we are duplicating. */ #undef strdup char *strdup(const char *string) { int len; char *buf, *file; GET_RET_ADDR(file); /* check the arguments */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, 0 /* no line */, "strdup", string, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in strdup"); } } /* len + \0 */ len = strlen(string) + 1; buf = dmalloc_malloc(file, DMALLOC_DEFAULT_LINE, len, DMALLOC_FUNC_STRDUP, 0 /* no alignment */, 0 /* no xalloc messages */); if (buf != NULL) { (void)memcpy(buf, string, len); } return buf; } #endif /* * DMALLOC_PNT strndup * * DESCRIPTION: * * Overload of strndup(3). Allocate and return an allocated block of * memory holding a copy of a string with a maximum length. * * RETURNS: * * Success - Valid pointer. * * Failure - 0L * * ARGUMENTS: * * string -> String we are duplicating. * * len -> Length of the string to duplicate. */ #undef strndup char *strndup(const char *string, const DMALLOC_SIZE len) { int size; char *buf, *file; const char *string_p; GET_RET_ADDR(file); /* check the arguments */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt_strsize(file, 0 /* no line */, "strdup", string, 0 /* not exact */, 1 /* strlen */, size)) { dmalloc_message("bad pointer argument found in strdup"); } } /* so we have to figure out the max length of the string directly */ for (string_p = string; string_p < string + len; string_p++) { if (*string_p == '\0') { break; } } size = string_p - string; /* at 1 for null */ buf = dmalloc_malloc(file, DMALLOC_DEFAULT_LINE, size + 1, DMALLOC_FUNC_STRDUP, 0 /* no alignment */, 0 /* no xalloc messages */); if (buf != NULL) { (void)memcpy(buf, string, size); buf[size] = '\0'; } return buf; } /* * DMALLOC_FREE_RET free * * DESCRIPTION: * * Release a pointer back into the heap. * * RETURNS: * * Returns FREE_ERROR, FREE_NOERROR or void depending on whether STDC * is defined by your compiler. * * ARGUMENTS: * * pnt -> Existing pointer we are freeing. */ #undef free DMALLOC_FREE_RET free(DMALLOC_PNT pnt) { char *file; int ret; GET_RET_ADDR(file); ret = dmalloc_free(file, DMALLOC_DEFAULT_LINE, pnt, DMALLOC_FUNC_FREE); #if (defined(__STDC__) && __STDC__ == 1) || defined(__cplusplus) || defined(STDC_HEADERS) #else return ret; #endif } /* * DMALLOC_FREE_RET cfree * * DESCRIPTION: * * Same as free. * * RETURNS: * * Returns FREE_ERROR, FREE_NOERROR or void depending on whether STDC * is defined by your compiler. * * ARGUMENTS: * * pnt -> Existing pointer we are freeing. */ #undef cfree DMALLOC_FREE_RET cfree(DMALLOC_PNT pnt) { char *file; int ret; GET_RET_ADDR(file); ret = dmalloc_free(file, DMALLOC_DEFAULT_LINE, pnt, DMALLOC_FUNC_CFREE); #if (defined(__STDC__) && __STDC__ == 1) || defined(__cplusplus) || defined(STDC_HEADERS) #else return ret; #endif } /******************************* utility calls *******************************/ /* * int dmalloc_verify * * DESCRIPTION: * * Verify a pointer which has previously been allocated by the * library or check the entire heap. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * pnt -> Pointer we are verifying. If 0L then check the entire heap. */ int dmalloc_verify(const DMALLOC_PNT pnt) { int ret; if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 0)) { return MALLOC_VERIFY_NOERROR; } /* should not check heap here because we will be doing it below */ if (pnt == NULL) { ret = _dmalloc_chunk_heap_check(); } else { ret = _dmalloc_chunk_pnt_check("dmalloc_verify", pnt, 1 /* exact pointer */, 0 /* no strlen */, 0 /* no min size */); } dmalloc_out(); if (ret) { return MALLOC_VERIFY_NOERROR; } else { return MALLOC_VERIFY_ERROR; } } /* * int malloc_verify * * DESCRIPTION: * * Verify a pointer which has previously been allocated by the * library. Same as dmalloc_verify. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * pnt -> Pointer we are verifying. If 0L then check the entire heap. */ int malloc_verify(const DMALLOC_PNT pnt) { return dmalloc_verify(pnt); } /* * int dmalloc_verify_pnt * * DESCRIPTION: * * This function is mainly used by the arg_check.c functions to verify * specific pointers. This can be used by users to provide more fine * grained tests on pointers. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * file -> File-name or return-address of the caller. You can use * __FILE__ for this argument or 0L for none. * * line -> Line-number of the caller. You can use __LINE__ for this * argument or 0 for none. * * func -> Function string which is checking the pointer. 0L if none. * * pnt -> Pointer we are checking. * * exact_b -> Set to 1 if this pointer was definitely handed back from * a memory allocation. If set to 0 then this pointer can be inside * another allocation or outside the heap altogether. * * strlen_b -> Set to 1 to make sure that this pointer can handle * strlen(pnt) + 1 bytes up to the maximum specified by min_size. If * this is 1 and min_size > 0 then it is in effect a strnlen. * * min_size -> Make sure that pointer can hold at least that many * bytes if inside of the heap. If 0 then don't check the size. */ int dmalloc_verify_pnt_strsize(const char *file, const int line, const char *func, const void *pnt, const int exact_b, const int strlen_b, const int min_size) { int ret; if (! dmalloc_in(file, line, 0)) { return MALLOC_VERIFY_NOERROR; } /* call the pnt checking chunk code */ ret = _dmalloc_chunk_pnt_check(func, pnt, exact_b, strlen_b, min_size); dmalloc_out(); if (ret) { return MALLOC_VERIFY_NOERROR; } else { return MALLOC_VERIFY_ERROR; } } /* * int dmalloc_verify_pnt * * DESCRIPTION: * * This function is mainly used by the arg_check.c functions to verify * specific pointers. This can be used by users to provide more fine * grained tests on pointers. * * RETURNS: * * Success - MALLOC_VERIFY_NOERROR * * Failure - MALLOC_VERIFY_ERROR * * ARGUMENTS: * * file -> File-name or return-address of the caller. You can use * __FILE__ for this argument or 0L for none. * * line -> Line-number of the caller. You can use __LINE__ for this * argument or 0 for none. * * func -> Function string which is checking the pointer. 0L if none. * * pnt -> Pointer we are checking. * * exact_b -> Set to 1 if this pointer was definitely handed back from * a memory allocation. If set to 0 then this pointer can be inside * another allocation or outside the heap altogether. * * min_size -> Make sure that pointer can hold at least that many * bytes if inside of the heap. If -1 then make sure it can handle * strlen(pnt) + 1 bytes (+1 for the \0). If 0 then don't check the * size. If you need strnlen functionality with a maximum on the * strlen, see dmalloc_verify_pnt_strsize. */ int dmalloc_verify_pnt(const char *file, const int line, const char *func, const void *pnt, const int exact_b, const int min_size) { if (min_size < 0) { return dmalloc_verify_pnt_strsize(file, line, func, pnt, exact_b, 1 /* strlen */, 0 /* no min-size */); } else { return dmalloc_verify_pnt_strsize(file, line, func, pnt, exact_b, 0 /* no strlen */, min_size); } } /* * unsigned int dmalloc_debug * * DESCRIPTION: * * Set the global debug functionality flags. You can also use * dmalloc_debug_setup. * * Note: you cannot add or remove certain flags such as signal * handlers since they are setup at initialization time only. * * RETURNS: * * The old debug flag value. * * ARGUMENTS: * * flags -> Flag value to set. Pass in 0 to disable all debugging. */ unsigned int dmalloc_debug(const unsigned int flags) { unsigned int old_flags; if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } old_flags = _dmalloc_flags; /* add the new flags */ _dmalloc_flags = flags; return old_flags; } /* * unsigned int dmalloc_debug_current * * DESCRIPTION: * * Returns the current debug functionality flags. This allows you to * save a dmalloc library state to be restored later. * * RETURNS: * * Current debug flags. * * ARGUMENTS: * * None. */ unsigned int dmalloc_debug_current(void) { if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } /* should not check the heap here since we are dumping the debug variable */ return _dmalloc_flags; } /* * void dmalloc_debug_setup * * DESCRIPTION: * * Set the global debugging functionality as an option string. * Normally this would be pased in in the DMALLOC_OPTIONS * environmental variable. This is here to override the env or for * circumstances where modifying the environment is not possible or * does not apply such as servers or cgi-bin programs. * * RETURNS: * * None. * * ARGUMENTS: * * options_str -> Options string to set the library flags. */ void dmalloc_debug_setup(const char *options_str) { if (! enabled_b) { (void)dmalloc_startup(options_str); /* if we just started up then we don't have to do anything else */ return; } /* we need to lock */ if (! dmalloc_in(NULL /* no file-name */, 0 /* no line-number */, 0 /* don't-check-heap */)) { return; } process_environ(options_str); dmalloc_out(); } /* * int dmalloc_examine * * DESCRIPTION: * * Examine a pointer and pass back information on its allocation size * as well as the file and line-number where it was allocated. If the * file and line number is not available, then it will pass back the * allocation location's return-address if available. * * RETURNS: * * Success - DMALLOC_NOERROR * * Failure - DMALLOC_ERROR * * ARGUMENTS: * * pnt -> Pointer we are checking. * * user_size_p <- Pointer to a DMALLOC_SIZE type variable which, if * not NULL, will be set to the size of bytes from the pointer. * * total_size_p <- Poiner to a DMALLOC_SIZE type variable which, if * not NULL, will be set to the total size given for this allocation * including administrative overhead. * * file_p <- Pointer to a character pointer which, if not NULL, will * be set to the file where the pointer was allocated. * * line_p <- Pointer to an unsigned integer which, if not NULL, will * be set to the line-number where the pointer was allocated. * * ret_attr_p <- Pointer to a void pointer, if not NULL, will be set * to the return-address where the pointer was allocated. * * used_mark_p <- Poiner to an unsigned integer which, if not NULL, * will be set to the mark of when the pointer was last "used". This * could be when it was allocated, reallocated, or freed. * * seen_p <- Poiner to an unsigned long which, if not NULL, will be * set to the number of times that this pointer has been allocated, * realloced, or freed. NOTE: LOG_PNT_SEEN_COUNT must be set to 1 * otherwise no seen information is available and it will be set to 0. */ int dmalloc_examine(const DMALLOC_PNT pnt, DMALLOC_SIZE *user_size_p, DMALLOC_SIZE *total_size_p, char **file_p, unsigned int *line_p, DMALLOC_PNT *ret_attr_p, unsigned long *used_mark_p, unsigned long *seen_p) { int ret; unsigned int user_size_map, tot_size_map; unsigned long *loc_seen_p; /* * NOTE: we use the size maps because we use a unsigned int size * type internally but may use some size_t externally. */ /* need to check the heap here since we are geting info from it below */ if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return DMALLOC_ERROR; } /* NOTE: we do not need the alloc-size info */ ret = _dmalloc_chunk_read_info(pnt, "dmalloc_examine", &user_size_map, &tot_size_map, file_p, line_p, ret_attr_p, &loc_seen_p, used_mark_p, NULL, NULL); dmalloc_out(); if (ret) { SET_POINTER(user_size_p, user_size_map); SET_POINTER(total_size_p, tot_size_map); if (loc_seen_p == NULL) { SET_POINTER(seen_p, 0); } else { SET_POINTER(seen_p, *loc_seen_p); } return DMALLOC_NOERROR; } else { return DMALLOC_ERROR; } } /* * void dmalloc_track * * DESCRIPTION: * * Register an allocation tracking function which will be called each * time an allocation occurs. * * RETURNS: * * None. * * ARGUMENTS: * * track_func -> Function to register as the tracking function. Set * to NULL to disable. */ void dmalloc_track(const dmalloc_track_t track_func) { tracking_func = track_func; } /* * unsigned long dmalloc_mark * * DESCRIPTION: * * Return to the caller the current "mark" which can be used later by * dmalloc_log_changed to log the changed pointers since this point. * Multiple marks can be saved and used. * * This is also the iteration number and can be logged at the front of * each memory transaction in the logfile with the LOG_ITERATION * define in settings.h and can be logged with each pointer with the * LOG_PNT_ITERATION define in settings.h. * * RETURNS: * * Current mark value * * ARGUMENTS: * * None. */ unsigned long dmalloc_mark(void) { if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } return _dmalloc_iter_c; } /* * unsigned long dmalloc_memory_allocated * * DESCRIPTION: * * Return the total number of bytes allocated by the program so far. * * RETURNS: * * Total number of bytes allocated by the program so far. * * ARGUMENTS: * * None. */ unsigned long dmalloc_memory_allocated(void) { if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } return _dmalloc_alloc_total; } /* * unsigned int dmalloc_page_size * * DESCRIPTION: * * Get the page-size being used by dmalloc. * * RETURNS: * * Page size. * * ARGUMENTS: * * None. */ unsigned int dmalloc_page_size(void) { if (! enabled_b) { (void)dmalloc_startup(NULL /* no options string */); } return BLOCK_SIZE; } /* * unsigned long dmalloc_count_changed * * DESCRIPTION: * * Count the changed memory bytes since a particular mark. * * RETURNS: * * Number of bytes since mark. * * ARGUMENTS: * * mark -> Sets the point from which to count the changed memory. You * can use dmalloc_mark to get the current mark value which can later * be passed in here. Pass in 0 to report on the unfreed memory since * the program started. * * not_freed_b -> Set to 1 to count the new pointers that are non-freed. * * free_b -> Set to 1 to count the new pointers that are freed. */ unsigned long dmalloc_count_changed(const unsigned long mark, const int not_freed_b, const int free_b) { unsigned long mem_count; if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return 0; } if (! BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("counting the unfreed memory since mark %lu", mark); } mem_count = _dmalloc_chunk_count_changed(mark, not_freed_b, free_b); dmalloc_out(); return mem_count; } /* * void dmalloc_log_status * * DESCRIPTION: * * Dump dmalloc statistics to logfile. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ void dmalloc_log_stats(void) { if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return; } _dmalloc_chunk_log_stats(); dmalloc_out(); } /* * void dmalloc_log_unfreed * * DESCRIPTION: * * Dump unfreed-memory info to logfile. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ void dmalloc_log_unfreed(void) { if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return; } if (! BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("dumping the unfreed pointers"); } /* * to log the non-free we are interested in the pointers currently * being used */ _dmalloc_chunk_log_changed(0, 1, 0, #if DUMP_UNFREED_SUMMARY_ONLY 0 #else 1 #endif ); dmalloc_out(); } /* * void dmalloc_log_changed * * DESCRIPTION: * * Dump the pointers that have changed since a point in time. * * RETURNS: * * mark -> Sets the point to compare against. You can use * dmalloc_mark to get the current mark value which can later be * passed in here. Pass in 0 to log what has changed since the * program started. * * not_freed_b -> Set to 1 to log the new pointers that are non-freed. * * free_b -> Set to 1 to log the new pointers that are freed. * * details_b -> Set to 1 to dump the individual pointers that have * changed otherwise the summaries will be logged. */ void dmalloc_log_changed(const unsigned long mark, const int not_freed_b, const int free_b, const int details_b) { if (! dmalloc_in(DMALLOC_DEFAULT_FILE, DMALLOC_DEFAULT_LINE, 1)) { return; } _dmalloc_chunk_log_changed(mark, not_freed_b, free_b, details_b); dmalloc_out(); } /* * void dmalloc_vmessage * * DESCRIPTION: * * Message writer with vprintf like arguments which adds a line to the * dmalloc logfile. * * RETURNS: * * None. * * ARGUMENTS: * * format -> Printf-style format statement. * * args -> Already converted pointer to a stdarg list. */ void dmalloc_vmessage(const char *format, va_list args) { _dmalloc_vmessage(format, args); } /* * void dmalloc_message * * DESCRIPTION: * * Message writer with printf like arguments which adds a line to the * dmalloc logfile. * * RETURNS: * * None. * * ARGUMENTS: * * format -> Printf-style format statement. * * ... -> Variable argument list. */ void dmalloc_message(const char *format, ...) /* __attribute__ ((format (printf, 1, 2))) */ { va_list args; va_start(args, format); _dmalloc_vmessage(format, args); va_end(args); } /* * void dmalloc_get_stats * * DESCRIPTION: * * Return a number of statistics about the current heap. * * RETURNS: * * None. * * ARGUMENTS: * * heap_low_p <- Pointer to pointer which, if not 0L, will be set to * the low address in the heap. * * heap_high_p <- Pointer to pointer which, if not 0L, will be set to * the high address in the heap. * * total_space_p <- Pointer to an unsigned long which, if not 0L, will * be set to the total space managed by the library including user * space, administrative space, and overhead. * * user_space_p <- Pointer to an unsigned long which, if not 0L, will * be set to the space given to the user process (allocated and free). * * current_allocated_p <- Pointer to an unsigned long which, if not * 0L, will be set to the current allocated space given to the user * process. * * current_pnt_np <- Pointer to an unsigned long which, if not 0L, * will be set to the current number of pointers allocated by the user * process. * * max_allocated_p <- Pointer to an unsigned long which, if not 0L, * will be set to the maximum allocated space given to the user * process. * * max_pnt_np <- Pointer to an unsigned long which, if not 0L, will be * set to the maximum number of pointers allocated by the user * process. * * max_one_p <- Pointer to an unsigned long which, if not 0L, will be * set to the maximum allocated with 1 call by the user process. */ void dmalloc_get_stats(DMALLOC_PNT *heap_low_p, DMALLOC_PNT *heap_high_p, unsigned long *total_space_p, unsigned long *user_space_p, unsigned long *current_allocated_p, unsigned long *current_pnt_np, unsigned long *max_allocated_p, unsigned long *max_pnt_np, unsigned long *max_one_p) { _dmalloc_chunk_get_stats(heap_low_p, heap_high_p, total_space_p, user_space_p, current_allocated_p, current_pnt_np, max_allocated_p, max_pnt_np, max_one_p); } /* * const char *dmalloc_strerror * * DESCRIPTION: * * Convert a dmalloc error code into its string equivalent. * * RETURNS: * * Success - String version of the error * * Failure - The string "unknown error" * * ARGUMENTS: * * error_num -> Error number we are converting. */ const char *dmalloc_strerror(const int error_num) { error_str_t *err_p; /* should not dmalloc_in here because _dmalloc_error calls this */ for (err_p = error_list; err_p->es_error != 0; err_p++) { if (err_p->es_error == error_num) { return err_p->es_string; } } return INVALID_ERROR; } dmalloc-5.5.2/heap.h000644 001751 001751 00000003664 10622115666 014212 0ustar00graygray000000 000000 /* * defines for the system specific memory routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: heap.h,v 1.44 2004/07/10 03:49:52 gray Exp $ */ #ifndef __HEAP_H__ #define __HEAP_H__ #include "dmalloc_loc.h" /* for LOCAL and BLOCK_SIZE */ /* * error code returned by heap allocation routine */ #define HEAP_ALLOC_ERROR 0L /* test whether pointer PNT is in the heap space */ #define IS_IN_HEAP(pnt) \ ((char *)(pnt) >= (char *)_dmalloc_heap_low \ && (char *)(pnt) < (char *)_dmalloc_heap_high) /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ extern void *_dmalloc_heap_low; /* base of our heap */ extern void *_dmalloc_heap_high; /* end of our heap */ /* * int _heap_startup * * DESCRIPTION: * * Initialize heap pointers. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * None. */ extern int _dmalloc_heap_startup(void); /* * void *_dmalloc_heap_alloc * * DESCRIPTION: * * Function to get memory bytes from the heap. * * RETURNS: * * Success - Valid pointer. * * Failure - NULL * * ARGUMENTS: * * size -> Number of bytes we need. */ extern void *_dmalloc_heap_alloc(const unsigned int size); /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __HEAP_H__ */ dmalloc-5.5.2/heap.c000640 001751 001751 00000012613 10622115666 014173 0ustar00graygray000000 000000 /* * system specific memory routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: heap.c,v 1.69 2005/01/11 18:27:05 gray Exp $ */ /* * These are the system/machine specific routines for allocating space on the * heap as well as reporting the current position of the heap. */ #if HAVE_UNISTD_H # include /* for write */ #endif #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_MMAN_H # include /* for mmap stuff */ #endif #define DMALLOC_DISABLE #include "conf.h" #include "dmalloc.h" #include "chunk.h" #include "compat.h" #include "debug_tok.h" #include "error.h" #include "error_val.h" #include "heap.h" #include "dmalloc_loc.h" #define SBRK_ERROR ((char *)-1) /* sbrk error code */ /* exported variables */ void *_dmalloc_heap_low = NULL; /* base of our heap */ void *_dmalloc_heap_high = NULL; /* end of our heap */ /****************************** local functions ******************************/ /* * static void *heap_extend * * DESCRIPTION: * * Get more bytes from the system functions. * * RETURNS: * * Success - Valid pointer. * * Failure - NULL * * ARGUMENTS: * * incr -> Number of bytes we need. */ static void *heap_extend(const int incr) { void *ret = SBRK_ERROR; char *high; #if INTERNAL_MEMORY_SPACE { static char block_o_bytes[INTERNAL_MEMORY_SPACE]; static char *bounds_p = block_o_bytes + sizeof(block_o_bytes); static char *block_p = block_o_bytes; if (block_p + incr >= bounds_p) { ret = SBRK_ERROR; } else { ret = block_p; block_p += incr; } } #else #if HAVE_MMAP && USE_MMAP #if MAP_ANON /* if we have and can use mmap, then do so */ ret = mmap(0L, incr, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1 /* no fd */, 0 /* no offset */); #else #endif if (ret == MAP_FAILED) { ret = SBRK_ERROR; } #else #if HAVE_SBRK ret = sbrk(incr); #endif /* if HAVE_SBRK */ #endif /* if not HAVE_MMAP && USE_MMAP */ #endif /* if not INTERNAL_MEMORY_SPACE */ if (ret == SBRK_ERROR) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CATCH_NULL)) { char str[128]; int len; len = loc_snprintf(str, sizeof(str), "\r\ndmalloc: critical error: could not extend heap %u more bytes\r\n", incr); (void)write(STDERR, str, len); _dmalloc_die(0); } dmalloc_errno = ERROR_ALLOC_FAILED; dmalloc_error("heap_extend"); } if (_dmalloc_heap_low == NULL || (char *)ret < (char *)_dmalloc_heap_low) { _dmalloc_heap_low = ret; } high = (char *)ret + incr; if (high > (char *)_dmalloc_heap_high) { _dmalloc_heap_high = high; } if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_ADMIN)) { dmalloc_message("extended heap space by %d bytes [%#lx, %#lx]", incr, (unsigned long)_dmalloc_heap_low, (unsigned long)_dmalloc_heap_high); } return ret; } /**************************** exported functions *****************************/ /* * int _heap_startup * * DESCRIPTION: * * Initialize heap pointers. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * None. */ int _dmalloc_heap_startup(void) { return 1; } /* * void *_dmalloc_heap_alloc * * DESCRIPTION: * * Function to get memory bytes from the heap. * * RETURNS: * * Success - Valid pointer. * * Failure - NULL * * ARGUMENTS: * * size -> Number of bytes we need. */ void *_dmalloc_heap_alloc(const unsigned int size) { void *heap_new, *heap_diff; long diff; if (size == 0) { dmalloc_errno = ERROR_BAD_SIZE; dmalloc_error("_dmalloc_heap_alloc"); return HEAP_ALLOC_ERROR; } while (1) { /* extend the heap by our size */ heap_new = heap_extend(size); if (heap_new == SBRK_ERROR) { return HEAP_ALLOC_ERROR; } /* calculate bytes needed to align to block boundary */ diff = (long)heap_new % BLOCK_SIZE; if (diff == 0) { /* if we are already aligned then we are all set */ break; } diff = BLOCK_SIZE - diff; /* shift the heap a bit to account for non block alignment */ heap_diff = heap_extend(diff); if (heap_diff == SBRK_ERROR) { return HEAP_ALLOC_ERROR; } /* if heap-diff went down then our stack grows down */ if ((char *)heap_diff + diff == (char *)heap_new) { heap_new = heap_diff; break; } else if ((char *)heap_new + size == (char *)heap_diff) { /* shift up our heap to align with the block */ heap_new = (char *)heap_new + diff; break; } /* * We may have a wierd sbrk race condition here. We hope that we * are not just majorly confused which may mean that we sbrk till * the cows come home and die from lack of memory. */ /* start over again */ } return heap_new; } dmalloc-5.5.2/error_val.h000640 001751 001751 00000011172 10622115666 015255 0ustar00graygray000000 000000 /* * global error codes for chunk allocation problems * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: error_val.h,v 1.35 2005/06/05 05:22:28 gray Exp $ */ #ifndef __ERROR_VAL_H__ #define __ERROR_VAL_H__ /* * Dmalloc error codes. * * NOTE: these are here instead of error.h because the dmalloc utility * needs them as well as the dmalloc library. */ #define ERROR_NONE 1 /* no error */ /* 2 is reserved for invalid error */ /* administrative errors */ #define ERROR_BAD_SETUP 10 /* bad setup value */ #define ERROR_IN_TWICE 11 /* in malloc domain twice */ /* 12 unused */ #define ERROR_LOCK_NOT_CONFIG 13 /* thread locking not config */ /* pointer verification errors */ #define ERROR_IS_NULL 20 /* pointer is NULL */ #define ERROR_NOT_IN_HEAP 21 /* pointer is not in heap */ #define ERROR_NOT_FOUND 22 /* pointer not-found */ #define ERROR_IS_FOUND 23 /* found special pointer */ #define ERROR_BAD_FILE 24 /* bad file-name */ #define ERROR_BAD_LINE 25 /* bad line-number */ #define ERROR_UNDER_FENCE 26 /* failed picket fence lower */ #define ERROR_OVER_FENCE 27 /* failed picket fence upper */ #define ERROR_WOULD_OVERWRITE 28 /* would overwrite fence */ /* 29 unused */ #define ERROR_NOT_START_BLOCK 30 /* pointer not to start mem */ /* allocation errors */ #define ERROR_BAD_SIZE 40 /* bad size value */ #define ERROR_TOO_BIG 41 /* allocation too large */ /* 42 unused */ #define ERROR_ALLOC_FAILED 43 /* could not get more space */ /* 44 unused */ #define ERROR_OVER_LIMIT 45 /* over allocation limit */ /* free errors */ #define ERROR_NOT_ON_BLOCK 60 /* not on block boundary */ #define ERROR_ALREADY_FREE 61 /* already in free list */ /* 62-66 unused */ #define ERROR_FREE_OVERWRITTEN 67 /* free space overwritten */ /* administrative errors */ #define ERROR_ADMIN_LIST 70 /* list pnt out of bounds */ /* 71 unused */ #define ERROR_ADDRESS_LIST 72 /* invalid address list */ #define ERROR_SLOT_CORRUPT 73 /* memory slot corruption */ #define INVALID_ERROR "errno value is not valid" typedef struct { int es_error; /* error number */ char *es_string; /* associated string */ } error_str_t; /* string error codes which apply to error codes in error_val.h */ static error_str_t error_list[] #ifdef __GNUC__ __attribute__ ((unused)) #endif = { { ERROR_NONE, "no error" }, /* administrative errors */ { ERROR_BAD_SETUP, "dmalloc initialization and setup failed" }, { ERROR_IN_TWICE, "dmalloc library has gone recursive" }, { ERROR_LOCK_NOT_CONFIG, "dmalloc thread locking has not been configured" }, /* pointer verification errors */ { ERROR_IS_NULL, "pointer is null" }, { ERROR_NOT_IN_HEAP, "pointer is not pointing to heap data space" }, { ERROR_NOT_FOUND, "cannot locate pointer in heap" }, { ERROR_IS_FOUND, "found pointer the user was looking for" }, { ERROR_BAD_FILE, "possibly bad .c filename pointer" }, { ERROR_BAD_LINE, "possibly bad .c file line-number" }, { ERROR_UNDER_FENCE, "failed UNDER picket-fence magic-number check"}, { ERROR_OVER_FENCE, "failed OVER picket-fence magic-number check"}, { ERROR_WOULD_OVERWRITE, "use of pointer would exceed allocation" }, { ERROR_NOT_START_BLOCK, "pointer is not to start of memory block" }, /* allocation errors */ { ERROR_BAD_SIZE, "invalid allocation size" }, { ERROR_TOO_BIG, "largest maximum allocation size exceeded" }, { ERROR_ALLOC_FAILED, "could not grow heap by allocating memory" }, { ERROR_OVER_LIMIT, "over user specified allocation limit" }, /* free errors */ { ERROR_NOT_ON_BLOCK, "pointer is not on block boundary" }, { ERROR_ALREADY_FREE, "tried to free previously freed pointer" }, { ERROR_FREE_OVERWRITTEN, "free space has been overwritten" }, /* administrative errors */ { ERROR_ADMIN_LIST, "dmalloc bad admin structure list" }, { ERROR_ADDRESS_LIST, "dmalloc internal address list corruption" }, { ERROR_SLOT_CORRUPT, "dmalloc internal memory slot corruption" }, { 0 } }; #endif /* ! __ERROR_VAL_H__ */ dmalloc-5.5.2/error.h000644 001751 001751 00000011404 10622115666 014415 0ustar00graygray000000 000000 /* * Defines for the error and message code. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: error.h,v 1.53 2003/06/18 21:57:52 gray Exp $ */ #ifndef __ERROR_H__ #define __ERROR_H__ #include /* for ... */ #include "conf.h" /* up here for _INCLUDE */ /* for time type -- see settings.h */ #if STORE_TIME #ifdef TIME_INCLUDE #include TIME_INCLUDE #endif #endif /* for timeval type -- see settings.h */ #if STORE_TIMEVAL #ifdef TIMEVAL_INCLUDE #include TIMEVAL_INCLUDE #endif #endif /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ /* address to look for. when discovered call dmalloc_error() */ extern DMALLOC_PNT _dmalloc_address; /* when to stop at an address */ extern unsigned long _dmalloc_address_seen_n; /* global debug flags that are set my DMALLOC_DEBUG environ variable */ extern unsigned int _dmalloc_flags; /* global iteration counter for activities */ extern unsigned long _dmalloc_iter_c; /* how often to check the heap */ extern unsigned long _dmalloc_check_interval; #if LOG_PNT_TIMEVAL /* overhead information storing when the library started up for elapsed time */ extern TIMEVAL_TYPE _dmalloc_start; #endif /* if LOG_PNT_TIMEVAL */ #if LOG_PNT_TIMEVAL == 0 #if HAVE_TIME /* NOTE: we do the ifdef this way for fillproto */ extern TIME_TYPE _dmalloc_start; #endif /* if HAVE_TIME */ #endif /* if LOG_PNT_TIMEVAL == 0 */ /* when we are going to startup our locking subsystem */ extern int _dmalloc_lock_on; /* global flag which indicates when we are aborting */ extern int _dmalloc_aborting_b; /* * void _dmalloc_open_log * * DESCRIPTION: * * Open up our log file and write some version of settings * information. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ extern void _dmalloc_open_log(void); /* * void _dmalloc_reopen_log * * DESCRIPTION: * * Re-open our log file which basically calls close() on the * logfile-fd. If we change the name of the log-file then we will * re-open the file. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ extern void _dmalloc_reopen_log(void); #if LOG_PNT_TIMEVAL /* * char *_dmalloc_ptimeval * * DESCRIPTION: * * Print the time into local buffer. * * RETURNS: * * Poiner to the buf argument. * * ARGUMENTS: * * timeval_p -> Pointer to a time value. * * buf -> Internal buffer into which we are writing the time. * * buf_size -> Size of the buffer. * * elapsed_b -> Set to 1 to dump the elapsed instead of global time. */ extern char *_dmalloc_ptimeval(const TIMEVAL_TYPE *timeval_p, char *buf, const int buf_size, const int elapsed_b); #endif /* if LOG_PNT_TIMEVAL */ #if LOG_PNT_TIMEVAL == 0 && HAVE_TIME /* * char *_dmalloc_ptime * * DESCRIPTION: * * Print the time into local buffer. * * RETURNS: * * Poiner to the buf argument. * * ARGUMENTS: * * time_p -> Pointer to a time value. * * buf -> Internal buffer into which we are writing the time. * * buf_size -> Size of the buffer. * * elapsed_b -> Set to 1 to dump the elapsed instead of global time. */ extern char *_dmalloc_ptime(const TIME_TYPE *time_p, char *buf, const int buf_size, const int elapsed_b); #endif /* if LOG_PNT_TIMEVAL == 0 && HAVE_TIME */ /* * void _dmalloc_vmessage * * DESCRIPTION: * * Message writer with vprintf like arguments which adds a line to the * dmalloc logfile. * * RETURNS: * * None. * * ARGUMENTS: * * format -> Printf-style format statement. * * args -> Already converted pointer to a stdarg list. */ extern void _dmalloc_vmessage(const char *format, va_list args); /* * void _dmalloc_die * * DESCRIPTION: * * Kill the program because of an internal malloc error. * * RETURNS: * * None. * * ARGUMENTS: * * silent_b -> Set to 1 to not drop log entries. */ extern void _dmalloc_die(const int silent_b); /* * void dmalloc_error * * DESCRIPTION: * * Handler of error codes. The caller should have set the errno already * * RETURNS: * * None. * * ARGUMENTS: * * func -> Function name for the logs. */ extern void dmalloc_error(const char *func); /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __ERROR_H__ */ dmalloc-5.5.2/error.c000640 001751 001751 00000040246 10622115666 014412 0ustar00graygray000000 000000 /* * Error and message routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: error.c,v 1.114 2004/08/13 21:26:27 gray Exp $ */ /* * This file contains the routines needed for processing error codes * produced by the library. */ #include /* for O_WRONLY, etc. */ #include #if HAVE_STDARG_H # include /* for message vsprintf */ #endif #if HAVE_STDLIB_H # include /* for abort */ #endif #if HAVE_UNISTD_H # include /* for write */ #endif #include "conf.h" /* up here for _INCLUDE */ /* for KILL_PROCESS define */ #if USE_ABORT == 0 #ifdef KILL_INCLUDE #include KILL_INCLUDE /* for kill signals */ #endif #endif #if LOG_PNT_TIMEVAL # ifdef TIMEVAL_INCLUDE # include TIMEVAL_INCLUDE # endif #else # if HAVE_TIME # ifdef TIME_INCLUDE # include TIME_INCLUDE # endif # endif #endif #define DMALLOC_DISABLE #include "dmalloc.h" #include "chunk.h" /* for _dmalloc_memory_limit */ #include "compat.h" #include "debug_tok.h" #include "env.h" /* for LOGPATH_INIT */ #include "error.h" #include "error_val.h" #include "dmalloc_loc.h" #include "version.h" #if LOCK_THREADS #if IDENT_WORKS #ident "@(#) $Information: lock-threads is enabled $" #else static char *information = "@(#) $Information: lock-threads is enabled $"; #endif #endif #define MINS_IN_HOUR 60 #define SECS_IN_MIN 60 #define SECS_IN_HOUR (MINS_IN_HOUR * SECS_IN_MIN) /* external routines */ extern const char *dmalloc_strerror(const int errnum); /* * exported variables */ /* address to look for. when discovered call dmalloc_error() */ DMALLOC_PNT _dmalloc_address = NULL; /* when to stop at an address */ unsigned long _dmalloc_address_seen_n = 0; /* global debug flags that are set my DMALLOC_DEBUG environ variable */ unsigned int _dmalloc_flags = 0; /* global iteration counter for activities */ unsigned long _dmalloc_iter_c = 0; /* how often to check the heap */ unsigned long _dmalloc_check_interval = 0; #if LOG_PNT_TIMEVAL /* overhead information storing when the library started up for elapsed time */ TIMEVAL_TYPE _dmalloc_start; #endif /* NOTE: we do the ifdef this way for fillproto */ #if LOG_PNT_TIMEVAL == 0 #if HAVE_TIME TIME_TYPE _dmalloc_start = 0; #endif #endif /* when we are going to startup our locking subsystem */ int _dmalloc_lock_on = 0; /* global flag which indicates when we are aborting */ int _dmalloc_aborting_b = 0; /* local variables */ static int outfile_fd = -1; /* output file descriptor */ /* the following are here to reduce stack overhead */ static char error_str[1024]; /* error string buffer */ static char message_str[1024]; /* message string buffer */ /* * void _dmalloc_open_log * * DESCRIPTION: * * Open up our log file and write some version of settings * information. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ static void build_logfile_path(char *buf, const int buf_len) { char *bounds_p; char *path_p, *buf_p, *start_p; int len; if (dmalloc_logpath == NULL) { buf[0] = '\0'; return; } buf_p = buf; bounds_p = buf + buf_len; start_p = dmalloc_logpath; for (path_p = dmalloc_logpath; *path_p != '\0'; path_p++) { /* if we don't have to do anything special then just continue */ if (*path_p != '%' || *(path_p + 1) == '\0') { if (buf_p < bounds_p) { *buf_p++ = *path_p; } continue; } /* skip over the % */ path_p++; /* dump the hostname */ if (*path_p == 'h') { #if HAVE_GETHOSTNAME char our_host[128]; gethostname(our_host, sizeof(our_host)); buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s", our_host); #else buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "not-gethostname"); #endif } /* dump the thread-id */ if (*path_p == 'i') { #if LOG_PNT_THREAD_ID char id_str[256]; THREAD_TYPE id; id = THREAD_GET_ID(); THREAD_ID_TO_STRING(id_str, sizeof(id_str), id); buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s", id_str); #else buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "no-thread-id"); #endif } /* dump the pid -- also support backwards compatibility with %d */ if (*path_p == 'p' || *path_p == 'd') { #if HAVE_GETPID /* we make it long in case it's big and we hope it will promote if not */ long our_pid = getpid(); buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%ld", our_pid); #else buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "no-getpid"); #endif } /* dump the time value */ if (*path_p == 't') { #if HAVE_TIME /* we make time a long here so it will promote */ long now; now = time(NULL); buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%ld", now); #else buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "no-time"); #endif } /* dump the user-id */ if (*path_p == 'u') { #if HAVE_GETUID /* we make it long in case it's big and we hope it will promote if not */ long our_uid = getuid(); buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%ld", our_uid); #else buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "no-uid"); #endif } } if (buf_p >= bounds_p - 1) { /* NOTE: we can't use dmalloc_message of course so do it the hard way */ len = loc_snprintf(error_str, sizeof(error_str), "debug-malloc library: logfile path too large '%s'\r\n", dmalloc_logpath); (void)write(STDERR, error_str, len); } *buf_p = '\0'; } /* * void _dmalloc_open_log * * DESCRIPTION: * * Open up our log file and write some version of settings * information. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ void _dmalloc_open_log(void) { char log_path[1024]; int len; /* if it's already open or if we don't have a log file configured */ if (outfile_fd >= 0 || dmalloc_logpath == NULL) { return; } build_logfile_path(log_path, sizeof(log_path)); /* open our logfile */ outfile_fd = open(log_path, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (outfile_fd < 0) { /* NOTE: we can't use dmalloc_message of course so do it the hardway */ len = loc_snprintf(error_str, sizeof(error_str), "debug-malloc library: could not open '%s'\r\n", log_path); (void)write(STDERR, error_str, len); /* disable log_path */ dmalloc_logpath = NULL; return; } /* * NOTE: this makes it go recursive here, but it will never enter * this section of code. */ dmalloc_message("Dmalloc version '%s' from '%s'", dmalloc_version, DMALLOC_HOME); dmalloc_message("flags = %#x, logfile '%s'", _dmalloc_flags, log_path); dmalloc_message("interval = %lu, addr = %#lx, seen # = %ld, limit = %ld", _dmalloc_check_interval, (unsigned long)_dmalloc_address, _dmalloc_address_seen_n, _dmalloc_memory_limit); #if LOCK_THREADS dmalloc_message("threads enabled, lock-on = %d, lock-init = %d", _dmalloc_lock_on, THREAD_INIT_LOCK); #endif #if LOG_PNT_TIMEVAL { char time_buf[64]; dmalloc_message("starting time = %s", _dmalloc_ptimeval(&_dmalloc_start, time_buf, sizeof(time_buf), 0)); } #else #if HAVE_TIME /* NOT LOG_PNT_TIME */ { char time_buf[64]; dmalloc_message("starting time = %s", _dmalloc_ptime(&_dmalloc_start, time_buf, sizeof(time_buf), 0)); } #endif #endif #if HAVE_GETPID { /* we make it long in case it's big and we hope it will promote if not */ long our_pid = getpid(); dmalloc_message("process pid = %ld", our_pid); } #endif } /* * void _dmalloc_reopen_log * * DESCRIPTION: * * Re-open our log file which basically calls close() on the * logfile-fd. If we change the name of the log-file then we will * re-open the file. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ void _dmalloc_reopen_log(void) { /* no need to reopen it if it hasn't been reopened yet */ if (outfile_fd < 0) { return; } if (dmalloc_logpath == NULL) { dmalloc_message("Closing logfile to not be reopened"); } else { dmalloc_message("Closing logfile to be reopened as '%s'", dmalloc_logpath); } (void)close(outfile_fd); outfile_fd = -1; /* we don't call open here, we'll let the next message do it */ } #if LOG_PNT_TIMEVAL /* * char *_dmalloc_ptimeval * * DESCRIPTION: * * Print the time into local buffer. * * RETURNS: * * Poiner to the buf argument. * * ARGUMENTS: * * timeval_p -> Pointer to a time value. * * buf -> Internal buffer into which we are writing the time. * * buf_size -> Size of the buffer. * * elapsed_b -> Set to 1 to dump the elapsed instead of global time. */ char *_dmalloc_ptimeval(const TIMEVAL_TYPE *timeval_p, char *buf, const int buf_size, const int elapsed_b) { unsigned long hrs, mins, secs, usecs; secs = timeval_p->tv_sec; usecs = timeval_p->tv_usec; if (elapsed_b) { if (usecs >= _dmalloc_start.tv_usec) { usecs -= _dmalloc_start.tv_usec; } else { usecs = _dmalloc_start.tv_usec - usecs; secs--; } secs -= _dmalloc_start.tv_sec; hrs = secs / SECS_IN_HOUR; mins = (secs / SECS_IN_MIN) % MINS_IN_HOUR; secs %= SECS_IN_MIN; (void)loc_snprintf(buf, buf_size, "%lu:%02lu:%02lu.%06lu", hrs, mins, secs, usecs); } else { (void)loc_snprintf(buf, buf_size, "%lu.%06lu", secs, usecs); } return buf; } #endif /* NOTE: we do the ifdef this way for fillproto */ #if LOG_PNT_TIMEVAL == 0 && HAVE_TIME /* * char *_dmalloc_ptime * * DESCRIPTION: * * Print the time into local buffer. * * RETURNS: * * Poiner to the buf argument. * * ARGUMENTS: * * time_p -> Pointer to a time value. * * buf -> Internal buffer into which we are writing the time. * * buf_size -> Size of the buffer. * * elapsed_b -> Set to 1 to dump the elapsed instead of global time. */ char *_dmalloc_ptime(const TIME_TYPE *time_p, char *buf, const int buf_size, const int elapsed_b) { unsigned long hrs, mins, secs; secs = *time_p; if (elapsed_b) { secs -= _dmalloc_start; hrs = secs / SECS_IN_HOUR; mins = (secs / SECS_IN_MIN) % MINS_IN_HOUR; secs %= SECS_IN_MIN; (void)loc_snprintf(buf, buf_size, "%lu:%02lu:%02lu", hrs, mins, secs); } else { (void)loc_snprintf(buf, buf_size, "%lu", secs); } return buf; } #endif /* * void _dmalloc_vmessage * * DESCRIPTION: * * Message writer with vprintf like arguments which adds a line to the * dmalloc logfile. * * RETURNS: * * None. * * ARGUMENTS: * * format -> Printf-style format statement. * * args -> Already converted pointer to a stdarg list. */ void _dmalloc_vmessage(const char *format, va_list args) { char *str_p, *bounds_p; int len; str_p = message_str; bounds_p = str_p + sizeof(message_str); /* no logpath and no print then no workie */ if (dmalloc_logpath == NULL && ! BIT_IS_SET(_dmalloc_flags, DEBUG_PRINT_MESSAGES)) { return; } #if HAVE_GETPID && LOG_REOPEN if (dmalloc_logpath != NULL) { char *log_p; /* * This static pid will be checked to make sure it doesn't change. * We make it long in case it's big and we hope it will promote if * not. */ static long current_pid = -1; long new_pid; new_pid = getpid(); if (new_pid != current_pid) { /* NOTE: we need to do this _before_ the reopen otherwise we recurse */ current_pid = new_pid; /* if the new pid doesn't match the old one then reopen it */ if (current_pid >= 0) { /* this only works if there is a %p in the logpath */ for (log_p = dmalloc_logpath; *log_p != '\0'; log_p++) { if (*log_p == '%' && *(log_p + 1) == 'p') { _dmalloc_reopen_log(); break; } } } } } #endif /* do we need to open the logfile? */ if (dmalloc_logpath != NULL && outfile_fd < 0) { _dmalloc_open_log(); } #if HAVE_TIME #if LOG_TIME_NUMBER { long now; now = time(NULL); str_p += loc_snprintf(str_p, bounds_p - str_p, "%ld: ", now); } #endif /* LOG_TIME_NUMBER */ #if HAVE_CTIME #if LOG_CTIME_STRING { TIME_TYPE now; now = time(NULL); str_p += loc_snprintf(str_p, bounds_p - str_p, "%.24s: ", ctime(&now)); } #endif /* LOG_CTIME_STRING */ #endif /* HAVE_CTIME */ #endif /* HAVE_TIME */ #if LOG_ITERATION /* add the iteration number */ str_p += loc_snprintf(str_p, bounds_p - str_p, "%lu: ", _dmalloc_iter_c); #endif #if LOG_PID && HAVE_GETPID { /* we make it long in case it's big and we hope it will promote if not */ long our_pid = getpid(); /* add the pid to the log file */ str_p += loc_snprintf(str_p, bounds_p - str_p, "p%ld: ", our_pid); } #endif /* * NOTE: the following code, as well as the function definition * above, would need to be altered to conform to non-ANSI-C * specifications if necessary. */ /* write the format + info into str */ len = loc_vsnprintf(str_p, bounds_p - str_p, format, args); /* was it an empty format? */ if (len == 0) { return; } str_p += len; /* tack on a '\n' if necessary */ if (*(str_p - 1) != '\n') { *str_p++ = '\n'; *str_p = '\0'; } len = str_p - message_str; /* do we need to write the message to the logfile */ if (dmalloc_logpath != NULL) { (void)write(outfile_fd, message_str, len); } /* do we need to print the message? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_PRINT_MESSAGES)) { (void)write(STDERR, message_str, len); } } /* * void _dmalloc_die * * DESCRIPTION: * * Kill the program because of an internal malloc error. * * RETURNS: * * None. * * ARGUMENTS: * * silent_b -> Set to 1 to not drop log entries. */ void _dmalloc_die(const int silent_b) { char *stop_str; int len; if (! silent_b) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_ERROR_ABORT)) { stop_str = "dumping"; } else { stop_str = "halting"; } /* print a message that we are going down */ len = loc_snprintf(error_str, sizeof(error_str), "debug-malloc library: %s program, fatal error\r\n", stop_str); (void)write(STDERR, error_str, len); if (dmalloc_errno != ERROR_NONE) { len = loc_snprintf(error_str, sizeof(error_str), " Error: %s (err %d)\r\n", dmalloc_strerror(dmalloc_errno), dmalloc_errno); (void)write(STDERR, error_str, len); } } /* * set this in case the following generates a recursive call for * some dumb reason */ _dmalloc_aborting_b = 1; /* do I need to drop core? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_ERROR_ABORT) || BIT_IS_SET(_dmalloc_flags, DEBUG_ERROR_DUMP)) { #if USE_ABORT abort(); #else #ifdef KILL_PROCESS KILL_PROCESS; #endif #endif } /* * NOTE: this should not be exit() because fclose will free, etc */ _exit(1); } /* * void dmalloc_error * * DESCRIPTION: * * Handler of error codes. The caller should have set the errno already * * RETURNS: * * None. * * ARGUMENTS: * * func -> Function name for the logs. */ void dmalloc_error(const char *func) { /* do we need to log or print the error? */ if (dmalloc_logpath != NULL || BIT_IS_SET(_dmalloc_flags, DEBUG_PRINT_MESSAGES)) { /* default str value */ if (func == NULL) { func = "_malloc_error"; } /* print the malloc error message */ dmalloc_message("ERROR: %s: %s (err %d)", func, dmalloc_strerror(dmalloc_errno), dmalloc_errno); } /* do I need to abort? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_ERROR_ABORT)) { _dmalloc_die(0); } #if HAVE_FORK /* how about just drop core? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_ERROR_DUMP)) { if (fork() == 0) { _dmalloc_die(1); } } #endif } dmalloc-5.5.2/env.h000640 001751 001751 00000004604 10622115666 014054 0ustar00graygray000000 000000 /* * Defines for the env routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: env.h,v 1.25 2007/05/14 17:09:20 gray Exp $ */ #ifndef __ENV_H__ #define __ENV_H__ /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ /* * Break up ADDR_ALL into ADDR_P and ADDR_COUNT_P */ extern void _dmalloc_address_break(const char *addr_all, DMALLOC_PNT *addr_p, unsigned long *addr_count_p); /* * Break up START_ALL into SFILE_P, SLINE_P, and SCOUNT_P */ extern void _dmalloc_start_break(char *start_all, char **start_file_p, int *start_line_p, unsigned long *start_iter_p, unsigned long *start_size_p); /* * Process the values of dmalloc environ variable(s) from ENVIRON * string. */ extern void _dmalloc_environ_process(const char *env_str, DMALLOC_PNT *addr_p, unsigned long *addr_count_p, unsigned int *debug_p, unsigned long *interval_p, int *lock_on_p, char **logpath_p, char **start_file_p, int *start_line_p, unsigned long *start_iter_p, unsigned long *start_size_p, unsigned long *limit_p); /* * Set dmalloc environ variable(s) with the values (maybe SHORT debug * info) into BUF. */ extern void _dmalloc_environ_set(char *buf, const int buf_size, const int long_tokens_b, const DMALLOC_PNT address, const unsigned long addr_count, const unsigned int debug, const unsigned long interval, const int lock_on, const char *logpath, const char *start_file_p, const int start_line, const unsigned long start_iter, const unsigned long start_size, const unsigned long limit_val); /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __ENV_H__ */ dmalloc-5.5.2/env.c000640 001751 001751 00000025000 10622115666 014040 0ustar00graygray000000 000000 /* * Environment handling routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: env.c,v 1.37 2007/05/14 17:09:20 gray Exp $ */ /* * This file contains short routine(s) to process the environment * variable(s) used by the library to get the runtime option(s). */ #define DMALLOC_DISABLE #if HAVE_STDLIB_H # include #endif #if HAVE_STRING_H # include #endif #if HAVE_UNISTD_H # include /* for getpid */ #endif #include "conf.h" #include "dmalloc.h" #include "compat.h" #include "dmalloc_loc.h" #include "debug_tok.h" #include "env.h" #include "error.h" /* * Environmental labels. * * NOTE: the decision has been made _not_ to do the sizeof() hack for * portability reasons. */ #define ADDRESS_LABEL "addr" #define DEBUG_LABEL "debug" #define INTERVAL_LABEL "inter" #define LOCK_ON_LABEL "lockon" #define LOGFILE_LABEL "log" #define START_LABEL "start" #define LIMIT_LABEL "limit" #define ASSIGNMENT_CHAR '=' /* local variables */ static char log_path[512] = { '\0' }; /* storage for env path */ static char start_file[512] = { '\0' }; /* file to start at */ /****************************** local utilities ******************************/ /* * Hexadecimal STR to int translation */ static long hex_to_long(const char *str) { long ret; /* strip off spaces */ for (; *str == ' ' || *str == '\t'; str++) { } /* skip a leading 0[xX] */ if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) { str += 2; } for (ret = 0;; str++) { if (*str >= '0' && *str <= '9') { ret = ret * 16 + (*str - '0'); } else if (*str >= 'a' && *str <= 'f') { ret = ret * 16 + (*str - 'a' + 10); } else if (*str >= 'A' && *str <= 'F') { ret = ret * 16 + (*str - 'A' + 10); } else { break; } } return ret; } /***************************** exported routines *****************************/ /* * Break up ADDR_ALL into ADDR_P and ADDR_COUNT_P */ void _dmalloc_address_break(const char *addr_all, DMALLOC_PNT *addr_p, unsigned long *addr_count_p) { char *colon_p; SET_POINTER(addr_p, (DMALLOC_PNT)hex_to_long(addr_all)); if (addr_count_p != NULL) { colon_p = strchr(addr_all, ':'); if (colon_p != NULL) { *addr_count_p = loc_atoul(colon_p + 1); } } } /* * Break up START_ALL into SFILE_P, SLINE_P, and SCOUNT_P */ void _dmalloc_start_break(char *start_all, char **start_file_p, int *start_line_p, unsigned long *start_iter_p, unsigned long *start_size_p) { char *start_p; start_p = strchr(start_all, ':'); if (start_p != NULL) { (void)strncpy(start_file, start_all, sizeof(start_file)); start_file[sizeof(start_file) - 1] = '\0'; SET_POINTER(start_file_p, start_file); start_p = start_file + (start_p - start_all); *start_p = '\0'; SET_POINTER(start_line_p, atoi(start_p + 1)); SET_POINTER(start_iter_p, 0); SET_POINTER(start_size_p, 0); } else if (start_all[0] == 's') { SET_POINTER(start_file_p, NULL); SET_POINTER(start_line_p, 0); SET_POINTER(start_iter_p, 0); SET_POINTER(start_size_p, loc_atoul(start_all + 1)); } else { SET_POINTER(start_file_p, NULL); SET_POINTER(start_line_p, 0); if (start_all[0] == 'c') { SET_POINTER(start_iter_p, loc_atoul(start_all + 1)); } else { SET_POINTER(start_iter_p, loc_atoul(start_all)); } SET_POINTER(start_size_p, 0); } } /* * Process the values of dmalloc environ variable(s) from ENVIRON * string. */ void _dmalloc_environ_process(const char *env_str, DMALLOC_PNT *addr_p, unsigned long *addr_count_p, unsigned int *debug_p, unsigned long *interval_p, int *lock_on_p, char **logpath_p, char **start_file_p, int *start_line_p, unsigned long *start_iter_p, unsigned long *start_size_p, unsigned long *limit_p) { char *env_p, *this_p; char buf[1024]; int len, done_b = 0; unsigned int flags = 0; attr_t *attr_p; SET_POINTER(addr_p, NULL); SET_POINTER(addr_count_p, 0); SET_POINTER(debug_p, 0); SET_POINTER(interval_p, 0); SET_POINTER(lock_on_p, 0); SET_POINTER(logpath_p, NULL); SET_POINTER(start_file_p, NULL); SET_POINTER(start_line_p, 0); SET_POINTER(start_iter_p, 0); SET_POINTER(start_size_p, 0); SET_POINTER(limit_p, 0); /* make a copy */ (void)strncpy(buf, env_str, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; /* handle each of tokens, in turn */ for (env_p = buf, this_p = buf; ! done_b; env_p++, this_p = env_p) { /* find the comma of end */ for (;; env_p++) { if (*env_p == '\0') { done_b = 1; break; } if (*env_p == ',' && (env_p == buf || *(env_p - 1) != '\\')) { break; } } /* should we strip ' ' or '\t' here? */ if (this_p == env_p) { continue; } *env_p = '\0'; len = strlen(ADDRESS_LABEL); if (strncmp(this_p, ADDRESS_LABEL, len) == 0 && *(this_p + len) == ASSIGNMENT_CHAR) { this_p += len + 1; _dmalloc_address_break(this_p, addr_p, addr_count_p); continue; } len = strlen(DEBUG_LABEL); if (strncmp(this_p, DEBUG_LABEL, len) == 0 && *(this_p + len) == ASSIGNMENT_CHAR) { this_p += len + 1; SET_POINTER(debug_p, hex_to_long(this_p)); continue; } len = strlen(INTERVAL_LABEL); if (strncmp(this_p, INTERVAL_LABEL, len) == 0 && *(this_p + len) == ASSIGNMENT_CHAR) { this_p += len + 1; SET_POINTER(interval_p, loc_atoul(this_p)); continue; } len = strlen(LOCK_ON_LABEL); if (strncmp(this_p, LOCK_ON_LABEL, len) == 0 && *(this_p + len) == ASSIGNMENT_CHAR) { this_p += len + 1; SET_POINTER(lock_on_p, atoi(this_p)); continue; } /* get the dmalloc logfile name into a holding variable */ len = strlen(LOGFILE_LABEL); if (strncmp(this_p, LOGFILE_LABEL, len) == 0 && *(this_p + len) == ASSIGNMENT_CHAR) { this_p += len + 1; (void)strncpy(log_path, this_p, sizeof(log_path)); log_path[sizeof(log_path) - 1] = '\0'; SET_POINTER(logpath_p, log_path); continue; } /* * start checking the heap after X iterations OR * start at a file:line combination */ len = strlen(START_LABEL); if (strncmp(this_p, START_LABEL, len) == 0 && *(this_p + len) == ASSIGNMENT_CHAR) { this_p += len + 1; _dmalloc_start_break(this_p, start_file_p, start_line_p, start_iter_p, start_size_p); continue; } /* set the memory limit to the library */ len = strlen(LIMIT_LABEL); if (strncmp(this_p, LIMIT_LABEL, len) == 0 && *(this_p + len) == ASSIGNMENT_CHAR) { this_p += len + 1; SET_POINTER(limit_p, loc_atoul(this_p)); continue; } /* need to check the short/long debug options */ for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) { if (strcmp(this_p, attr_p->at_string) == 0) { flags |= attr_p->at_value; break; } } if (attr_p->at_string != NULL) { continue; } } /* append the token settings to the debug setting */ if (debug_p != NULL) { if (*debug_p == 0) { *debug_p = flags; } else { *debug_p |= flags; } } } /* * Set dmalloc environ variable(s) with the values (maybe SHORT debug * info) into BUF. */ void _dmalloc_environ_set(char *buf, const int buf_size, const int long_tokens_b, const DMALLOC_PNT address, const unsigned long addr_count, const unsigned int debug, const unsigned long interval, const int lock_on, const char *logpath, const char *start_file_p, const int start_line, const unsigned long start_iter, const unsigned long start_size, const unsigned long limit_val) { char *buf_p = buf, *bounds_p = buf + buf_size; if (debug > 0) { if (long_tokens_b) { attr_t *attr_p; for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) { if (debug & attr_p->at_value) { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s,", attr_p->at_string); } } } else { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%#x,", DEBUG_LABEL, ASSIGNMENT_CHAR, debug); } } if (address != NULL) { if (addr_count > 0) { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%#lx:%lu,", ADDRESS_LABEL, ASSIGNMENT_CHAR, (long)address, addr_count); } else { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%#lx,", ADDRESS_LABEL, ASSIGNMENT_CHAR, (long)address); } } if (interval > 0) { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%lu,", INTERVAL_LABEL, ASSIGNMENT_CHAR, interval); } if (lock_on > 0) { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%d,", LOCK_ON_LABEL, ASSIGNMENT_CHAR, lock_on); } if (logpath != NULL) { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%s,", LOGFILE_LABEL, ASSIGNMENT_CHAR, logpath); } if (start_file_p != NULL) { if (start_line > 0) { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%s:%d,", START_LABEL, ASSIGNMENT_CHAR, start_file_p, start_line); } else { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%s,", START_LABEL, ASSIGNMENT_CHAR, start_file_p); } } else if (start_iter > 0) { /* NOTE: there is an 'c' (for count) before the iter variable here */ buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%cc%lu,", START_LABEL, ASSIGNMENT_CHAR, start_iter); } else if (start_size > 0) { /* NOTE: there is an 's' before the size variable here */ buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%cs%lu,", START_LABEL, ASSIGNMENT_CHAR, start_size); } if (limit_val > 0) { buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%lu,", LIMIT_LABEL, ASSIGNMENT_CHAR, limit_val); } /* cut off the last comma */ if (buf_p > buf) { buf_p--; } *buf_p = '\0'; } dmalloc-5.5.2/debug_tok.h000640 001751 001751 00000014052 10622115666 015225 0ustar00graygray000000 000000 /* * Token attributes for the dmalloc program and _dmalloc_flags * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: debug_tok.h,v 1.41 2004/09/13 05:13:29 gray Exp $ */ #ifndef __DEBUG_TOK_H__ #define __DEBUG_TOK_H__ #include "dmalloc_loc.h" /* for BIT_FLAG */ /* * special debug codes which detail what debug features are enabled * NOTE: need to change debug_tok.h, mallocrc, and malloc.texi if any * capabilities are added/removed/updated */ /* logging */ #define DEBUG_LOG_STATS BIT_FLAG(0) /* generally log statistics */ #define DEBUG_LOG_NONFREE BIT_FLAG(1) /* report non-freed pointers */ #define DEBUG_LOG_KNOWN BIT_FLAG(2) /* report only known nonfreed*/ #define DEBUG_LOG_TRANS BIT_FLAG(3) /* log memory transactions */ /* 4 available - 20001107 */ #define DEBUG_LOG_ADMIN BIT_FLAG(5) /* log background admin info */ /* 6 available 20030508 */ /* 7 available - 20001107 */ #define DEBUG_LOG_BAD_SPACE BIT_FLAG(8) /* dump space from bad pnt */ #define DEBUG_LOG_NONFREE_SPACE BIT_FLAG(9) /* dump space from non-freed */ #define DEBUG_LOG_ELAPSED_TIME BIT_FLAG(18) /* log pnt elapsed time info */ #define DEBUG_LOG_CURRENT_TIME BIT_FLAG(19) /* log pnt current time info */ /* checking */ #define DEBUG_CHECK_FENCE BIT_FLAG(10) /* check fence-post errors */ #define DEBUG_CHECK_HEAP BIT_FLAG(11) /* examine heap adm structs */ /* 12 available - 20030608 */ #define DEBUG_CHECK_BLANK BIT_FLAG(13) /* check blank sections */ #define DEBUG_CHECK_FUNCS BIT_FLAG(14) /* check functions */ #define DEBUG_CHECK_SHUTDOWN BIT_FLAG(15) /* check pointers on shutdown*/ /* misc */ /* 16 available - 20040709 */ #define DEBUG_CATCH_SIGNALS BIT_FLAG(17) /* catch HUP, INT, and TERM */ /* 18,19 used above */ #define DEBUG_REALLOC_COPY BIT_FLAG(20) /* copy all reallocations */ #define DEBUG_FREE_BLANK BIT_FLAG(21) /* write over free'd memory */ #define DEBUG_ERROR_ABORT BIT_FLAG(22) /* abort on error else exit */ #define DEBUG_ALLOC_BLANK BIT_FLAG(23) /* write over to-be-alloced */ /* 24 available - 20030508 */ #define DEBUG_PRINT_MESSAGES BIT_FLAG(25) /* write messages to STDERR */ #define DEBUG_CATCH_NULL BIT_FLAG(26) /* quit before return null */ #define DEBUG_NEVER_REUSE BIT_FLAG(27) /* never reuse memory */ #define DEBUG_ERROR_FREE_NULL BIT_FLAG(28) /* catch free(0) */ /* 29 available - 20011130 */ #define DEBUG_ERROR_DUMP BIT_FLAG(30) /* dump core on error */ /* 31 is the high bit and off-limits */ /* * structure for mapping the string to the numerical token */ typedef struct { char *at_string; /* attribute string */ unsigned long at_value; /* value for the item */ char *at_desc; /* description string */ } attr_t; static attr_t attributes[] #ifdef __GNUC__ __attribute__ ((unused)) #endif = { { "none", 0, "no functionality" }, { "log-stats", DEBUG_LOG_STATS, "log general statistics" }, { "log-non-free", DEBUG_LOG_NONFREE, "log non-freed pointers" }, { "log-known", DEBUG_LOG_KNOWN, "log only known non-freed" }, { "log-trans", DEBUG_LOG_TRANS, "log memory transactions" }, { "log-admin", DEBUG_LOG_ADMIN, "log administrative info" }, { "log-bad-space", DEBUG_LOG_BAD_SPACE, "dump space from bad pnt" }, { "log-nonfree-space",DEBUG_LOG_NONFREE_SPACE, "dump space from non-freed pointers" }, { "log-elapsed-time", DEBUG_LOG_ELAPSED_TIME, "log elapsed-time for allocated pointer" }, { "log-current-time", DEBUG_LOG_CURRENT_TIME, "log current-time for allocated pointer" }, { "check-fence", DEBUG_CHECK_FENCE, "check fence-post errors" }, { "check-heap", DEBUG_CHECK_HEAP, "check heap adm structs" }, { "check-blank", DEBUG_CHECK_BLANK, "check mem overwritten by alloc-blank, free-blank" }, { "check-funcs", DEBUG_CHECK_FUNCS, "check functions" }, { "check-shutdown", DEBUG_CHECK_SHUTDOWN, "check heap on shutdown" }, { "catch-signals", DEBUG_CATCH_SIGNALS, "shutdown program on SIGHUP, SIGINT, SIGTERM" }, { "realloc-copy", DEBUG_REALLOC_COPY, "copy all re-allocations" }, { "free-blank", DEBUG_FREE_BLANK, "overwrite freed memory with \\0337 byte (0xdf)" }, { "error-abort", DEBUG_ERROR_ABORT, "abort immediately on error" }, { "alloc-blank", DEBUG_ALLOC_BLANK, "overwrite allocated memory with \\0332 byte (0xda)" }, { "print-messages", DEBUG_PRINT_MESSAGES, "write messages to stderr" }, { "catch-null", DEBUG_CATCH_NULL, "abort if no memory available"}, { "never-reuse", DEBUG_NEVER_REUSE, "never re-use freed memory" }, { "error-dump", DEBUG_ERROR_DUMP, "dump core on error, then continue" }, { "error-free-null", DEBUG_ERROR_FREE_NULL, "generate error when a 0L pointer is freed" }, /* * The following are here for backwards compatibility */ /* this is the default now and log-known is the opposite */ { "log-unknown", 0, "Disabled -- this is the default now, log-known is opposite" }, { "log-blocks", 0, "Disabled because of new heap organization" }, /* this is the default and force-linear is opposite */ { "allow-nonlinear", 0, "Disabled -- this is the default now" }, /* this is the default and error-free-null opposite */ { "allow-free-null", 0, "Disabled -- this is the default now, error-free-null is opposite" }, { "heap-check-map", 0, "Disabled because of new heap organization" }, { "check-lists", 0, "Disabled -- removed with new heap organization" }, { "force-linear", 0, "Disabled -- removed with new mmap usage" }, { NULL } }; #endif /* ! __DEBUG_TOK_H__ */ dmalloc-5.5.2/compat.h000640 001751 001751 00000013023 10622115666 014542 0ustar00graygray000000 000000 /* * Header file for compatibility functions. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: compat.h,v 1.42 2007/05/14 15:53:11 gray Exp $ */ #ifndef __COMPAT_H__ #define __COMPAT_H__ #if HAVE_STDARG_H # include /* for ... */ #endif #include "conf.h" /* for HAVE... */ /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ #if HAVE_ATOI == 0 /* * Turn a ascii-string into an integer which is returned */ extern int atoi(const char *str); #endif /* if HAVE_ATOI == 0 */ #if HAVE_ATOL == 0 /* * Turn a ascii-string into an integer which is returned */ extern long atol(const char *str); #endif /* if HAVE_ATOL == 0 */ /* * Local ascii to unsigned long function */ extern unsigned long loc_atoul(const char *str); /* * Local vsnprintf which handles the buffer-size or not. Returns the * number of characters copied into BUF. */ extern int loc_vsnprintf(char *buf, const int buf_size, const char *format, va_list args); /* * Local snprintf which handles the buf-size not. Returns the number * of characters copied into BUF. */ extern int loc_snprintf(char *buf, const int buf_size, const char *format, ...); #if HAVE_MEMCMP == 0 /* * Compare LEN characters, return -1,0,1 if STR1 is <,==,> STR2 */ extern int memcmp(const void *str1, const void *str2, DMALLOC_SIZE len); #endif /* if HAVE_MEMCMP == 0 */ #if HAVE_MEMCPY == 0 /* * Copy LEN characters from SRC to DEST */ extern void *memcpy(void *dest, const void *src, DMALLOC_SIZE len); #endif /* if HAVE_MEMCPY == 0 */ #if HAVE_MEMMOVE == 0 /* * Copy LEN characters from SRC to DEST */ extern void *memmove(void *dest, const void *src, DMALLOC_SIZE len); #endif /* if HAVE_MEMMOVE == 0 */ #if HAVE_MEMSET == 0 /* * Set LEN characters in STR to character CH */ extern void *memset(void *str, const int ch, DMALLOC_SIZE len); #endif /* if HAVE_MEMSET == 0 */ #if HAVE_STRCHR == 0 /* * Find CH in STR by searching backwards through the string */ extern char *strchr(const char *str, const int ch); #endif /* if HAVE_STRCHR == 0 */ #if HAVE_STRCMP == 0 /* * Returns -1,0,1 on whether STR1 is <,==,> STR2 */ extern int strcmp(const char *str1, const char *str2); #endif /* if HAVE_STRCMP == 0 */ #if HAVE_STRCPY == 0 /* * Copies STR2 to STR1. Returns STR1. */ extern char *strcpy(char *str1, const char *str2); #endif /* if HAVE_STRCPY == 0 */ #if HAVE_STRLEN == 0 /* * Return the length in characters of STR */ extern int strlen(const char *str); #endif /* if HAVE_STRLEN == 0 */ #if HAVE_STRNCMP == 0 /* * Compare at most LEN chars in STR1 and STR2 and return -1,0,1 or * STR1 - STR2 */ extern int strncmp(const char *str1, const char *str2, const int len); #endif /* if HAVE_STRNCMP == 0 */ #if HAVE_STRNCPY == 0 /* * Copy STR2 to STR1 until LEN or null */ extern char *strncpy(char *str1, const char *str2, const int len); #endif /* if HAVE_STRNCPY == 0 */ #if HAVE_STRRCHR == 0 /* * Find CH in STR by searching backwards through the string */ extern char *strrchr(const char *str, const int ch); #endif /* if HAVE_STRRCHR == 0 */ #if HAVE_STRSEP == 0 /* * char *strsep * * DESCRIPTION: * * This is a function which should be in libc in every Unix. Grumble. * It basically replaces the strtok function because it is reentrant. * This tokenizes a string by returning the next token in a string and * punching a \0 on the first delimiter character past the token. The * difference from strtok is that you pass in the address of a string * pointer which will be shifted allong the buffer being processed. * With strtok you passed in a 0L for subsequant calls. Yeach. * * This will count the true number of delimiter characters in the string * and will return an empty token (one with \0 in the zeroth position) * if there are two delimiter characters in a row. * * Consider the following example: * * char *tok, *str_p = "1,2,3, hello there "; * * while (1) { tok = strsep(&str_p, " ,"); if (tok == 0L) { break; } } * * strsep will return as tokens: "1", "2", "3", "", "hello", "there", "". * Notice the two empty "" tokens where there were two delimiter * characters in a row ", " and at the end of the string where there * was an extra delimiter character. If you want to ignore these * tokens then add a test to see if the first character of the token * is \0. * * RETURNS: * * Success - Pointer to the next delimited token in the string. * * Failure - 0L if there are no more tokens. * * ARGUMENTS: * * string_p - Pointer to a string pointer which will be searched for * delimiters. \0's will be added to this buffer. * * delim - List of delimiter characters which separate our tokens. It * does not have to remain constant through all calls across the same * string. */ extern char *strsep(char **string_p, const char *delim); #endif /* if HAVE_STRSEP == 0 */ /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __COMPAT_H__ */ dmalloc-5.5.2/compat.c000640 001751 001751 00000025032 10622115666 014540 0ustar00graygray000000 000000 /* * Compatibility functions for those systems who are missing them. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: compat.c,v 1.57 2007/05/14 15:53:11 gray Exp $ */ /* * This file holds the compatibility routines necessary for the library to * function just in case your system does not have them. */ #include /* for vsprintf */ #if HAVE_STDARG_H # include /* for ... */ #endif #define DMALLOC_DISABLE #include "conf.h" #include "dmalloc.h" #include "compat.h" #include "dmalloc_loc.h" #if HAVE_ATOI == 0 /* * Turn a ascii-string into an integer which is returned */ int atoi(const char *str) { const char *str_p; int sign = 1, result = 0; /* skip opening white space */ for (str_p = str; *str_p == ' ' || *str_p == '\t'; str_p++) { } /* handle sign */ if (*str_p == '-') { sign = -1; str_p++; } else if (*str_p == '+') { /* sign is already 1 */ str_p++; } /* skip more white space */ for (; *str_p == ' ' || *str_p == '\t'; str_p++) { } /* now add up all digits */ for (; *str_p >= '0' && *str_p <= '9'; str_p++) { result = result * 10 + *str_p - '0'; } return result * sign; } #endif /* HAVE_ATOI == 0 */ #if HAVE_ATOL == 0 /* * Turn a ascii-string into an integer which is returned */ long atol(const char *str) { const char *str_p; long sign = 1, result = 0; /* skip opening white space */ for (str_p = str; *str_p == ' ' || *str_p == '\t'; str_p++) { } /* handle sign */ if (*str_p == '-') { sign = -1; str_p++; } else if (*str_p == '+') { /* sign is already 1 */ str_p++; } /* skip more white space */ for (; *str_p == ' ' || *str_p == '\t'; str_p++) { } /* now add up all digits */ for (; *str_p >= '0' && *str_p <= '9'; str_p++) { result = result * (long)10 + (long)(*str_p - '0'); } return result * sign; } #endif /* HAVE_ATOL == 0 */ /* * Local ascii to unsigned long function */ unsigned long loc_atoul(const char *str) { const char *str_p; unsigned long result = 0; /* skip opening white space */ for (str_p = str; *str_p == ' ' || *str_p == '\t'; str_p++) { } /* now add up all digits */ for (; *str_p >= '0' && *str_p <= '9'; str_p++) { result = result * (unsigned long)10 + (unsigned long)(*str_p - '0'); } return result; } /* * Local vsnprintf which handles the buffer-size or not. Returns the * number of characters copied into BUF. */ int loc_vsnprintf(char *buf, const int buf_size, const char *format, va_list args) { char *buf_p; #if HAVE_VSNPRINTF (void)vsnprintf(buf, buf_size, format, args); #else #if HAVE_VPRINTF (void)vsprintf(buf, format, args); #else /* Oh well. Just do a strcpy of the format */ (void)strncpy(buf, format, buf_size - 1); buf[buf_size - 1] = '\0'; #endif #endif /* now find the end of the buffer */ for (buf_p = buf; *buf_p != '\0'; buf_p++) { } return buf_p - buf; } /* * Local snprintf which handles the buf-size not. Returns the number * of characters copied into BUF. */ int loc_snprintf(char *buf, const int buf_size, const char *format, ...) { va_list args; int len; va_start(args, format); len = loc_vsnprintf(buf, buf_size, format, args); va_end(args); return len; } #if HAVE_MEMCMP == 0 /* * Compare LEN characters, return -1,0,1 if STR1 is <,==,> STR2 */ int memcmp(const void *str1, const void *str2, DMALLOC_SIZE len) { const unsigned char *str1_p, *str2_p; for (str1_p = str1, str2_p = str2; len > 0; len--, str1_p++, str2_p++) { if (*str1_p != *str2_p) { return *str1_p - *str2_p; } } return 0; } #endif /* HAVE_MEMCMP == 0 */ #if HAVE_MEMCPY == 0 /* * Copy LEN characters from SRC to DEST */ void *memcpy(void *dest, const void *src, DMALLOC_SIZE len) { unsigned char *dest_p; const unsigned char *src_p; int byte_c; if (len <= 0) { return; } /* * NOTE: should we check to make sure that it's not overlapped but * there may be times where people want this, albeit bizarre, * behavior. */ src_p = src; dest_p = dest; if (src_p <= dest_p && src_p + (len - 1) >= dest_p) { /* overlap, must copy right-to-left. */ src_p += len - 1; dest_p += len - 1; for (byte_c = 0; byte_c < len; byte_c++) { *dest_p-- = *src_p--; } } else { for (byte_c = 0; byte_c < len; byte_c++) { *dest_p++ = *src_p++; } } return dest; } #endif /* HAVE_MEMCPY == 0 */ #if HAVE_MEMMOVE == 0 /* * Copy LEN characters from SRC to DEST */ void *memmove(void *dest, const void *src, DMALLOC_SIZE len) { unsigned char *dest_p; const unsigned char *src_p; int byte_c; if (len <= 0) { return; } src_p = src; dest_p = dest; if (src_p <= dest_p && src_p + (len - 1) >= dest_p) { /* overlap, must copy right-to-left. */ src_p += len - 1; dest_p += len - 1; for (byte_c = 0; byte_c < len; byte_c++) { *dest_p-- = *src_p--; } } else { for (byte_c = 0; byte_c < len; byte_c++) { *dest_p++ = *src_p++; } } return dest; } #endif /* HAVE_MEMMOVE == 0 */ #if HAVE_MEMSET == 0 /* * Set LEN characters in STR to character CH */ void *memset(void *str, const int ch, DMALLOC_SIZE len) { unsigned char *str_p = str; for (; len > 0; len--, str_p++) { *(unsigned char *)str_p = (unsigned char)ch; } return str; } #endif /* HAVE_MEMSET == 0 */ #if HAVE_STRCHR == 0 /* * Find CH in STR by searching backwards through the string */ char *strchr(const char *str, const int ch) { const char *str_p; for (str_p = str; *str_p != '\0'; str_p++) { if (*str_p == (char)ch) { return (char *)str_p; } } if (ch == '\0') { return (char *)str_p; } else { return NULL; } } #endif /* HAVE_STRCHR == 0 */ #if HAVE_STRCMP == 0 /* * Returns -1,0,1 on whether STR1 is <,==,> STR2 */ int strcmp(const char *str1, const char *str2) { for (; *str1 != '\0' && *str1 == *str2; str1++, str2++) { } return *str1 - *str2; } #endif /* HAVE_STRCMP == 0 */ #if HAVE_STRCPY == 0 /* * Copies STR2 to STR1. Returns STR1. */ char *strcpy(char *str1, const char *str2) { char *str_p; for (str_p = str1; *str2 != '\0'; str_p++, str2++) { *str_p = *str2; } *str_p = '\0'; return str1; } #endif /* HAVE_STRCPY == 0 */ #if HAVE_STRLEN == 0 /* * Return the length in characters of STR */ int strlen(const char *str) { int len; for (len = 0; *str != '\0'; str++, len++) { } return len; } #endif /* HAVE_STRLEN == 0 */ #if HAVE_STRNCMP == 0 /* * Compare at most LEN chars in STR1 and STR2 and return -1,0,1 or * STR1 - STR2 */ int strncmp(const char *str1, const char *str2, const int len) { int len_c; for (len_c = 0; len_c < len; len_c++, str1++, str2++) { if (*str1 != *str2 || *str1 == '\0') { return *str1 - *str2; } } return 0; } #endif /* HAVE_STRNCMP == 0 */ #if HAVE_STRNCPY == 0 /* * Copy STR2 to STR1 until LEN or null */ char *strncpy(char *str1, const char *str2, const int len) { char *str1_p, null_reached_b = 0; int len_c; for (len_c = 0, str1_p = str1; len_c < len; len_c++, str1_p++, str2++) { if (null_reached || *str2 == '\0') { null_reached = 1; *str1_p = '\0'; } else { *str1_p = *str2; } } return str1; } #endif /* HAVE_STRNCPY == 0 */ #if HAVE_STRRCHR == 0 /* * Find CH in STR by searching backwards through the string */ char *strrchr(const char *str, const int ch) { const char *str_p, *pnt = NULL; for (str_p = str; *str_p != '\0'; str_p++) { if (*str_p == (char)ch) { pnt = str_p; } } if (ch == '\0') { return (char *)str_p; } else { return (char *)pnt_p; } } #endif /* HAVE_STRRCHR == 0 */ #if HAVE_STRSEP == 0 /* * char *strsep * * DESCRIPTION: * * This is a function which should be in libc in every Unix. Grumble. * It basically replaces the strtok function because it is reentrant. * This tokenizes a string by returning the next token in a string and * punching a \0 on the first delimiter character past the token. The * difference from strtok is that you pass in the address of a string * pointer which will be shifted allong the buffer being processed. * With strtok you passed in a 0L for subsequant calls. Yeach. * * This will count the true number of delimiter characters in the string * and will return an empty token (one with \0 in the zeroth position) * if there are two delimiter characters in a row. * * Consider the following example: * * char *tok, *str_p = "1,2,3, hello there "; * * while (1) { tok = strsep(&str_p, " ,"); if (tok == 0L) { break; } } * * strsep will return as tokens: "1", "2", "3", "", "hello", "there", "". * Notice the two empty "" tokens where there were two delimiter * characters in a row ", " and at the end of the string where there * was an extra delimiter character. If you want to ignore these * tokens then add a test to see if the first character of the token * is \0. * * RETURNS: * * Success - Pointer to the next delimited token in the string. * * Failure - 0L if there are no more tokens. * * ARGUMENTS: * * string_p - Pointer to a string pointer which will be searched for * delimiters. \0's will be added to this buffer. * * delim - List of delimiter characters which separate our tokens. It * does not have to remain constant through all calls across the same * string. */ char *strsep(char **string_p, const char *delim) { char *str_p, *tok; const char *delim_p; /* no tokens left? */ str_p = *string_p; if (str_p == 0L) { return 0L; } /* now find end of token */ tok = str_p; for (; *str_p != '\0'; str_p++) { for (delim_p = delim; *delim_p != '\0'; delim_p++) { if (*delim_p == *str_p) { /* punch the '\0' */ *str_p = '\0'; *string_p = str_p + 1; return tok; } } } /* there are no more delimiter characters */ *string_p = 0L; return tok; } #endif /* HAVE_STRSEP == 0 */ dmalloc-5.5.2/chunk_loc.h000640 001751 001751 00000013622 10622115666 015231 0ustar00graygray000000 000000 /* * Local defines for the low level memory routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: chunk_loc.h,v 1.70 2003/06/09 23:14:17 gray Exp $ */ #ifndef __CHUNK_LOC_H__ #define __CHUNK_LOC_H__ #include "conf.h" /* up here for _INCLUDE */ #include "dmalloc_loc.h" /* for DMALLOC_SIZE */ /* for thread-id types -- see conf.h */ #if LOG_THREAD_ID #ifdef THREAD_INCLUDE #include THREAD_INCLUDE #endif #endif /* for time type -- see settings.h */ #if LOG_PNT_TIMEVAL # ifdef TIMEVAL_INCLUDE # include TIMEVAL_INCLUDE # endif #else # if LOG_PNT_TIME # ifdef TIME_INCLUDE # include TIME_INCLUDE # endif # endif #endif /* log-bad-space info */ #define SPECIAL_CHARS "\"\"''\\\\n\nr\rt\tb\bf\fa\007" /* * Maximum level in the skip list. This implies that we can only * store 2^32 entries optimally. Needless to say this is plenty. */ #define MAX_SKIP_LEVEL 32 /* memory table settings */ #define MEM_ALLOC_ENTRIES (MEMORY_TABLE_SIZE * 2) #define MEM_CHANGED_ENTRIES (MEMORY_TABLE_SIZE * 2) /* NOTE: FENCE_BOTTOM_SIZE and FENCE_TOP_SIZE defined in settings.h */ #define FENCE_OVERHEAD_SIZE (FENCE_BOTTOM_SIZE + FENCE_TOP_SIZE) #define FENCE_MAGIC_BOTTOM 0xC0C0AB1B #define FENCE_MAGIC_TOP 0xFACADE69 /* smallest allocated block */ #define CHUNK_SMALLEST_BLOCK \ (FENCE_BOTTOM_SIZE + DEFAULT_SMALLEST_ALLOCATION) /* flags associated with the skip_alloc_t type's sa_flags field */ #define ALLOC_FLAG_USER BIT_FLAG(0) /* slot is user allocated */ #define ALLOC_FLAG_FREE BIT_FLAG(1) /* slot is free */ #define ALLOC_FLAG_EXTERN BIT_FLAG(2) /* slot allocated externally */ #define ALLOC_FLAG_ADMIN BIT_FLAG(3) /* administrative space */ #define ALLOC_FLAG_BLANK BIT_FLAG(4) /* slot has been blanked */ #define ALLOC_FLAG_FENCE BIT_FLAG(5) /* slot is fence posted */ #define ALLOC_FLAG_VALLOC BIT_FLAG(6) /* slot is block aligned */ /* * Below defines an allocation structure either on the free or used * list. It tracks allocations that fit in partial, one, or many * basic-blocks. It stores some optional fields for recording * information about the pointer. */ typedef struct skip_alloc_st { unsigned char sa_flags; /* what it is */ /* some small data types up front to save on space */ unsigned char sa_level_n; /* how tall our node is */ unsigned short sa_line; /* line where it was allocated */ unsigned int sa_user_size; /* size requested by user (wo fence) */ unsigned int sa_total_size; /* total size of the block */ void *sa_mem; /* pointer to the memory in question */ const char *sa_file; /* .c filename where allocated */ unsigned long sa_use_iter; /* when last ``used'' */ #if LOG_PNT_SEEN_COUNT unsigned long sa_seen_c; /* times pointer was seen */ #endif #if LOG_PNT_ITERATION unsigned long sa_iteration; /* interation when pointer alloced */ #endif #if LOG_PNT_TIMEVAL TIMEVAL_TYPE sa_timeval; /* time when pointer alloced */ #else #if LOG_PNT_TIME TIME_TYPE sa_time; /* time when pointer alloced */ #endif #endif #if LOG_PNT_THREAD_ID THREAD_TYPE sa_thread_id; /* thread id which allocaed pnt */ #endif /* * Array of next pointers. This may extend past the end of the * function if we allocate for space larger than the structure. */ struct skip_alloc_st *sa_next_p[1]; } skip_alloc_t; /* * This macro helps us determine how much memory we need to store to * hold all of the next pointers in the skip-list entry. So if we are * at level 0 then this will have no extra next pointers since there * already is one inside of skip_alloc_t. */ #define SKIP_SLOT_SIZE(next_n) \ (sizeof(skip_alloc_t) + sizeof(skip_alloc_t *) * (next_n)) /* entry block magic numbers */ #define ENTRY_BLOCK_MAGIC1 0xEBEB1111 /* for the eb_magic1 field */ #define ENTRY_BLOCK_MAGIC2 0xEBEB2222 /* for the eb_magic2 field */ #define ENTRY_BLOCK_MAGIC3 0xEBEB3333 /* written at end of eb block*/ /* * The following structure is written at the front of a skip-list * entry administrative block. */ typedef struct entry_block_st { unsigned int eb_magic1; /* magic number */ unsigned int eb_level_n; /* the levels which are stored here */ struct entry_block_st *eb_next_p; /* pointer to next block */ unsigned int eb_magic2; /* magic number */ skip_alloc_t eb_first_slot; /* first slot in the block */ /* * the rest are after this one but we don't really know the size * because it is based on the skip-level. */ /* * At the end of the block is the MAGIC3 value but we can't define * it in a structure. */ } entry_block_t; /* * The following structure is used to figure out a number of bits of * information about a user allocation. */ typedef struct { int pi_fence_b; /* fence-posts are on for pointer */ int pi_valloc_b; /* pointer is valloc-aligned */ int pi_blanked_b; /* pointer was blanked */ void *pi_alloc_start; /* pnt to start of allocation */ void *pi_fence_bottom; /* pnt to the bottom fence area */ void *pi_user_start; /* pnt to start of user allocation */ void *pi_user_bounds; /* pnt past end of user allocation */ void *pi_fence_top; /* pnt to the top fence area */ void *pi_upper_bounds; /* pnt to highest available user area*/ void *pi_alloc_bounds; /* pnt past end of total allocation */ } pnt_info_t; #endif /* ! __CHUNK_LOC_H__ */ dmalloc-5.5.2/chunk.h000640 001751 001751 00000023416 10622115666 014376 0ustar00graygray000000 000000 /* * Defines for low level memory management routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: chunk.h,v 1.72 2007/03/23 13:33:06 gray Exp $ */ #ifndef __CHUNK_H__ #define __CHUNK_H__ /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ /* limit in how much memory we are allowed to allocate */ extern unsigned long _dmalloc_memory_limit; /* total number of bytes that the heap has allocated */ extern unsigned long _dmalloc_alloc_total; /* * int _dmalloc_chunk_startup * * DESCRIPTION: * * Startup the low level malloc routines. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * None. */ extern int _dmalloc_chunk_startup(void); /* * char *_dmalloc_chunk_desc_pnt * * DESCRIPTION: * * Write into a buffer a pointer description with file and * line-number. * * RETURNS: * * Pointer to buffer 1st argument. * * ARGUMENTS: * * buf <-> Passed in buffer which will be filled with a description of * the pointer. * * buf_size -> Size of the buffer in bytes. * * file -> File name, return address, or NULL. * * line -> Line number or 0. */ extern char *_dmalloc_chunk_desc_pnt(char *buf, const int buf_size, const char *file, const unsigned int line); /* * int _dmalloc_chunk_read_info * * DESCRIPTION: * * Return some information associated with a pointer. * * RETURNS: * * Success - 1 pointer is okay * * Failure - 0 problem with pointer * * ARGUMENTS: * * user_pnt -> Pointer we are checking. * * where <- Where the check is being made from. * * user_size_p <- Pointer to an unsigned int which, if not NULL, will * be set to the size of bytes that the user requested. * * alloc_size_p <- Pointer to an unsigned int which, if not NULL, will * be set to the total given size of bytes including block overhead. * * file_p <- Pointer to a character pointer which, if not NULL, will * be set to the file where the pointer was allocated. * * line_p <- Pointer to a character pointer which, if not NULL, will * be set to the line-number where the pointer was allocated. * * ret_attr_p <- Pointer to a void pointer, if not NULL, will be set * to the return-address where the pointer was allocated. * * seen_cp <- Pointer to an unsigned long which, if not NULL, will be * set to the number of times the pointer has been "seen". * * used_p <- Pointer to an unsigned long which, if not NULL, will be * set to the last time the pointer was "used". * * valloc_bp <- Pointer to an integer which, if not NULL, will be set * to 1 if the pointer was allocated with valloc otherwise 0. * * fence_bp <- Pointer to an integer which, if not NULL, will be set * to 1 if the pointer has the fence bit set otherwise 0. */ extern int _dmalloc_chunk_read_info(const void *user_pnt, const char *where, unsigned int *user_size_p, unsigned int *alloc_size_p, char **file_p, unsigned int *line_p, void **ret_attr_p, unsigned long **seen_cp, unsigned long *used_p, int *valloc_bp, int *fence_bp); /* * int _dmalloc_chunk_heap_check * * DESCRIPTION: * * Run extensive tests on the entire heap. * * RETURNS: * * Success - 1 if the heap is okay * * Failure - 0 if a problem was detected * * ARGUMENTS: * * None. */ extern int _dmalloc_chunk_heap_check(void); /* * int _dmalloc_chunk_pnt_check * * DESCRIPTION: * * Run extensive tests on a pointer. * * RETURNS: * * Success - 1 if the pointer is okay * * Failure - 0 if not * * ARGUMENTS: * * func -> Function string which is checking the pointer. * * user_pnt -> Pointer we are checking. * * exact_b -> Set to 1 to find the pointer specifically. Otherwise we * can find the pointer inside of an allocation. * * strlen_b -> Make sure that pnt can hold at least a strlen + 1 * bytes. If 0 then ignore. * * min_size -> Make sure that pnt can hold at least that many bytes. * If 0 then ignore. */ extern int _dmalloc_chunk_pnt_check(const char *func, const void *user_pnt, const int exact_b, const int strlen_b, const int min_size); /* * void *_dmalloc_chunk_malloc * * DESCRIPTION: * * Allocate a chunk of memory. * * RETURNS: * * Success - Valid pointer. * * Failure - NULL * * ARGUMENTS: * * file -> File-name or return-address location of the allocation. * * line -> Line-number location of the allocation. * * size -> Number of bytes to allocate. * * func_id -> Calling function-id as defined in dmalloc.h. * * alignment -> If greater than 0 then try to align the returned * block. */ extern void *_dmalloc_chunk_malloc(const char *file, const unsigned int line, const unsigned long size, const int func_id, const unsigned int alignment); /* * int _dmalloc_chunk_free * * DESCRIPTION: * * Free a user pointer from the heap. * * RETURNS: * * Success - FREE_NOERROR * * Failure - FREE_ERROR * * ARGUMENTS: * * file -> File-name or return-address location of the allocation. * * line -> Line-number location of the allocation. * * user_pnt -> Pointer we are freeing. * * func_id -> Function ID */ extern int _dmalloc_chunk_free(const char *file, const unsigned int line, void *user_pnt, const int func_id); /* * void *_dmalloc_chunk_realloc * * DESCRIPTION: * * Re-allocate a chunk of memory either shrinking or expanding it. * * RETURNS: * * Success - Valid pointer. * * Failure - NULL * * ARGUMENTS: * * file -> File-name or return-address location of the allocation. * * line -> Line-number location of the allocation. * * old_user_pnt -> Old user pointer that we are reallocating. * * new_size -> New-size to change the pointer. * * func_id -> Calling function-id as defined in dmalloc.h. */ extern void *_dmalloc_chunk_realloc(const char *file, const unsigned int line, void *old_user_pnt, const unsigned long new_size, const int func_id); /* * void _dmalloc_chunk_log_stats * * DESCRIPTION: * * Log general statistics from the heap to the logfile. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ extern void _dmalloc_chunk_log_stats(void); /* * void _dmalloc_chunk_log_changed * * DESCRIPTION: * * Log the pointers that has changed since a pointer in time. * * RETURNS: * * None. * * ARGUMENTS: * * mark -> Dmalloc counter used to mark a specific time so that * servers can check on the changed pointers. * * log_non_free_b -> If set to 1 then log the new not-freed * (i.e. used) pointers. * * log_free_b -> If set to 1 then log the new freed pointers. * * details_b -> If set to 1 then dump the individual pointer entries * instead of just the summary. */ extern void _dmalloc_chunk_log_changed(const unsigned long mark, const int log_not_freed_b, const int log_freed_b, const int details_b); /* * unsigned long _dmalloc_chunk_count_changed * * DESCRIPTION: * * Return the pointers that has changed since a pointer in time. * * RETURNS: * * Number of bytes changed since mark. * * ARGUMENTS: * * mark -> Dmalloc counter used to mark a specific time so that * servers can check on the changed pointers. * * count_non_free_b -> If set to 1 then count the new not-freed * (i.e. used) pointers. * * count_free_b -> If set to 1 then count the new freed pointers. */ extern unsigned long _dmalloc_chunk_count_changed(const unsigned long mark, const int count_not_freed_b, const int count_freed_b); /* * void _dmalloc_chunk_get_stats * * DESCRIPTION: * * Return a number of statistics about the current heap. * * RETURNS: * * None. * * ARGUMENTS: * * heap_low_p <- Pointer to pointer which, if not 0L, will be set to * the low address in the heap. * * heap_high_p <- Pointer to pointer which, if not 0L, will be set to * the high address in the heap. * * total_space_p <- Pointer to an unsigned long which, if not 0L, will * be set to the total space managed by the library including user * space, administrative space, and overhead. * * user_space_p <- Pointer to an unsigned long which, if not 0L, will * be set to the space given to the user process (allocated and free). * * current_allocated_p <- Pointer to an unsigned long which, if not * 0L, will be set to the current allocated space given to the user * process. * * current_pnt_np <- Pointer to an unsigned long which, if not 0L, * will be set to the current number of pointers allocated by the user * process. * * max_allocated_p <- Pointer to an unsigned long which, if not 0L, * will be set to the maximum allocated space given to the user * process. * * max_pnt_np <- Pointer to an unsigned long which, if not 0L, will be * set to the maximum number of pointers allocated by the user * process. * * max_one_p <- Pointer to an unsigned long which, if not 0L, will be * set to the maximum allocated with 1 call by the user process. */ extern void _dmalloc_chunk_get_stats(void **heap_low_p, void **heap_high_p, unsigned long *total_space_p, unsigned long *user_space_p, unsigned long *current_allocated_p, unsigned long *current_pnt_np, unsigned long *max_allocated_p, unsigned long *max_pnt_np, unsigned long *max_one_p); /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __CHUNK_H__ */ dmalloc-5.5.2/chunk.c000640 001751 001751 00000252634 10622115666 014377 0ustar00graygray000000 000000 /* * Memory chunk low-level allocation routines * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: chunk.c,v 1.217 2007/03/25 18:53:41 gray Exp $ */ /* * This file contains algorithm level routine for the heap. They handle the * manipulation and administration of chunks of memory. */ #include #if HAVE_STRING_H # include #endif #if HAVE_STDLIB_H # include #endif #define DMALLOC_DISABLE #include "conf.h" #if LOG_PNT_TIMEVAL #ifdef TIMEVAL_INCLUDE # include TIMEVAL_INCLUDE #endif #else # if LOG_PNT_TIME # ifdef TIME_INCLUDE # include TIME_INCLUDE # endif # endif #endif #include "dmalloc.h" #include "chunk.h" #include "chunk_loc.h" #include "compat.h" #include "debug_tok.h" #include "dmalloc_loc.h" #include "dmalloc_rand.h" #include "dmalloc_tab.h" #include "error.h" #include "error_val.h" #include "heap.h" /* * Library Copyright and URL information for ident and what programs */ #if IDENT_WORKS #ident "@(#) $Copyright: Dmalloc package Copyright 2007 by Gray Watson $" #ident "@(#) $URL: Source for dmalloc available from http://dmalloc.com/ $" #else static char *copyright = "@(#) $Copyright: Dmalloc package Copyright 2007 by Gray Watson $"; static char *source_url = "@(#) $URL: Source for dmalloc available from http://dmalloc.com/ $"; #endif #if LOCK_THREADS #if IDENT_WORKS #ident "@(#) $Information: lock-threads is enabled $" #else static char *information = "@(#) $Information: lock-threads is enabled $"; #endif #endif /* * exported variables */ /* limit in how much memory we are allowed to allocate */ unsigned long _dmalloc_memory_limit = 0; /* total number of bytes that the heap has allocated */ unsigned long _dmalloc_alloc_total = 0; /* * local variables */ /* * Skip list of our free list sorted by size in bytes. Bit of a hack * here. Basically we cannot do a alloc for the structure and we'd * like it to be static storage so we allocate an array of them to * make sure we have enough forward pointers, when all we need is * SKIP_SLOT_SIZE(MAX_SKIP_LEVEL + 1) bytes. */ static skip_alloc_t skip_free_alloc[MAX_SKIP_LEVEL /* read note ^^ */]; static skip_alloc_t *skip_free_list = skip_free_alloc; /* skip list of all of our allocated blocks sorted by address */ static skip_alloc_t skip_address_alloc[MAX_SKIP_LEVEL /* read note ^^ */]; static skip_alloc_t *skip_address_list = skip_address_alloc; /* update slots which we use to update the skip lists */ static skip_alloc_t skip_update[MAX_SKIP_LEVEL /* read note ^^ */]; /* linked list of slots of various sizes */ static skip_alloc_t *entry_free_list[MAX_SKIP_LEVEL]; /* linked list of blocks of the sizes */ static entry_block_t *entry_blocks[MAX_SKIP_LEVEL]; /* linked list of freed blocks on hold waiting for the FREED_POINTER_DELAY */ static skip_alloc_t *free_wait_list_head = NULL; static skip_alloc_t *free_wait_list_tail = NULL; /* administrative structures */ static char fence_bottom[FENCE_BOTTOM_SIZE]; static char fence_top[FENCE_TOP_SIZE]; static int bit_sizes[BASIC_BLOCK]; /* number bits for div-blocks*/ /* memory tables */ static mem_table_t mem_table_alloc[MEM_ALLOC_ENTRIES]; static int mem_table_alloc_c = 0; static mem_table_t mem_table_changed[MEM_CHANGED_ENTRIES]; static int mem_table_changed_c = 0; /* memory stats */ static unsigned long alloc_current = 0; /* current memory usage */ static unsigned long alloc_maximum = 0; /* maximum memory usage */ static unsigned long alloc_cur_given = 0; /* current mem given */ static unsigned long alloc_max_given = 0; /* maximum mem given */ static unsigned long alloc_one_max = 0; /* maximum at once */ static unsigned long free_space_bytes = 0; /* count the free bytes */ /* pointer stats */ static unsigned long alloc_cur_pnts = 0; /* current pointers */ static unsigned long alloc_max_pnts = 0; /* maximum pointers */ static unsigned long alloc_tot_pnts = 0; /* total pointers */ /* admin counts */ static unsigned long heap_check_c = 0; /* count of heap-checks */ static unsigned long user_block_c = 0; /* count of blocks */ static unsigned long admin_block_c = 0; /* count of admin blocks */ /* alloc counts */ static unsigned long func_malloc_c = 0; /* count the mallocs */ static unsigned long func_calloc_c = 0; /* # callocs, done in alloc */ static unsigned long func_realloc_c = 0; /* count the reallocs */ static unsigned long func_recalloc_c = 0; /* count the reallocs */ static unsigned long func_memalign_c = 0; /* count the memaligns */ static unsigned long func_valloc_c = 0; /* count the veallocs */ static unsigned long func_new_c = 0; /* count the news */ static unsigned long func_free_c = 0; /* count the frees */ static unsigned long func_delete_c = 0; /* count the deletes */ /**************************** skip list routines *****************************/ /* * static int random_level * * DESCRIPTION: * * Return a random level to be associated with a new free-list entry. * * RETURNS: * * Random level from 0 to max_level - 1. * * ARGUMENTS: * * max_level -> Maximum level of the free-list. */ static int random_level(const int max_level) { int level_c; for (level_c = 0; level_c < max_level; level_c++) { /* * Basically we count the number of times that the random number * generator returns an odd number in a row. On average this * should return 0 1/2 the time, 1 1/4 of the time, 2 1/8 of a * time, and N 1/(2^(N - 1)) of the time. This is what we want. * We could test for this in the configure scripts. * * Since many machines return random numbers which aren't that * random, there may be better ways of doing this. In the past I * had (_dmalloc_rand() % 10000 >= 5000) or something but I'd * rather not have the % overhead here. */ if (_dmalloc_rand() & 1) { break; } } return level_c; } /* * static skip_alloc_t *find_address * * DESCRIPTION: * * Look for a specific address in the skip list. If it exist then a * pointer to the matching slot is returned otherwise NULL. Either * way, the links that were traversed to get there are set in the * update slot which has the maximum number of levels. * * RETURNS: * * Success - Pointer to the slot which matches the block-num and size * pair. * * Failure - NULL and this will not set dmalloc_errno * * ARGUMENTS: * * address -> Address we are looking for. * * free_b -> Look on the free list otherwise look on the used list. * * exact_b -> Set to 1 to find the exact pointer. If 0 then the * address could be inside a block. * * update_p -> Pointer to the skip_alloc entry we are using to hold * the update pointers. */ static skip_alloc_t *find_address(const void *address, const int free_b, const int exact_b, skip_alloc_t *update_p) { int level_c; skip_alloc_t *slot_p, *found_p = NULL, *next_p; /* skip_address_max_level */ level_c = MAX_SKIP_LEVEL - 1; if (free_b) { slot_p = skip_free_list; } else { slot_p = skip_address_list; } /* traverse list to smallest entry */ while (1) { /* next on we are looking for */ next_p = slot_p->sa_next_p[level_c]; /* * sort by address */ /* are we are at the end of a row? */ if (next_p == NULL) { /* just go down a level */ } else if (next_p == found_p || (char *)next_p->sa_mem > (char *)address) { /* just go down a level */ } else if ((char *)next_p->sa_mem == (char *)address) { /* found it and go down a level */ found_p = next_p; } /* * (char *)next_p->sa_mem < (char *)address */ else if ((! exact_b) && ((char *)next_p->sa_mem + next_p->sa_total_size > (char *)address)) { /* * if we are doing loose searches and this block contains this * pointer then we have a match */ found_p = next_p; } else { /* next slot is less, go right */ slot_p = next_p; continue; } /* we are lowering the level */ update_p->sa_next_p[level_c] = slot_p; if (level_c == 0) { break; } level_c--; } return found_p; } /* * static skip_alloc_t *find_free_size * * DESCRIPTION: * * Look for a specific size in the free skip list. If it exist then a * pointer to the matching slot is returned otherwise NULL. Either * way, the links that were traversed to get there are set in the * update slot which has the maximum number of levels. * * RETURNS: * * Success - Pointer to the slot which matches the size pair. * * Failure - NULL * * ARGUMENTS: * * address -> Address we are looking for. * * update_p -> Pointer to the skip_alloc entry we are using to hold * the update pointers. */ static skip_alloc_t *find_free_size(const unsigned int size, skip_alloc_t *update_p) { int level_c, cmp; skip_alloc_t *slot_p, *found_p = NULL, *next_p; /* skip_free_max_level */ level_c = MAX_SKIP_LEVEL - 1; slot_p = skip_free_list; /* traverse list to smallest entry */ while (1) { /* next on we are looking for */ next_p = slot_p->sa_next_p[level_c]; /* are we are at the end of a row? */ if (next_p == NULL || next_p == found_p) { /* just go down a level */ } else { cmp = next_p->sa_total_size - size; if (cmp < 0) { /* next slot is less, go right */ slot_p = next_p; continue; } else if (cmp == 0) { /* * we found a match but it may not be the first slot with this * size and we want the first match */ found_p = next_p; } } /* we are lowering the level */ update_p->sa_next_p[level_c] = slot_p; if (level_c == 0) { break; } level_c--; } /* space should be free */ if (found_p != NULL && (! BIT_IS_SET(found_p->sa_flags, ALLOC_FLAG_FREE))) { /* sanity check */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("find_free_size"); return NULL; } return found_p; } /* * static int insert_slot * * DESCRIPTION: * * Insert an address entry into a skip list. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * slot_p <-> Slot that we are inserting into the skip list. * * free_b -> Insert a free address in the free-size list otherwise it * will go into the used address list. */ static int insert_slot(skip_alloc_t *slot_p, const int free_b) { skip_alloc_t *adjust_p, *update_p; int level_c; update_p = skip_update; if (free_b) { (void)find_free_size(slot_p->sa_total_size, update_p); /* * NOTE: we can get a new_p because there might be other blocks of * the same size which we will be inserting before. */ } else if (find_address(slot_p->sa_mem, 0 /* used list */, 1 /* exact */, update_p) != NULL) { /* * Sanity check. We should not have found it since that means * that someone has the same size and block-num. */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("insert_slot"); return 0; } /* update the block skip list */ for (level_c = 0; level_c <= slot_p->sa_level_n; level_c++) { /* * We are inserting our new slot after each of the slots in the * update array. So for each level, we get the slot we are * adjusting, we take it's next pointers and set them in the new * slot, and we point its next pointers to the new slot. */ adjust_p = update_p->sa_next_p[level_c]; slot_p->sa_next_p[level_c] = adjust_p->sa_next_p[level_c]; adjust_p->sa_next_p[level_c] = slot_p; } return 1; } /* * static int alloc_slots * * DESCRIPTION: * * Allocate a block of new slots of a certain size and add them to the * free list. If there are none in the linked list then we will * allocate a block of the size. * * RETURNS: * * Success - Valid pointer to a single block that was allocated for * the slots. * * Failure - NULL * * ARGUMENTS: * * level_n -> Number of the level we are looking for. Set to 0 to * have it be chosen at random. */ static void *alloc_slots(const int level_n) { skip_alloc_t *new_p; entry_block_t *block_p; unsigned int *magic3_p, magic3; int size, new_c; if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_ADMIN)) { dmalloc_message("need a block of slots for level %d", level_n); } /* we need to allocate a new block of the slots of this level */ block_p = _dmalloc_heap_alloc(BLOCK_SIZE); if (block_p == NULL) { /* * Sanity check. Out of heap memory. Error code set in * _dmalloc_heap_alloc(). */ return NULL; } memset(block_p, 0, BLOCK_SIZE); admin_block_c++; /* intialize the block structure */ block_p->eb_magic1 = ENTRY_BLOCK_MAGIC1; block_p->eb_level_n = level_n; block_p->eb_magic2 = ENTRY_BLOCK_MAGIC2; /* add the block on the entry block linked list */ block_p->eb_next_p = entry_blocks[level_n]; entry_blocks[level_n] = block_p; /* put the magic3 at the end of the block */ magic3_p = (unsigned int *)((char *)block_p + BLOCK_SIZE - sizeof(*magic3_p)); magic3 = ENTRY_BLOCK_MAGIC3; memcpy(magic3_p, &magic3, sizeof(*magic3_p)); /* get the size of the slot */ size = SKIP_SLOT_SIZE(level_n); /* add in all of the unused slots to the linked list */ new_c = 1; for (new_p = &block_p->eb_first_slot; (char *)new_p + size < (char *)magic3_p; new_p = (skip_alloc_t *)((char *)new_p + size)) { new_p->sa_level_n = level_n; new_p->sa_next_p[0] = entry_free_list[level_n]; entry_free_list[level_n] = new_p; new_c++; } /* extern pointer information set in _dmalloc_heap_alloc */ return block_p; } /* * static int remove_slot * * DESCRIPTION: * * Remove a slot from the skip list. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * delete_p -> Pointer to the block we are deleting from the list. * * update_p -> Pointer to the skip_alloc entry we are using to hold * the update pointers. */ static int remove_slot(skip_alloc_t *delete_p, skip_alloc_t *update_p) { skip_alloc_t *adjust_p; int level_c; /* update the block skip list */ for (level_c = 0; level_c <= MAX_SKIP_LEVEL; level_c++) { /* * The update node holds pointers to the slots which are pointing * to the one we want since we need to update those pointers * ahead. */ adjust_p = update_p->sa_next_p[level_c]; /* * If the pointer in question is not pointing to the deleted slot * then the deleted slot is shorter than this level and we are * done. This is guaranteed if we have a proper skip list. */ if (adjust_p->sa_next_p[level_c] != delete_p) { break; } /* * We are deleting a slot after each of the slots in the update * array. So for each level, we get the slot we are adjusting, we * set it's next pointers to the next pointers at the same level * from the deleted slot. */ adjust_p->sa_next_p[level_c] = delete_p->sa_next_p[level_c]; } /* * Sanity check here, we should always have at least 1 pointer to * the found node that we are deleting. */ if (level_c == 0) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("remove_slot"); return 0; } return 1; } /* * static skip_alloc_t *get_slot * * DESCRIPTION: * * Get a new slot of a certain size. This calls alloc_slot and then * does a whole bunch of things if alloc_slots generates the need for * two new slots. Jumping through hoops to get this right. * * RETURNS: * * Success - Valid skip-alloc pointer. * * Failure - NULL * * ARGUMENTS: * * None. */ static skip_alloc_t *get_slot(void) { skip_alloc_t *new_p; int level_n, slot_size; void *admin_mem; /* generate the level for our new slot */ level_n = random_level(MAX_SKIP_LEVEL); slot_size = SKIP_SLOT_SIZE(level_n); /* get an extry from the free list */ new_p = entry_free_list[level_n]; if (new_p != NULL) { /* shift the linked list over */ entry_free_list[level_n] = new_p->sa_next_p[0]; /* zero our slot entry */ memset(new_p, 0, slot_size); new_p->sa_level_n = level_n; return new_p; } /* * Okay, this is a little wild. Holding on? * * So we are trying to get a slot of a certain size to store * something in a skip list. We didn't have any on the free-list so * now we will allocate a block. We allocate a block of memory to * hold the slots meaning that we may need 1 new slot to account for * the admin and external memory in addition to the 1 requested. * * To do it right, would take a recursive call to get_slot which I * am not willing to do so we will have 2 blocks in a row which have * the same height. This is less than efficient but oh well. */ /* add in all of the unused slots to the linked list */ admin_mem = alloc_slots(level_n); if (admin_mem == NULL) { /* Sanity check. Error code set in alloc_slots(). */ return NULL; } /* get one for the admin memory */ new_p = entry_free_list[level_n]; if (new_p == NULL) { /* * Sanity check. We should have created a whole bunch of * addresses. */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("get_slot"); return NULL; } entry_free_list[level_n] = new_p->sa_next_p[0]; memset(new_p, 0, slot_size); new_p->sa_flags = ALLOC_FLAG_ADMIN; new_p->sa_mem = admin_mem; new_p->sa_total_size = BLOCK_SIZE; new_p->sa_level_n = level_n; /* now put it in the used list */ if (! insert_slot(new_p, 0 /* used list */)) { /* Sanity check. error code set in insert_slot(). */ return NULL; } /* now get one for the user */ new_p = entry_free_list[level_n]; if (new_p == NULL) { /* * Sanity check. We should have created a whole bunch of * addresses. */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("get_slot"); return NULL; } entry_free_list[level_n] = new_p->sa_next_p[0]; memset(new_p, 0, slot_size); new_p->sa_level_n = level_n; /* level_np set up top */ return new_p; } /* * static skip_alloc_t *insert_address * * DESCRIPTION: * * Insert an address entry into a skip list. * * RETURNS: * * Success - Valid slot pointer. * * Failure - NULL * * ARGUMENTS: * * address -> Address we are inserting into the address list. * * free_b -> Insert a free address in the free-size list otherwise it * will go into the used address list. * * tot_size -> Total size of the chunk that we are inserting into the * list. */ static skip_alloc_t *insert_address(void *address, const int free_b, const unsigned int tot_size) { skip_alloc_t *new_p; /* get a new entry */ new_p = get_slot(); if (new_p == NULL) { /* error code set in get_slot */ return NULL; } if (free_b) { new_p->sa_flags = ALLOC_FLAG_FREE; } else { new_p->sa_flags = ALLOC_FLAG_USER; } new_p->sa_mem = address; new_p->sa_total_size = tot_size; /* now try and insert the slot into the skip-list */ if (! insert_slot(new_p, free_b)) { /* Sanity check. error code set in insert_slot(). */ return NULL; } return new_p; } /******************************* misc routines *******************************/ /* * static int expand_chars * * DESCRIPTION: * * Copies a buffer into a output buffer while translates * non-printables into %03o octal values. If it can, it will also * translate certain \ characters (\r, \n, etc.) into \\%c. The * routine is useful for printing out binary values. * * Note: It does _not_ add a \0 at the end of the output buffer. * * RETURNS: * * Returns the number of characters added to the output buffer. * * ARGUMENTS: * * buf - the buffer to convert. * * buf_size - size of the buffer. If < 0 then it will expand till it * sees a \0 character. * * out - destination buffer for the convertion. * * out_size - size of the output buffer. */ static int expand_chars(const void *buf, const int buf_size, char *out, const int out_size) { const unsigned char *buf_p, *spec_p; char *out_p = out, *bounds_p; /* setup our max pointer */ bounds_p = out + out_size; /* run through the input buffer, counting the characters as we go */ for (buf_p = (const unsigned char *)buf; buf_p < (const unsigned char *)buf + buf_size; buf_p++) { /* search for special characters */ for (spec_p = (unsigned char *)SPECIAL_CHARS + 1; *(spec_p - 1) != '\0'; spec_p += 2) { if (*spec_p == *buf_p) { break; } } /* did we find one? */ if (*(spec_p - 1) != '\0') { if (out_p + 2 >= bounds_p) { break; } out_p += loc_snprintf(out_p, bounds_p - out_p, "\\%c", *(spec_p - 1)); continue; } /* print out any 7-bit printable characters */ if (*buf_p < 128 && isprint(*buf_p)) { if (out_p + 1 >= bounds_p) { break; } *out_p = *(char *)buf_p; out_p += 1; } else { if (out_p + 4 >= bounds_p) { break; } out_p += loc_snprintf(out_p, bounds_p - out_p, "\\%03o", *buf_p); } } /* try to punch the null if we have space in case the %.*s doesn't work */ if (out_p < bounds_p) { *out_p = '\0'; } return out_p - out; } /* * static void get_pnt_info * * DESCRIPTION: * * With a slot, set a number of pointers to places within the block. * * RETURNS: * * None. * * ARGUMENTS: * * slot_p -> Pointer to a slot structure that we are getting info on. * * info_p <-> Pointer to an info structure that we are filling with * information. */ static void get_pnt_info(const skip_alloc_t *slot_p, pnt_info_t *info_p) { info_p->pi_fence_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FENCE); info_p->pi_valloc_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_VALLOC); info_p->pi_blanked_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK); info_p->pi_alloc_start = slot_p->sa_mem; if (info_p->pi_fence_b) { if (info_p->pi_valloc_b) { info_p->pi_user_start = (char *)info_p->pi_alloc_start + BLOCK_SIZE; info_p->pi_fence_bottom = (char *)info_p->pi_user_start - FENCE_BOTTOM_SIZE; } else { info_p->pi_fence_bottom = info_p->pi_alloc_start; info_p->pi_user_start = (char *)info_p->pi_alloc_start + FENCE_BOTTOM_SIZE; } } else { info_p->pi_fence_bottom = NULL; info_p->pi_user_start = info_p->pi_alloc_start; } info_p->pi_user_bounds = (char *)info_p->pi_user_start + slot_p->sa_user_size; info_p->pi_alloc_bounds = (char *)slot_p->sa_mem + slot_p->sa_total_size; if (info_p->pi_fence_b) { info_p->pi_fence_top = info_p->pi_user_bounds; info_p->pi_upper_bounds = (char *)info_p->pi_alloc_bounds - FENCE_TOP_SIZE; } else { info_p->pi_fence_top = NULL; info_p->pi_upper_bounds = info_p->pi_alloc_bounds; } } /* * static char *display_pnt * * DESCRIPTION: * * Write into a buffer a discription of a pointer. * * RETURNS: * * Pointer to buffer 1st argument. * * ARGUMENTS: * * user_pnt -> Pointer that we are displaying. * * alloc_p -> Pointer to the skip slot which we are displaying. * * buf <-> Passed in buffer which will be filled with a description of * the pointer. * * buf_size -> Size of the buffer in bytes. */ static char *display_pnt(const void *user_pnt, const skip_alloc_t *alloc_p, char *buf, const int buf_size) { char *buf_p, *bounds_p; int elapsed_b; buf_p = buf; bounds_p = buf_p + buf_size; buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%#lx", (unsigned long)user_pnt); #if LOG_PNT_SEEN_COUNT buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|s%lu", alloc_p->sa_seen_c); #endif #if LOG_PNT_ITERATION buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|i%lu", alloc_p->sa_iteration); #endif if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_ELAPSED_TIME)) { elapsed_b = 1; } else { elapsed_b = 0; } if (elapsed_b || BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_CURRENT_TIME)) { #if LOG_PNT_TIMEVAL { char time_buf[64]; buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|w%s", _dmalloc_ptimeval(&alloc_p->sa_timeval, time_buf, sizeof(time_buf), elapsed_b)); } #else #if LOG_PNT_TIME { char time_buf[64]; buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|w%s", _dmalloc_ptime(&alloc_p->sa_time, time_buf, sizeof(time_buf), elapsed_b)); } #endif #endif } #if LOG_PNT_THREAD_ID { char thread_id[256]; buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "|t"); THREAD_ID_TO_STRING(thread_id, sizeof(thread_id), alloc_p->sa_thread_id); buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s", thread_id); } #endif return buf; } /* * static void log_error_info * * DESCRIPTION: * * Logging information about a pointer, usually during an error * condition. * * RETURNS: * * None. * * ARGUMENTS: * * now_file -> File from where we generated the error. * * now_line -> Line number from where we generated the error. * * user_pnt -> Pointer in question. This can be 0L then it will use * the slot_p memory pointer. * * slot_p -> Pointer to the slot associated with the user_pnt or 0L. * * reason -> Reason string why something happened. * * where -> What routine is calling log_error_info. For instance * malloc or chunk_check. */ static void log_error_info(const char *now_file, const unsigned int now_line, const void *user_pnt, const skip_alloc_t *slot_p, const char *reason, const char *where) { static int dump_bottom_b = 0, dump_top_b = 0; char out[(DUMP_SPACE + FENCE_BOTTOM_SIZE + FENCE_TOP_SIZE) * 4]; char where_buf[MAX_FILE_LENGTH + 64]; char where_buf2[MAX_FILE_LENGTH + 64]; const char *prev_file; const void *dump_pnt = user_pnt; const void *start_user; unsigned int prev_line, user_size; skip_alloc_t *other_p; pnt_info_t pnt_info; int out_len, dump_size, offset; if (slot_p == NULL) { prev_file = NULL; prev_line = 0; user_size = 0; start_user = user_pnt; } else { prev_file = slot_p->sa_file; prev_line = slot_p->sa_line; user_size = slot_p->sa_user_size; if (user_pnt == NULL) { get_pnt_info(slot_p, &pnt_info); start_user = pnt_info.pi_user_start; } else { start_user = user_pnt; } } /* get a proper reason string */ if (reason != NULL) { dmalloc_message(" error details: %s", reason); } /* dump the pointer information */ if (start_user == NULL) { dmalloc_message(" from '%s' prev access '%s'", _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), now_file, now_line), _dmalloc_chunk_desc_pnt(where_buf2, sizeof(where_buf2), prev_file, prev_line)); } else { dmalloc_message(" pointer '%#lx' from '%s' prev access '%s'", (unsigned long)start_user, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), now_file, now_line), _dmalloc_chunk_desc_pnt(where_buf2, sizeof(where_buf2), prev_file, prev_line)); } /* * If we aren't logging bad space or we didn't error with an * overwrite error then don't log the bad bytes. */ if ((! BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_BAD_SPACE)) || (dmalloc_errno != ERROR_UNDER_FENCE && dmalloc_errno != ERROR_OVER_FENCE && dmalloc_errno != ERROR_FREE_OVERWRITTEN)) { /* we call the error function after writing more info to the logfile */ dmalloc_error(where); return; } /* NOTE: display memory like this has the potential for generating a core */ if (dmalloc_errno == ERROR_UNDER_FENCE) { /* NOTE: only dump out the proper fence-post area once */ if (! dump_bottom_b) { out_len = expand_chars(fence_bottom, FENCE_BOTTOM_SIZE, out, sizeof(out)); dmalloc_message(" dump of proper fence-bottom bytes: '%.*s'", out_len, out); dump_bottom_b = 1; } offset = -FENCE_BOTTOM_SIZE; dump_size = DUMP_SPACE + FENCE_BOTTOM_SIZE; if (dump_size > user_size + FENCE_OVERHEAD_SIZE) { dump_size = user_size + FENCE_OVERHEAD_SIZE; } } else if (dmalloc_errno == ERROR_OVER_FENCE && user_size > 0) { /* NOTE: only dump out the proper fence-post area once */ if (! dump_top_b) { out_len = expand_chars(fence_top, FENCE_TOP_SIZE, out, sizeof(out)); dmalloc_message(" dump of proper fence-top bytes: '%.*s'", out_len, out); dump_top_b = 1; } /* * The size includes the bottom fence post area. We want it to * align with the start of the top fence post area. */ if (DUMP_SPACE > user_size + FENCE_OVERHEAD_SIZE) { dump_size = user_size + FENCE_OVERHEAD_SIZE; offset = -FENCE_BOTTOM_SIZE; } else { dump_size = DUMP_SPACE; /* we will go backwards possibly up to FENCE_BOTTOM_SIZE offset */ offset = user_size + FENCE_TOP_SIZE - DUMP_SPACE; } } else { dump_size = DUMP_SPACE; offset = 0; if (user_size > 0 && dump_size > user_size) { dump_size = user_size; } } dump_pnt = (char *)start_user + offset; if (IS_IN_HEAP(dump_pnt)) { out_len = expand_chars(dump_pnt, dump_size, out, sizeof(out)); dmalloc_message(" dump of '%#lx'%+d: '%.*s'", (unsigned long)start_user, offset, out_len, out); } else { dmalloc_message(" dump of '%#lx'%+d failed: not in heap", (unsigned long)start_user, offset); } /* find the previous pointer in case it ran over */ if (dmalloc_errno == ERROR_UNDER_FENCE && start_user != NULL) { other_p = find_address((char *)start_user - FENCE_BOTTOM_SIZE - 1, 0 /* used list */, 1 /* not exact pointer */, skip_update); if (other_p != NULL) { dmalloc_message(" prev pointer '%#lx' (size %u) may have run over from '%s'", (unsigned long)other_p->sa_mem, other_p->sa_user_size, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), other_p->sa_file, other_p->sa_line)); } } /* find the next pointer in case it ran under */ else if (dmalloc_errno == ERROR_OVER_FENCE && start_user != NULL && slot_p != NULL) { other_p = find_address((char *)slot_p->sa_mem + slot_p->sa_total_size, 0 /* used list */, 1 /* not exact pointer */, skip_update); if (other_p != NULL) { dmalloc_message(" next pointer '%#lx' (size %u) may have run under from '%s'", (unsigned long)other_p->sa_mem, other_p->sa_user_size, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), other_p->sa_file, other_p->sa_line)); } } /* we call the error function after writing more info to the logfile */ dmalloc_error(where); } /* * static int fence_read * * DESCRIPTION * * Check a pointer for fence-post magic numbers. * * RETURNS: * * Success - 1 if the fence posts are good. * * Failure - 0 if they are not. * * ARGUMENTS: * * info_p -> Pointer information that we are checking. */ static int fence_read(const pnt_info_t *info_p) { /* check magic numbers in bottom of allocation block */ if (memcmp(fence_bottom, info_p->pi_fence_bottom, FENCE_BOTTOM_SIZE) != 0) { dmalloc_errno = ERROR_UNDER_FENCE; return 0; } /* check numbers at top of allocation block */ if (memcmp(fence_top, info_p->pi_fence_top, FENCE_TOP_SIZE) != 0) { dmalloc_errno = ERROR_OVER_FENCE; return 0; } return 1; } /* * static void clear_alloc * * DESCRIPTION * * Setup allocations by writing fence post and doing any necessary * clearing of memory. * * RETURNS: * * Success - 1 if the fence posts are good. * * Failure - 0 if they are not. * * ARGUMENTS: * * slot_p <-> Slot we are clearing. * * info_p -> Pointer to information about the allocation. * * old_size -> If there was an old-size that we have copied into the * new pointer then set this. If 0 then it will clear the entire * allocation. * * func_id -> ID of the function which is doing the allocation. Used * to determine if we should 0 memory for [re]calloc. */ static void clear_alloc(skip_alloc_t *slot_p, pnt_info_t *info_p, const unsigned int old_size, const int func_id) { char *start_p; int num; /* * NOTE: The alloc blank flag is set so we blank a slot when it is * allocated. It used to be that the allocated spaces were blanked * and the free spaces of the allocated chunk were blanked only if * the FREE_BLANK flag was enabled. Wrong! */ /* * Set our slot blank flag if the flags are set now. This will * carry over with a realloc. */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_ALLOC_BLANK) || BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_BLANK)) { BIT_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK); } /* * If we have a fence post protected valloc then there is almost a * full block at the front what is "free". Set it with blank chars. */ if (info_p->pi_fence_b) { num = (char *)info_p->pi_fence_bottom - (char *)info_p->pi_alloc_start; /* alloc-blank NOT free-blank */ if (num > 0 && BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK)) { memset(info_p->pi_alloc_start, ALLOC_BLANK_CHAR, num); } } /* * If we are allocating or extending memory, write in our alloc * chars. */ start_p = (char *)info_p->pi_user_start + old_size; num = (char *)info_p->pi_user_bounds - start_p; if (num > 0) { if (func_id == DMALLOC_FUNC_CALLOC || func_id == DMALLOC_FUNC_RECALLOC) { memset(start_p, 0, num); } else if (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK)) { memset(start_p, ALLOC_BLANK_CHAR, num); } } /* write in fence-post info */ if (info_p->pi_fence_b) { memcpy(info_p->pi_fence_bottom, fence_bottom, FENCE_BOTTOM_SIZE); memcpy(info_p->pi_fence_top, fence_top, FENCE_TOP_SIZE); } /* * Now clear the rest of the block above any fence post space with * free characters. * * NOTE alloc-blank NOT free-blank */ if (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK)) { if (info_p->pi_fence_b) { start_p = (char *)info_p->pi_fence_top + FENCE_TOP_SIZE; } else { start_p = info_p->pi_user_bounds; } num = (char *)info_p->pi_alloc_bounds - start_p; if (num > 0) { memset(start_p, ALLOC_BLANK_CHAR, num); } } } /************************** administration functions *************************/ /* * static int create_divided_chunks * * DESCRIPTION: * * Get a divided-block from the free list or heap allocation. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * div_size -> Size of the divided block that we are allocating. */ static int create_divided_chunks(const unsigned int div_size) { void *mem, *bounds_p; /* allocate a 1 block chunk that we will cut up into pieces */ mem = _dmalloc_heap_alloc(BLOCK_SIZE); if (mem == HEAP_ALLOC_ERROR) { /* error code set in _dmalloc_heap_alloc */ return 0; } user_block_c++; /* * now run through the block and add the the locations to the * free-list */ /* end of the block */ bounds_p = (char *)mem + BLOCK_SIZE - div_size; for (; mem <= bounds_p; mem = (char *)mem + div_size) { /* insert the rest of the blocks into the free-list */ if (insert_address(mem, 1 /* free list */, div_size) == NULL) { /* error set in insert_address */ return 0; } free_space_bytes += div_size; } return 1; } /* * static skip_alloc_t *use_free_memory * * DESCRIPTION: * * Find a free memory chunk and remove it from the free list and put * it on the used list if available. * * RETURNS: * * Success - Valid slot pointer * * Failure - NULL * * ARGUMENTS: * * size -> Size of the block that we are looking for. * * update_p -> Pointer to the skip_alloc entry we are using to hold * the update pointers. */ static skip_alloc_t *use_free_memory(const unsigned int size, skip_alloc_t *update_p) { skip_alloc_t *slot_p; #if FREED_POINTER_DELAY /* * check the free wait list to see if any of the waiting pointers * need to be moved off and inserted into the free list */ for (slot_p = free_wait_list_head; slot_p != NULL; ) { skip_alloc_t *next_p; /* we are done if we find a pointer delay in the future */ if (slot_p->sa_use_iter + FREED_POINTER_DELAY > _dmalloc_iter_c) { break; } /* put slot on free list */ next_p = slot_p->sa_next_p[0]; if (! insert_slot(slot_p, 1 /* free list */)) { /* error dumped in insert_slot */ return NULL; } /* adjust our linked list */ slot_p = next_p; free_wait_list_head = slot_p; if (slot_p == NULL) { free_wait_list_tail = NULL; } } #endif /* find a free block which matches the size */ slot_p = find_free_size(size, update_p); if (slot_p == NULL) { return NULL; } /* sanity check */ if (slot_p->sa_total_size != size) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("use_free_memory"); return NULL; } /* remove from free list */ if (! remove_slot(slot_p, update_p)) { /* error reported in remove_slot */ return NULL; } /* set to user allocated space */ slot_p->sa_flags = ALLOC_FLAG_USER; /* insert it into our address list */ if (! insert_slot(slot_p, 0 /* used list */)) { /* error set in insert_slot */ return NULL; } free_space_bytes -= slot_p->sa_total_size; return slot_p; } /* * static skip_alloc_t *get_divided_memory * * DESCRIPTION: * * Get a divided memory block from the free list or heap allocation. * * RETURNS: * * Success - Valid skip slot pointer. * * Failure - NULL * * ARGUMENTS: * * size -> Size of the block that we are allocating. */ static skip_alloc_t *get_divided_memory(const unsigned int size) { skip_alloc_t *slot_p; unsigned int need_size; int *bits_p; for (bits_p = bit_sizes;; bits_p++) { if (*bits_p >= size) { break; } } need_size = *bits_p; /* find a free block which matches the size */ slot_p = use_free_memory(need_size, skip_update); if (slot_p != NULL) { return slot_p; } /* need to get more slots */ if (! create_divided_chunks(need_size)) { /* errors dumped in create_divided_chunks */ return NULL; } /* now we ask again for the free memory */ slot_p = use_free_memory(need_size, skip_update); if (slot_p == NULL) { /* huh? This isn't right. */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("get_divided_memory"); return NULL; } return slot_p; } /* * static skip_alloc_t *get_memory * * DESCRIPTION: * * Get a block from the free list or heap allocation. * * RETURNS: * * Success - Valid skip slot pointer. * * Failure - NULL * * ARGUMENTS: * * size -> Size of the block that we are allocating. */ static skip_alloc_t *get_memory(const unsigned int size) { skip_alloc_t *slot_p, *update_p; void *mem; unsigned int need_size, block_n; /* do we need to print admin info? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_ADMIN)) { dmalloc_message("need %d bytes", size); } /* will this allocate put us over the limit? */ if (_dmalloc_memory_limit > 0 && alloc_cur_given + size > _dmalloc_memory_limit) { dmalloc_errno = ERROR_OVER_LIMIT; dmalloc_error("get_memory"); return NULL; } /* do we have a divided block here? */ if (size <= BLOCK_SIZE / 2) { return get_divided_memory(size); } /* round up to the nearest block size */ need_size = size + BLOCK_SIZE - 1; block_n = need_size / BLOCK_SIZE; need_size = block_n * BLOCK_SIZE; update_p = skip_update; /* find a free block which matches the size */ slot_p = use_free_memory(need_size, update_p); if (slot_p != NULL) { return slot_p; } /* if there are blocks that are larger than this */ slot_p = update_p->sa_next_p[0]; if (slot_p != NULL && slot_p->sa_total_size > size) { /* * now we ask again for the memory because we need to reset the * update pointer list */ slot_p = use_free_memory(need_size, update_p); if (slot_p != NULL) { /* huh? This isn't right. */ dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("get_memory"); return NULL; } } /* allocate the memory necessary for the new blocks */ mem = _dmalloc_heap_alloc(need_size); if (mem == HEAP_ALLOC_ERROR) { /* error code set in _dmalloc_heap_alloc */ return NULL; } user_block_c += block_n; /* create our slot */ slot_p = insert_address(mem, 0 /* used list */, need_size); if (slot_p == NULL) { /* error set in insert_address */ return NULL; } return slot_p; } /* * static int check_used_slot * * Check out the pointer in a allocated slot to make sure it is good. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * slot_p -> Slot that we are checking. * * user_pnt -> User pointer which was used to get the slot or NULL. * * exact_b -> Set to 1 to find the pointer specifically. Otherwise we * can find the pointer inside of an allocation. * * strlen_b -> Make sure that pnt can hold at least a strlen + 1 * bytes. If 0 then ignore. * * min_size -> Make sure that pnt can hold at least that many bytes. * If 0 then ignore. */ static int check_used_slot(const skip_alloc_t *slot_p, const void *user_pnt, const int exact_b, const int strlen_b, const int min_size) { const char *file, *name_p, *bounds_p, *mem_p; unsigned int line, num; pnt_info_t pnt_info; if (! (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_USER) || BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_EXTERN) || BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_ADMIN))) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; } /* get pointer info */ get_pnt_info(slot_p, &pnt_info); /* the user pointer needs to be within the user space */ if (user_pnt != NULL && (char *)user_pnt < (char *)pnt_info.pi_user_start) { dmalloc_errno = ERROR_WOULD_OVERWRITE; return 0; } /* if we need the exact pointer, make sure that the user_pnt agrees */ if (exact_b && user_pnt != pnt_info.pi_user_start) { dmalloc_errno = ERROR_NOT_START_BLOCK; return 0; } #if LARGEST_ALLOCATION /* have we exceeded the upper bounds */ if (slot_p->sa_user_size > LARGEST_ALLOCATION) { dmalloc_errno = ERROR_BAD_SIZE; return 0; } #endif /* check our total block size */ if (slot_p->sa_total_size > BLOCK_SIZE / 2 && slot_p->sa_total_size % BLOCK_SIZE != 0) { dmalloc_errno = ERROR_BAD_SIZE; return 0; } /* * If we have a valloc allocation then the _user_ pnt should be * block aligned otherwise the chunk_pnt should be. */ if (pnt_info.pi_valloc_b) { if ((long)pnt_info.pi_user_start % BLOCK_SIZE != 0) { dmalloc_errno = ERROR_NOT_ON_BLOCK; return 0; } if (slot_p->sa_total_size < BLOCK_SIZE) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; } /* now check the below space to make sure it is still clear */ if (pnt_info.pi_fence_b && pnt_info.pi_blanked_b) { num = (char *)pnt_info.pi_fence_bottom - (char *)pnt_info.pi_alloc_start; if (num > 0) { for (mem_p = pnt_info.pi_alloc_start; mem_p < (char *)pnt_info.pi_fence_bottom; mem_p++) { if (*mem_p != ALLOC_BLANK_CHAR) { dmalloc_errno = ERROR_FREE_OVERWRITTEN; return 0; } } } } } /* check out the fence-posts */ if (pnt_info.pi_fence_b && (! fence_read(&pnt_info))) { /* errno set in fence_read */ return 0; } /* check above the allocation to see if it's been overwritten */ if (pnt_info.pi_blanked_b) { if (pnt_info.pi_fence_b) { mem_p = (char *)pnt_info.pi_fence_top + FENCE_TOP_SIZE; } else { mem_p = pnt_info.pi_user_bounds; } for (; mem_p < (char *)pnt_info.pi_alloc_bounds; mem_p++) { if (*mem_p != ALLOC_BLANK_CHAR) { dmalloc_errno = ERROR_FREE_OVERWRITTEN; return 0; } } } file = slot_p->sa_file; line = slot_p->sa_line; /* check line number */ #if MAX_LINE_NUMBER if (line > MAX_LINE_NUMBER) { dmalloc_errno = ERROR_BAD_LINE; return 0; } #endif /* * Check file pointer only if file is not NULL and line is not 0 * which implies that file is a return-addr. */ #if MAX_FILE_LENGTH if (file != DMALLOC_DEFAULT_FILE && line != DMALLOC_DEFAULT_LINE) { /* NOTE: we don't use strlen here because we might check too far */ bounds_p = file + MAX_FILE_LENGTH; for (name_p = file; name_p <= bounds_p && *name_p != '\0'; name_p++) { } if (name_p > bounds_p || name_p < file + MIN_FILE_LENGTH) { dmalloc_errno = ERROR_BAD_FILE; return 0; } } #endif #if LOG_PNT_SEEN_COUNT /* * We divide by 2 here because realloc which returns the same * pointer will seen_c += 2. However, it will never be more than * twice the iteration value. We divide by two to not overflow * iter_c * 2. */ if (slot_p->sa_seen_c / 2 > _dmalloc_iter_c) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; } #endif if (strlen_b) { int equals_okay_b = 0; mem_p = (char *)user_pnt; if (min_size > 0) { bounds_p = mem_p + min_size; /* min_size can be out of bounds as long as we find a \0 beforehand */ if (bounds_p > (char *)pnt_info.pi_user_bounds) { bounds_p = (char *)pnt_info.pi_user_bounds; } else { /* we can equals our boundary if our min_size <= user_bounds */ equals_okay_b = 1; } } else { bounds_p = (char *)pnt_info.pi_user_bounds; } for (; mem_p < bounds_p; mem_p++) { if (*mem_p == '\0') { break; } } /* mem_p can == bounds_p if we hit the min_size but can't >= user_bounds*/ if (mem_p > (char *)pnt_info.pi_user_bounds || ((! equals_okay_b) && mem_p == (char *)pnt_info.pi_user_bounds)) { dmalloc_errno = ERROR_WOULD_OVERWRITE; return 0; } } else if (min_size > 0) { if ((char *)user_pnt + min_size > (char *)pnt_info.pi_user_bounds) { dmalloc_errno = ERROR_WOULD_OVERWRITE; return 0; } } return 1; } /* * static int check_free_slot * * Check out the pointer in a slot to make sure it is good. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * slot_p -> Slot that we are checking. */ static int check_free_slot(const skip_alloc_t *slot_p) { char *check_p; if (! BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FREE)) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; } if (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK)) { for (check_p = (char *)slot_p->sa_mem; check_p < (char *)slot_p->sa_mem + slot_p->sa_total_size; check_p++) { if (*check_p != FREE_BLANK_CHAR) { dmalloc_errno = ERROR_FREE_OVERWRITTEN; return 0; } } } #if LOG_PNT_SEEN_COUNT /* * We divide by 2 here because realloc which returns the same * pointer will seen_c += 2. However, it will never be more than * twice the iteration value. We divide by two to not overflow * iter_c * 2. */ if (slot_p->sa_seen_c / 2 > _dmalloc_iter_c) { dmalloc_errno = ERROR_SLOT_CORRUPT; return 0; } #endif return 1; } /***************************** exported routines *****************************/ /* * int _dmalloc_chunk_startup * * DESCRIPTION: * * Startup the low level malloc routines. * * RETURNS: * * Success - 1 * * Failure - 0 * * ARGUMENTS: * * None. */ int _dmalloc_chunk_startup(void) { unsigned int value; char *pos_p, *max_p; int bit_c, *bits_p; value = FENCE_MAGIC_BOTTOM; max_p = fence_bottom + FENCE_BOTTOM_SIZE; for (pos_p = fence_bottom; pos_p < max_p; pos_p += sizeof(value)) { if (pos_p + sizeof(value) <= max_p) { memcpy(pos_p, (char *)&value, sizeof(value)); } else { memcpy(pos_p, (char *)&value, max_p - pos_p); } } value = FENCE_MAGIC_TOP; max_p = fence_top + FENCE_TOP_SIZE; for (pos_p = fence_top; pos_p < max_p; pos_p += sizeof(value)) { if (pos_p + sizeof(value) <= max_p) { memcpy(pos_p, (char *)&value, sizeof(value)); } else { memcpy(pos_p, (char *)&value, max_p - pos_p); } } /* initialize the bits array */ bits_p = bit_sizes; for (bit_c = 0; bit_c < BASIC_BLOCK; bit_c++) { if ((1 << bit_c) >= CHUNK_SMALLEST_BLOCK) { *bits_p++ = 1 << bit_c; } } /* set the admin flags on the two statically allocated slots */ skip_free_list->sa_flags = ALLOC_FLAG_ADMIN; skip_address_list->sa_flags = ALLOC_FLAG_ADMIN; return 1; } /* * char *_dmalloc_chunk_desc_pnt * * DESCRIPTION: * * Write into a buffer a pointer description with file and * line-number. * * RETURNS: * * Pointer to buffer 1st argument. * * ARGUMENTS: * * buf <-> Passed in buffer which will be filled with a description of * the pointer. * * buf_size -> Size of the buffer in bytes. * * file -> File name, return address, or NULL. * * line -> Line number or 0. */ char *_dmalloc_chunk_desc_pnt(char *buf, const int buf_size, const char *file, const unsigned int line) { if (file == DMALLOC_DEFAULT_FILE && line == DMALLOC_DEFAULT_LINE) { (void)loc_snprintf(buf, buf_size, "unknown"); } else if (line == DMALLOC_DEFAULT_LINE) { (void)loc_snprintf(buf, buf_size, "ra=%#lx", (unsigned long)file); } else if (file == DMALLOC_DEFAULT_FILE) { (void)loc_snprintf(buf, buf_size, "ra=ERROR(line=%u)", line); } else { (void)loc_snprintf(buf, buf_size, "%.*s:%u", MAX_FILE_LENGTH, file, line); } return buf; } /* * int _dmalloc_chunk_read_info * * DESCRIPTION: * * Return some information associated with a pointer. * * RETURNS: * * Success - 1 pointer is okay * * Failure - 0 problem with pointer * * ARGUMENTS: * * user_pnt -> Pointer we are checking. * * where <- Where the check is being made from. * * user_size_p <- Pointer to an unsigned int which, if not NULL, will * be set to the size of bytes that the user requested. * * alloc_size_p <- Pointer to an unsigned int which, if not NULL, will * be set to the total given size of bytes including block overhead. * * file_p <- Pointer to a character pointer which, if not NULL, will * be set to the file where the pointer was allocated. * * line_p <- Pointer to a character pointer which, if not NULL, will * be set to the line-number where the pointer was allocated. * * ret_attr_p <- Pointer to a void pointer, if not NULL, will be set * to the return-address where the pointer was allocated. * * seen_cp <- Pointer to an unsigned long which, if not NULL, will be * set to the number of times the pointer has been "seen". * * used_p <- Pointer to an unsigned long which, if not NULL, will be * set to the last time the pointer was "used". * * valloc_bp <- Pointer to an integer which, if not NULL, will be set * to 1 if the pointer was allocated with valloc otherwise 0. * * fence_bp <- Pointer to an integer which, if not NULL, will be set * to 1 if the pointer has the fence bit set otherwise 0. */ int _dmalloc_chunk_read_info(const void *user_pnt, const char *where, unsigned int *user_size_p, unsigned int *alloc_size_p, char **file_p, unsigned int *line_p, void **ret_attr_p, unsigned long **seen_cp, unsigned long *used_p, int *valloc_bp, int *fence_bp) { skip_alloc_t *slot_p; if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("reading info about pointer '%#lx'", (unsigned long)user_pnt); } /* find the pointer with loose checking for fence */ slot_p = find_address(user_pnt, 0 /* used list */, 0 /* not exact pointer */, skip_update); if (slot_p == NULL) { dmalloc_errno = ERROR_NOT_FOUND; log_error_info(NULL, 0, user_pnt, NULL, "finding address in heap", where); return 0; } /* might as well check the pointer now */ if (! check_used_slot(slot_p, user_pnt, 1 /* exact */, 0 /* no strlen */, 0 /* no min-size */)) { /* errno set in check_slot */ log_error_info(NULL, 0, user_pnt, slot_p, "checking pointer admin", where); return 0; } /* write info back to user space */ SET_POINTER(user_size_p, slot_p->sa_user_size); SET_POINTER(alloc_size_p, slot_p->sa_total_size); if (slot_p->sa_file == DMALLOC_DEFAULT_FILE) { SET_POINTER(file_p, NULL); } else { SET_POINTER(file_p, (char *)slot_p->sa_file); } SET_POINTER(line_p, slot_p->sa_line); /* if the line is blank then the file will be 0 or the return address */ if (slot_p->sa_line == DMALLOC_DEFAULT_LINE) { SET_POINTER(ret_attr_p, (char *)slot_p->sa_file); } else { SET_POINTER(ret_attr_p, NULL); } #if LOG_PNT_SEEN_COUNT SET_POINTER(seen_cp, &slot_p->sa_seen_c); #else SET_POINTER(seen_cp, NULL); #endif SET_POINTER(used_p, slot_p->sa_use_iter); SET_POINTER(valloc_bp, BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_VALLOC)); SET_POINTER(fence_bp, BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FENCE)); return 1; } /******************************* heap checking *******************************/ /* * int _dmalloc_chunk_heap_check * * DESCRIPTION: * * Run extensive tests on the entire heap. * * RETURNS: * * Success - 1 if the heap is okay * * Failure - 0 if a problem was detected * * ARGUMENTS: * * None. */ int _dmalloc_chunk_heap_check(void) { skip_alloc_t *slot_p; entry_block_t *block_p; int ret, level_c, checking_list_c = 0; int final = 1; if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("checking heap"); } heap_check_c++; /* * first, run through all of the admin structures and check for * validity */ for (level_c = 0; level_c < MAX_SKIP_LEVEL; level_c++) { unsigned int *magic3_p, magic3; /* run through the blocks and test them */ for (block_p = entry_blocks[level_c]; block_p != NULL; block_p = block_p->eb_next_p) { /* better be in the heap */ if (! IS_IN_HEAP(block_p)) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* get the magic3 at the end of the block */ magic3_p = (unsigned int *)((char *)block_p + BLOCK_SIZE - sizeof(*magic3_p)); memcpy(&magic3, magic3_p, sizeof(magic3)); /* check magics */ if (block_p->eb_magic1 != ENTRY_BLOCK_MAGIC1 || block_p->eb_magic2 != ENTRY_BLOCK_MAGIC2 || magic3 != ENTRY_BLOCK_MAGIC3) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* check for a valid level */ if (block_p->eb_level_n != level_c) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* now we look up the block and make sure it exists and is valid */ slot_p = find_address(block_p, 0 /* used list */, 1 /* exact */, skip_update); if (slot_p == NULL) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } if ((! BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_ADMIN)) || slot_p->sa_mem != block_p || slot_p->sa_total_size != BLOCK_SIZE || slot_p->sa_level_n != level_c) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* * NOTE: we could now check each of the entries in the block to * make sure that they are valid and on the used or free list */ } } /* * Now run through the used pointers and check each one. */ for (slot_p = skip_address_list->sa_next_p[0]; ; slot_p = slot_p->sa_next_p[0]) { skip_alloc_t *block_slot_p; /* * switch to the free list in the middle after we've checked the * used pointer slots */ if (slot_p == NULL) { checking_list_c++; if (checking_list_c == 1) { slot_p = skip_free_list->sa_next_p[0]; } #if FREED_POINTER_DELAY else if (checking_list_c == 2) { slot_p = free_wait_list_head; } #endif else { /* we are done */ break; } if (slot_p == NULL) { break; } } /* better be in the heap */ if (! IS_IN_HEAP(slot_p)) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* * now we look up the slot pointer itself and make sure it exists * in a valid block */ block_slot_p = find_address(slot_p, 0 /* used list */, 0 /* not exact pointer */, skip_update); if (block_slot_p == NULL) { dmalloc_errno = ERROR_ADMIN_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* point at the block */ block_p = block_slot_p->sa_mem; /* check block magic */ if (block_p->eb_magic1 != ENTRY_BLOCK_MAGIC1) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* make sure the slot level matches */ if (slot_p->sa_level_n != block_p->eb_level_n) { dmalloc_errno = ERROR_ADDRESS_LIST; dmalloc_error("_dmalloc_chunk_heap_check"); return 0; } /* now check the allocation */ if (checking_list_c == 0) { ret = check_used_slot(slot_p, NULL /* no user pnt */, 0 /* loose pnt checking */, 0 /* no strlen */, 0 /* no min-size */); if (! ret) { /* error set in check_slot */ log_error_info(NULL, 0, NULL, slot_p, "checking user pointer", "_dmalloc_chunk_heap_check"); /* not a critical error */ final = 0; } } else { ret = check_free_slot(slot_p); if (! ret) { /* error set in check_slot */ log_error_info(NULL, 0, NULL, slot_p, "checking free pointer", "_dmalloc_chunk_heap_check"); /* not a critical error */ final = 0; } } } return final; } /* * int _dmalloc_chunk_pnt_check * * DESCRIPTION: * * Run extensive tests on a pointer. * * RETURNS: * * Success - 1 if the pointer is okay * * Failure - 0 if not * * ARGUMENTS: * * func -> Function string which is checking the pointer. * * user_pnt -> Pointer we are checking. * * exact_b -> Set to 1 to find the pointer specifically. Otherwise we * can find the pointer inside of an allocation. * * strlen_b -> Make sure that pnt can hold at least a strlen + 1 * bytes. If 0 then ignore. * * min_size -> Make sure that pnt can hold at least that many bytes. * If 0 then ignore. */ int _dmalloc_chunk_pnt_check(const char *func, const void *user_pnt, const int exact_b, const int strlen_b, const int min_size) { skip_alloc_t *slot_p; if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { if (func == NULL) { dmalloc_message("checking pointer '%#lx'", (unsigned long)user_pnt); } else { dmalloc_message("checking func '%s' pointer '%#lx'", func, (unsigned long)user_pnt); } } /* try to find the address */ slot_p = find_address(user_pnt, 0 /* used list */, 0 /* not exact pointer */, skip_update); if (slot_p == NULL) { if (exact_b) { dmalloc_errno = ERROR_NOT_FOUND; log_error_info(NULL, 0, user_pnt, NULL, "pointer-check", func); return 0; } else { return 1; } } /* now make sure that the user slot is valid */ if (! check_used_slot(slot_p, user_pnt, exact_b, strlen_b, min_size)) { /* dmalloc_error set in check_used_slot */ log_error_info(NULL, 0, user_pnt, slot_p, "pointer-check", func); return 0; } return 1; } /************************** low-level user functions *************************/ /* * void *_dmalloc_chunk_malloc * * DESCRIPTION: * * Allocate a chunk of memory. * * RETURNS: * * Success - Valid pointer. * * Failure - NULL * * ARGUMENTS: * * file -> File-name or return-address location of the allocation. * * line -> Line-number location of the allocation. * * size -> Number of bytes to allocate. * * func_id -> Calling function-id as defined in dmalloc.h. * * alignment -> If greater than 0 then try to align the returned * block. */ void *_dmalloc_chunk_malloc(const char *file, const unsigned int line, const unsigned long size, const int func_id, const unsigned int alignment) { unsigned long needed_size; int valloc_b = 0, memalign_b = 0, fence_b = 0; char where_buf[MAX_FILE_LENGTH + 64], disp_buf[64]; skip_alloc_t *slot_p; pnt_info_t pnt_info; const char *trans_log; /* counts calls to malloc */ if (func_id == DMALLOC_FUNC_CALLOC) { func_calloc_c++; } else if (alignment == BLOCK_SIZE) { func_valloc_c++; valloc_b = 1; } else if (alignment > 0) { func_memalign_c++; memalign_b = 1; } else if (func_id == DMALLOC_FUNC_NEW) { func_new_c++; } else if (func_id != DMALLOC_FUNC_REALLOC && func_id != DMALLOC_FUNC_RECALLOC) { func_malloc_c++; } #if ALLOW_ALLOC_ZERO_SIZE == 0 if (size == 0) { dmalloc_errno = ERROR_BAD_SIZE; log_error_info(file, line, NULL, NULL, "bad zero byte allocation request", "malloc"); return MALLOC_ERROR; } #endif #if LARGEST_ALLOCATION /* have we exceeded the upper bounds */ if (size > LARGEST_ALLOCATION) { dmalloc_errno = ERROR_TOO_BIG; log_error_info(file, line, NULL, NULL, "allocation too big", "malloc"); return MALLOC_ERROR; } #endif needed_size = size; /* adjust the size */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FENCE)) { needed_size += FENCE_OVERHEAD_SIZE; fence_b = 1; /* * If the user is requesting a page-aligned block of data then we * will need another block below the allocation just for the fence * information. Ugh. */ if (valloc_b) { needed_size += BLOCK_SIZE; } } else if (valloc_b && needed_size <= BLOCK_SIZE / 2) { /* * If we are valloc-ing, make sure that we get a blocksized chunk * because they are always block aligned. We know here that fence * posting is not on otherwise it would have been set above. */ needed_size = BLOCK_SIZE; } /* get some space for our memory */ slot_p = get_memory(needed_size); if (slot_p == NULL) { /* errno set in get_slot */ return MALLOC_ERROR; } if (fence_b) { BIT_SET(slot_p->sa_flags, ALLOC_FLAG_FENCE); } if (valloc_b) { BIT_SET(slot_p->sa_flags, ALLOC_FLAG_VALLOC); } slot_p->sa_user_size = size; /* initialize the bblocks */ alloc_cur_given += slot_p->sa_total_size; alloc_max_given = MAX(alloc_max_given, alloc_cur_given); get_pnt_info(slot_p, &pnt_info); /* clear the allocation */ clear_alloc(slot_p, &pnt_info, 0 /* no old-size */, func_id); slot_p->sa_file = file; slot_p->sa_line = line; slot_p->sa_use_iter = _dmalloc_iter_c; #if LOG_PNT_SEEN_COUNT slot_p->sa_seen_c++; #endif #if LOG_PNT_ITERATION slot_p->sa_iteration = _dmalloc_iter_c; #endif if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_ELAPSED_TIME) || BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_CURRENT_TIME)) { #if LOG_PNT_TIMEVAL GET_TIMEVAL(slot_p->sa_timeval); #else #if LOG_PNT_TIME slot_p->sa_time = time(NULL); #endif #endif } #if LOG_PNT_THREAD_ID slot_p->sa_thread_id = THREAD_GET_ID(); #endif /* do we need to print transaction info? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { switch (func_id) { case DMALLOC_FUNC_CALLOC: trans_log = "calloc"; break; case DMALLOC_FUNC_MEMALIGN: trans_log = "memalign"; break; case DMALLOC_FUNC_VALLOC: trans_log = "valloc"; break; default: trans_log = "alloc"; break; } dmalloc_message("*** %s: at '%s' for %ld bytes, got '%s'", trans_log, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), file, line), size, display_pnt(pnt_info.pi_user_start, slot_p, disp_buf, sizeof(disp_buf))); } #if MEMORY_TABLE_TOP_LOG _dmalloc_table_insert(mem_table_alloc, MEM_ALLOC_ENTRIES, file, line, size, &mem_table_alloc_c); #endif /* monitor current allocation level */ alloc_current += size; alloc_maximum = MAX(alloc_maximum, alloc_current); _dmalloc_alloc_total += size; alloc_one_max = MAX(alloc_one_max, size); /* monitor pointer usage */ alloc_cur_pnts++; alloc_max_pnts = MAX(alloc_max_pnts, alloc_cur_pnts); alloc_tot_pnts++; return pnt_info.pi_user_start; } /* * int _dmalloc_chunk_free * * DESCRIPTION: * * Free a user pointer from the heap. * * RETURNS: * * Success - FREE_NOERROR * * Failure - FREE_ERROR * * ARGUMENTS: * * file -> File-name or return-address location of the allocation. * * line -> Line-number location of the allocation. * * user_pnt -> Pointer we are freeing. * * func_id -> Function ID */ int _dmalloc_chunk_free(const char *file, const unsigned int line, void *user_pnt, const int func_id) { char where_buf[MAX_FILE_LENGTH + 64]; char where_buf2[MAX_FILE_LENGTH + 64], disp_buf[64]; skip_alloc_t *slot_p, *update_p; /* counts calls to free */ if (func_id == DMALLOC_FUNC_DELETE) { func_delete_c++; } else if (func_id == DMALLOC_FUNC_REALLOC || func_id == DMALLOC_FUNC_RECALLOC) { /* ignore these because they will alredy be accounted for in realloc */ } else { func_free_c++; } if (user_pnt == NULL) { #if ALLOW_FREE_NULL_MESSAGE /* does the user want a specific message? */ dmalloc_message("WARNING: tried to free(0) from '%s'", _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), file, line)); #endif /* * NOTE: we have here both a default in the settings.h file and a * runtime token in case people want to turn it on or off at * runtime. */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_ERROR_FREE_NULL)) { dmalloc_errno = ERROR_IS_NULL; log_error_info(file, line, user_pnt, NULL, "invalid 0L pointer", "free"); return FREE_ERROR; } #if ALLOW_FREE_NULL == 0 dmalloc_errno = ERROR_IS_NULL; #endif return FREE_ERROR; } update_p = skip_update; /* try to find the address with loose match */ slot_p = find_address(user_pnt, 0 /* used list */, 0 /* not exact pointer */, skip_update); if (slot_p == NULL) { #if FREED_POINTER_DELAY skip_alloc_t *del_p; /* search the delay list */ for (del_p = free_wait_list_head; del_p != NULL; del_p = del_p->sa_next_p[0]) { if (del_p->sa_mem <= user_pnt && (char *)del_p->sa_mem + del_p->sa_total_size > (char *)user_pnt) { pnt_info_t info; get_pnt_info(del_p, &info); if (info.pi_user_start == user_pnt) { dmalloc_errno = ERROR_ALREADY_FREE; } else { dmalloc_errno = ERROR_NOT_FOUND; } break; } } if (del_p == NULL) { #endif /* not in the used list so check the free list */ if (find_address(user_pnt, 1 /* free list */, 0 /* not exact pointer */, skip_update) == NULL) { dmalloc_errno = ERROR_NOT_FOUND; } else { dmalloc_errno = ERROR_ALREADY_FREE; } #if FREED_POINTER_DELAY } #endif log_error_info(file, line, user_pnt, NULL, "finding address in heap", "free"); return FREE_ERROR; } if (! check_used_slot(slot_p, user_pnt, 1 /* exact pnt */, 0 /* no strlen */, 0 /* no min-size */)) { /* error set in check slot */ log_error_info(file, line, user_pnt, slot_p, "checking pointer admin", "free"); return FREE_ERROR; } if (! remove_slot(slot_p, update_p)) { /* error set and dumped in remove_slot */ return FREE_ERROR; } if (BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FENCE)) { /* * We need to preserve the fence-post flag because we may need to * properly check for previously freed pointers in the future. */ slot_p->sa_flags = ALLOC_FLAG_FREE | ALLOC_FLAG_FENCE; } else { slot_p->sa_flags = ALLOC_FLAG_FREE; } alloc_cur_pnts--; slot_p->sa_use_iter = _dmalloc_iter_c; #if LOG_PNT_SEEN_COUNT slot_p->sa_seen_c++; #endif /* do we need to print transaction info? */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { dmalloc_message("*** free: at '%s' pnt '%s': size %u, alloced at '%s'", _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), file, line), display_pnt(user_pnt, slot_p, disp_buf, sizeof(disp_buf)), slot_p->sa_user_size, _dmalloc_chunk_desc_pnt(where_buf2, sizeof(where_buf2), slot_p->sa_file, slot_p->sa_line)); } #if MEMORY_TABLE_TOP_LOG _dmalloc_table_delete(mem_table_alloc, MEM_ALLOC_ENTRIES, slot_p->sa_file, slot_p->sa_line, slot_p->sa_user_size); #endif /* update the file/line -- must be after _dmalloc_table_delete */ slot_p->sa_file = file; slot_p->sa_line = line; /* monitor current allocation level */ alloc_current -= slot_p->sa_user_size; alloc_cur_given -= slot_p->sa_total_size; free_space_bytes += slot_p->sa_total_size; /* clear the memory */ if (BIT_IS_SET(_dmalloc_flags, DEBUG_FREE_BLANK) || BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_BLANK)) { memset(slot_p->sa_mem, FREE_BLANK_CHAR, slot_p->sa_total_size); /* set our slot blank flag */ BIT_SET(slot_p->sa_flags, ALLOC_FLAG_BLANK); } /* * The question is should we combine multiple free chunks together * into one. This would help we with fragmentation but it would * screwup the seen counter. * * Check above and below the free bblock looking for neighbors that * are free so we can add them together and put them in a different * free slot. * * NOTE: all of these block's reuse-iter count will be moved ahead * because we are encorporating in this newly freed block. */ if (! BIT_IS_SET(_dmalloc_flags, DEBUG_NEVER_REUSE)) { #if FREED_POINTER_DELAY slot_p->sa_next_p[0] = NULL; if (free_wait_list_head == NULL) { free_wait_list_head = slot_p; } else { free_wait_list_tail->sa_next_p[0] = slot_p; } free_wait_list_tail = slot_p; #else /* put slot on free list */ if (! insert_slot(slot_p, 1 /* free list */)) { /* error dumped in insert_slot */ return FREE_ERROR; } #endif } return FREE_NOERROR; } /* * void *_dmalloc_chunk_realloc * * DESCRIPTION: * * Re-allocate a chunk of memory either shrinking or expanding it. * * RETURNS: * * Success - Valid pointer. * * Failure - NULL * * ARGUMENTS: * * file -> File-name or return-address location of the allocation. * * line -> Line-number location of the allocation. * * old_user_pnt -> Old user pointer that we are reallocating. * * new_size -> New-size to change the pointer. * * func_id -> Calling function-id as defined in dmalloc.h. */ void *_dmalloc_chunk_realloc(const char *file, const unsigned int line, void *old_user_pnt, const unsigned long new_size, const int func_id) { const char *old_file; skip_alloc_t *slot_p; pnt_info_t pnt_info; void *new_user_pnt; unsigned int old_size, old_line; /* counts calls to realloc */ if (func_id == DMALLOC_FUNC_RECALLOC) { func_recalloc_c++; } else { func_realloc_c++; } #if ALLOW_ALLOC_ZERO_SIZE == 0 if (new_size == 0) { dmalloc_errno = ERROR_BAD_SIZE; log_error_info(file, line, NULL, NULL, "bad zero byte allocation request", "realloc"); return REALLOC_ERROR; } #endif /* by now malloc.c should have taken care of the realloc(NULL) case */ if (old_user_pnt == NULL) { dmalloc_errno = ERROR_IS_NULL; log_error_info(file, line, old_user_pnt, NULL, "invalid pointer", "realloc"); return REALLOC_ERROR; } /* find the old pointer with loose checking for fence post stuff */ slot_p = find_address(old_user_pnt, 0 /* used list */, 0 /* not exact pointer */, skip_update); if (slot_p == NULL) { dmalloc_errno = ERROR_NOT_FOUND; log_error_info(file, line, old_user_pnt, NULL, "finding address in heap", "realloc"); return 0; } /* get info about the pointer */ get_pnt_info(slot_p, &pnt_info); old_file = slot_p->sa_file; old_line = slot_p->sa_line; old_size = slot_p->sa_user_size; /* if we are not realloc copying and the size is the same */ if ((char *)pnt_info.pi_user_start + new_size > (char *)pnt_info.pi_upper_bounds || BIT_IS_SET(_dmalloc_flags, DEBUG_REALLOC_COPY) || BIT_IS_SET(_dmalloc_flags, DEBUG_NEVER_REUSE)) { int min_size; /* allocate space for new chunk */ new_user_pnt = _dmalloc_chunk_malloc(file, line, new_size, func_id, 0 /* no align */); if (new_user_pnt == MALLOC_ERROR) { return REALLOC_ERROR; } /* * NOTE: _chunk_malloc() already took care of the fence stuff and * zeroing of memory. */ /* copy stuff into new section of memory */ min_size = MIN(new_size, old_size); if (min_size > 0) { memcpy(new_user_pnt, pnt_info.pi_user_start, min_size); } /* free old pointer */ if (_dmalloc_chunk_free(file, line, old_user_pnt, func_id) != FREE_NOERROR) { return REALLOC_ERROR; } } else { /* new pointer is the same as the old one */ new_user_pnt = pnt_info.pi_user_start; /* * monitor current allocation level * * NOTE: we do this here since the malloc/free used above take care * on if in that section */ alloc_current += new_size - old_size; alloc_maximum = MAX(alloc_maximum, alloc_current); _dmalloc_alloc_total += new_size; alloc_one_max = MAX(alloc_one_max, new_size); /* monitor pointer usage */ alloc_tot_pnts++; /* change the slot information */ slot_p->sa_user_size = new_size; get_pnt_info(slot_p, &pnt_info); clear_alloc(slot_p, &pnt_info, old_size, func_id); slot_p->sa_use_iter = _dmalloc_iter_c; #if LOG_PNT_SEEN_COUNT /* we see in inbound and outbound so we need to increment by 2 */ slot_p->sa_seen_c += 2; #endif #if MEMORY_TABLE_TOP_LOG _dmalloc_table_delete(mem_table_alloc, MEM_ALLOC_ENTRIES, slot_p->sa_file, slot_p->sa_line, old_size); _dmalloc_table_insert(mem_table_alloc, MEM_ALLOC_ENTRIES, file, line, new_size, &mem_table_alloc_c); #endif /* * finally, we update the file/line info -- must be after * _dmalloc_table functions */ slot_p->sa_file = file; slot_p->sa_line = line; } if (BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_TRANS)) { const char *trans_log; char where_buf[MAX_FILE_LENGTH + 64]; char where_buf2[MAX_FILE_LENGTH + 64]; if (func_id == DMALLOC_FUNC_RECALLOC) { trans_log = "recalloc"; } else { trans_log = "realloc"; } dmalloc_message("*** %s: at '%s' from '%#lx' (%u bytes) file '%s' to '%#lx' (%lu bytes)", trans_log, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), file, line), (unsigned long)old_user_pnt, old_size, _dmalloc_chunk_desc_pnt(where_buf2, sizeof(where_buf2), old_file, old_line), (unsigned long)new_user_pnt, new_size); } return new_user_pnt; } /***************************** diagnostic routines ***************************/ /* * void _dmalloc_chunk_log_stats * * DESCRIPTION: * * Log general statistics from the heap to the logfile. * * RETURNS: * * None. * * ARGUMENTS: * * None. */ void _dmalloc_chunk_log_stats(void) { unsigned long overhead, user_space, tot_space; dmalloc_message("Dumping Chunk Statistics:"); tot_space = (user_block_c + admin_block_c) * BLOCK_SIZE; user_space = alloc_current + free_space_bytes; overhead = admin_block_c * BLOCK_SIZE; /* version information */ dmalloc_message("basic-block %d bytes, alignment %d bytes", BLOCK_SIZE, ALLOCATION_ALIGNMENT); /* general heap information with blocks */ dmalloc_message("heap address range: %#lx to %#lx, %ld bytes", (unsigned long)_dmalloc_heap_low, (unsigned long)_dmalloc_heap_high, (unsigned long)_dmalloc_heap_high - (unsigned long)_dmalloc_heap_low); dmalloc_message(" user blocks: %ld blocks, %ld bytes (%ld%%)", user_block_c, user_space, (tot_space < 100 ? 0 : user_space / (tot_space / 100))); dmalloc_message(" admin blocks: %ld blocks, %ld bytes (%ld%%)", admin_block_c, overhead, (tot_space < 100 ? 0 : overhead / (tot_space / 100))); dmalloc_message(" total blocks: %ld blocks, %ld bytes", user_block_c + admin_block_c, tot_space); dmalloc_message("heap checked %ld", heap_check_c); /* log user allocation information */ dmalloc_message("alloc calls: malloc %lu, calloc %lu, realloc %lu, free %lu", func_malloc_c, func_calloc_c, func_realloc_c, func_free_c); dmalloc_message("alloc calls: recalloc %lu, memalign %lu, valloc %lu", func_recalloc_c, func_memalign_c, func_valloc_c); dmalloc_message("alloc calls: new %lu, delete %lu", func_new_c, func_delete_c); dmalloc_message(" current memory in use: %lu bytes (%lu pnts)", alloc_current, alloc_cur_pnts); dmalloc_message(" total memory allocated: %lu bytes (%lu pnts)", _dmalloc_alloc_total, alloc_tot_pnts); /* maximum stats */ dmalloc_message(" max in use at one time: %lu bytes (%lu pnts)", alloc_maximum, alloc_max_pnts); dmalloc_message("max alloced with 1 call: %lu bytes", alloc_one_max); dmalloc_message("max unused memory space: %lu bytes (%lu%%)", alloc_max_given - alloc_maximum, (alloc_max_given == 0 ? 0 : ((alloc_max_given - alloc_maximum) * 100) / alloc_max_given)); #if MEMORY_TABLE_TOP_LOG dmalloc_message("top %d allocations:", MEMORY_TABLE_TOP_LOG); _dmalloc_table_log_info(mem_table_alloc, mem_table_alloc_c, MEM_ALLOC_ENTRIES, MEMORY_TABLE_TOP_LOG, 1 /* have in-use column */); #endif } /* * void _dmalloc_chunk_log_changed * * DESCRIPTION: * * Log the pointers that has changed since a pointer in time. * * RETURNS: * * None. * * ARGUMENTS: * * mark -> Dmalloc counter used to mark a specific time so that * servers can check on the changed pointers. * * log_non_free_b -> If set to 1 then log the new not-freed * (i.e. used) pointers. * * log_free_b -> If set to 1 then log the new freed pointers. * * details_b -> If set to 1 then dump the individual pointer entries * instead of just the summary. */ void _dmalloc_chunk_log_changed(const unsigned long mark, const int log_not_freed_b, const int log_freed_b, const int details_b) { skip_alloc_t *slot_p; pnt_info_t pnt_info; int known_b, freed_b, used_b; char out[DUMP_SPACE * 4], *which_str; char where_buf[MAX_FILE_LENGTH + 64], disp_buf[64]; int unknown_size_c = 0, unknown_block_c = 0, out_len; int size_c = 0, block_c = 0, checking_list_c = 0; if (log_not_freed_b && log_freed_b) { which_str = "Not-Freed and Freed"; } else if (log_not_freed_b) { which_str = "Not-Freed"; } else if (log_freed_b) { which_str = "Freed"; } else { return; } if (mark == 0) { dmalloc_message("Dumping %s Pointers Changed Since Start:", which_str); } else { dmalloc_message("Dumping %s Pointers Changed Since Mark %lu:", which_str, mark); } /* clear out our memory table so we can fill it with pointer info */ _dmalloc_table_clear(mem_table_changed, MEM_CHANGED_ENTRIES, &mem_table_changed_c); /* run through the blocks */ for (slot_p = skip_address_list->sa_next_p[0]; ; slot_p = slot_p->sa_next_p[0]) { /* * switch to the free list in the middle after we've checked the * used pointer slots */ if (slot_p == NULL) { checking_list_c++; if (checking_list_c == 1) { slot_p = skip_free_list->sa_next_p[0]; } #if FREED_POINTER_DELAY else if (checking_list_c == 2) { slot_p = free_wait_list_head; } #endif else { /* we are done */ break; } if (slot_p == NULL) { break; } } freed_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FREE); used_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_USER); /* * check for different types */ if (! (freed_b || used_b)) { continue; } /* do we want to dump this one? */ if (! ((log_not_freed_b && used_b) || (log_freed_b && freed_b))) { continue; } /* is it too long ago? */ if (slot_p->sa_use_iter <= mark) { continue; } /* unknown pointer? */ if (slot_p->sa_file == DMALLOC_DEFAULT_FILE || slot_p->sa_line == DMALLOC_DEFAULT_LINE) { unknown_block_c++; unknown_size_c += slot_p->sa_user_size; known_b = 0; } else { known_b = 1; } get_pnt_info(slot_p, &pnt_info); if (known_b || (! BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_KNOWN))) { if (details_b) { dmalloc_message(" %s freed: '%s' (%u bytes) from '%s'", (freed_b ? " " : "not"), display_pnt(pnt_info.pi_user_start, slot_p, disp_buf, sizeof(disp_buf)), slot_p->sa_user_size, _dmalloc_chunk_desc_pnt(where_buf, sizeof(where_buf), slot_p->sa_file, slot_p->sa_line)); if ((! freed_b) && BIT_IS_SET(_dmalloc_flags, DEBUG_LOG_NONFREE_SPACE)) { out_len = expand_chars((char *)pnt_info.pi_user_start, DUMP_SPACE, out, sizeof(out)); dmalloc_message(" dump of '%#lx': '%.*s'", (unsigned long)pnt_info.pi_user_start, out_len, out); } } _dmalloc_table_insert(mem_table_changed, MEM_CHANGED_ENTRIES, slot_p->sa_file, slot_p->sa_line, slot_p->sa_user_size, &mem_table_changed_c); } } /* dump the summary from the table table */ _dmalloc_table_log_info(mem_table_changed, mem_table_changed_c, MEM_CHANGED_ENTRIES, 0 /* log all entries */, 0 /* no in-use column */); /* copy out size of pointers */ if (block_c > 0) { if (block_c - unknown_block_c > 0) { dmalloc_message(" known memory: %d pointer%s, %d bytes", block_c - unknown_block_c, (block_c - unknown_block_c == 1 ? "" : "s"), size_c - unknown_size_c); } if (unknown_block_c > 0) { dmalloc_message(" unknown memory: %d pointer%s, %d bytes", unknown_block_c, (unknown_block_c == 1 ? "" : "s"), unknown_size_c); } } } /* * unsigned long _dmalloc_chunk_count_changed * * DESCRIPTION: * * Return the pointers that has changed since a pointer in time. * * RETURNS: * * Number of bytes changed since mark. * * ARGUMENTS: * * mark -> Dmalloc counter used to mark a specific time so that * servers can check on the changed pointers. * * count_non_free_b -> If set to 1 then count the new not-freed * (i.e. used) pointers. * * count_free_b -> If set to 1 then count the new freed pointers. */ unsigned long _dmalloc_chunk_count_changed(const unsigned long mark, const int count_not_freed_b, const int count_freed_b) { skip_alloc_t *slot_p; int freed_b, used_b; int checking_list_c = 0; unsigned int mem_count = 0; /* run through the blocks */ for (slot_p = skip_address_list->sa_next_p[0]; ; slot_p = slot_p->sa_next_p[0]) { /* * switch to the free list in the middle after we've checked the * used pointer slots */ if (slot_p == NULL) { checking_list_c++; if (checking_list_c == 1) { slot_p = skip_free_list->sa_next_p[0]; } #if FREED_POINTER_DELAY else if (checking_list_c == 2) { slot_p = free_wait_list_head; } #endif else { /* we are done */ break; } if (slot_p == NULL) { break; } } freed_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_FREE); used_b = BIT_IS_SET(slot_p->sa_flags, ALLOC_FLAG_USER); /* * check for different types */ if (! (freed_b || used_b)) { continue; } /* is it too long ago? */ if (slot_p->sa_use_iter <= mark) { continue; } /* count the memory */ if (count_not_freed_b && used_b) { mem_count += slot_p->sa_user_size; } else if (count_freed_b && freed_b) { mem_count += slot_p->sa_user_size; } } return mem_count; } /* * void _dmalloc_chunk_get_stats * * DESCRIPTION: * * Return a number of statistics about the current heap. * * RETURNS: * * None. * * ARGUMENTS: * * heap_low_p <- Pointer to pointer which, if not 0L, will be set to * the low address in the heap. * * heap_high_p <- Pointer to pointer which, if not 0L, will be set to * the high address in the heap. * * total_space_p <- Pointer to an unsigned long which, if not 0L, will * be set to the total space managed by the library including user * space, administrative space, and overhead. * * user_space_p <- Pointer to an unsigned long which, if not 0L, will * be set to the space given to the user process (allocated and free). * * current_allocated_p <- Pointer to an unsigned long which, if not * 0L, will be set to the current allocated space given to the user * process. * * current_pnt_np <- Pointer to an unsigned long which, if not 0L, * will be set to the current number of pointers allocated by the user * process. * * max_allocated_p <- Pointer to an unsigned long which, if not 0L, * will be set to the maximum allocated space given to the user * process. * * max_pnt_np <- Pointer to an unsigned long which, if not 0L, will be * set to the maximum number of pointers allocated by the user * process. * * max_one_p <- Pointer to an unsigned long which, if not 0L, will be * set to the maximum allocated with 1 call by the user process. */ void _dmalloc_chunk_get_stats(void **heap_low_p, void **heap_high_p, unsigned long *total_space_p, unsigned long *user_space_p, unsigned long *current_allocated_p, unsigned long *current_pnt_np, unsigned long *max_allocated_p, unsigned long *max_pnt_np, unsigned long *max_one_p) { SET_POINTER(heap_low_p, _dmalloc_heap_low); SET_POINTER(heap_high_p, _dmalloc_heap_high); SET_POINTER(total_space_p, (user_block_c + admin_block_c) * BLOCK_SIZE); SET_POINTER(user_space_p, alloc_current + free_space_bytes); SET_POINTER(current_allocated_p, alloc_current); SET_POINTER(current_pnt_np, alloc_cur_pnts); SET_POINTER(max_allocated_p, alloc_maximum); SET_POINTER(max_pnt_np, alloc_max_pnts); SET_POINTER(max_one_p, alloc_one_max); } dmalloc-5.5.2/arg_check.h000640 001751 001751 00000016164 10622115666 015176 0ustar00graygray000000 000000 /* * Defines for malloc string routines... * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: arg_check.h,v 1.25 2007/03/22 19:40:52 gray Exp $ */ #ifndef __ARG_CHECK_H__ #define __ARG_CHECK_H__ #include "conf.h" #include "dmalloc.h" /* for DMALLOC_SIZE */ /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ #if HAVE_ATOI /* * Dummy function for checking atoi's arguments. */ extern int _dmalloc_atoi(const char *file, const int line, const char *str); #endif /* if HAVE_ATOI */ #if HAVE_ATOL /* * Dummy function for checking atol's arguments. */ extern long _dmalloc_atol(const char *file, const int line, const char *str); #endif /* if HAVE_ATOL */ #if HAVE_BCMP /* * Dummy function for checking bcmp's arguments. */ extern int _dmalloc_bcmp(const char *file, const int line, const void *b1, const void *b2, const DMALLOC_SIZE len); #endif /* if HAVE_BCMP */ #if HAVE_BCOPY /* * Dummy function for checking bcopy's arguments. */ extern void _dmalloc_bcopy(const char *file, const int line, const void *from, void *to, const DMALLOC_SIZE len); #endif /* if HAVE_BCOPY */ #if HAVE_BZERO /* * Dummy function for checking bzero's arguments. */ extern void _dmalloc_bzero(const char *file, const int line, void *buf, const DMALLOC_SIZE len); #endif /* if HAVE_BZERO */ #if HAVE_INDEX /* * Dummy function for checking index's arguments. */ extern char *_dmalloc_index(const char *file, const int line, const char *str, const char ch); #endif /* if HAVE_INDEX */ #if HAVE_MEMCCPY /* * Dummy function for checking memccpy's arguments. */ extern void *_dmalloc_memccpy(const char *file, const int line, void *dest, const void *src, const int ch, const DMALLOC_SIZE len); #endif /* if HAVE_MEMCCPY */ #if HAVE_MEMCHR /* * Dummy function for checking memchr's arguments. */ extern void *_dmalloc_memchr(const char *file, const int line, const void *s1, const int ch, const DMALLOC_SIZE len); #endif /* if HAVE_MEMCHR */ #if HAVE_MEMCMP /* * Dummy function for checking memcmp's arguments. */ extern int _dmalloc_memcmp(const char *file, const int line, const void *b1, const void *b2, const DMALLOC_SIZE len); #endif /* if HAVE_MEMCMP */ #if HAVE_MEMCPY /* * Dummy function for checking memcpy's arguments. */ extern void *_dmalloc_memcpy(const char *file, const int line, void *to, const void *from, const DMALLOC_SIZE len); #endif /* if HAVE_MEMCPY */ #if HAVE_MEMMOVE /* * Dummy function for checking memmove's arguments. */ extern void *_dmalloc_memmove(const char *file, const int line, void *to, const void *from, const DMALLOC_SIZE len); #endif /* if HAVE_MEMMOVE */ #if HAVE_MEMSET /* * Dummy function for checking memset's arguments. */ extern void *_dmalloc_memset(const char *file, const int line, void *buf, const int ch, const DMALLOC_SIZE len); #endif /* if HAVE_MEMSET */ #if HAVE_RINDEX /* * Dummy function for checking rindex's arguments. */ extern char *_dmalloc_rindex(const char *file, const int line, const char *str, const char ch); #endif /* if HAVE_RINDEX */ #if HAVE_STRCASECMP /* * Dummy function for checking strcasecmp's arguments. */ extern int _dmalloc_strcasecmp(const char *file, const int line, const char *s1, const char *s2); #endif /* if HAVE_STRCASECMP */ #if HAVE_STRCAT /* * Dummy function for checking strcat's arguments. */ extern char *_dmalloc_strcat(const char *file, const int line, char *to, const char *from); #endif /* if HAVE_STRCAT */ #if HAVE_STRCHR /* * Dummy function for checking strchr's arguments. */ extern char *_dmalloc_strchr(const char *file, const int line, const char *str, const int ch); #endif /* if HAVE_STRCHR */ #if HAVE_STRCMP /* * Dummy function for checking strcmp's arguments. */ extern int _dmalloc_strcmp(const char *file, const int line, const char *s1, const char *s2); #endif /* if HAVE_STRCMP */ #if HAVE_STRCPY /* * Dummy function for checking strcpy's arguments. */ extern char *_dmalloc_strcpy(const char *file, const int line, char *to, const char *from); #endif /* if HAVE_STRCPY */ #if HAVE_STRCSPN /* * Dummy function for checking strcspn's arguments. */ extern int _dmalloc_strcspn(const char *file, const int line, const char *str, const char *list); #endif /* if HAVE_STRCSPN */ #if HAVE_STRLEN /* * Dummy function for checking strlen's arguments. */ extern DMALLOC_SIZE _dmalloc_strlen(const char *file, const int line, const char *str); #endif /* if HAVE_STRLEN */ #if HAVE_STRNCASECMP /* * Dummy function for checking strncasecmp's arguments. */ extern int _dmalloc_strncasecmp(const char *file, const int line, const char *s1, const char *s2, const DMALLOC_SIZE len); #endif /* if HAVE_STRNCASECMP */ #if HAVE_STRNCAT /* * Dummy function for checking strncat's arguments. */ extern char *_dmalloc_strncat(const char *file, const int line, char *to, const char *from, const DMALLOC_SIZE len); #endif /* if HAVE_STRNCAT */ #if HAVE_STRNCMP /* * Dummy function for checking strncmp's arguments. */ extern int _dmalloc_strncmp(const char *file, const int line, const char *s1, const char *s2, const DMALLOC_SIZE len); #endif /* if HAVE_STRNCMP */ #if HAVE_STRNCPY /* * Dummy function for checking strncpy's arguments. */ extern char *_dmalloc_strncpy(const char *file, const int line, char *to, const char *from, const DMALLOC_SIZE len); #endif /* if HAVE_STRNCPY */ #if HAVE_STRPBRK /* * Dummy function for checking strpbrk's arguments. */ extern char *_dmalloc_strpbrk(const char *file, const int line, const char *str, const char *list); #endif /* if HAVE_STRPBRK */ #if HAVE_STRRCHR /* * Dummy function for checking strrchr's arguments. */ extern char *_dmalloc_strrchr(const char *file, const int line, const char *str, const int ch); #endif /* if HAVE_STRRCHR */ #if HAVE_STRSPN /* * Dummy function for checking strspn's arguments. */ extern int _dmalloc_strspn(const char *file, const int line, const char *str, const char *list); #endif /* if HAVE_STRSPN */ #if HAVE_STRSTR /* * Dummy function for checking strstr's arguments. */ extern char *_dmalloc_strstr(const char *file, const int line, const char *str, const char *pat); #endif /* if HAVE_STRSTR */ #if HAVE_STRTOK /* * Dummy function for checking strtok's arguments. */ extern char *_dmalloc_strtok(const char *file, const int line, char *str, const char *sep); #endif /* if HAVE_STRTOK */ /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ #endif /* ! __ARG_CHECK_H__ */ dmalloc-5.5.2/arg_check.c000640 001751 001751 00000045103 10622115666 015164 0ustar00graygray000000 000000 /* * Functions for testing of string routines arguments. * * Copyright 2000 by Gray Watson * * This file is part of the dmalloc package. * * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of Gray Watson not be used in advertising * or publicity pertaining to distribution of the document or software * without specific, written prior permission. * * Gray Watson makes no representations about the suitability of the * software described herein for any purpose. It is provided "as is" * without express or implied warranty. * * The author may be contacted via http://dmalloc.com/ * * $Id: arg_check.c,v 1.40 2007/03/25 03:06:35 gray Exp $ */ /* * This file contains functions to be used to verify the arguments of * string functions. If enabled these can discover problems with * heap-based strings (such as fence errors) much closer to the error. */ #define DMALLOC_DISABLE #if HAVE_STRING_H # include #endif #if HAVE_STDLIB_H # include #endif #include "conf.h" #include "dmalloc.h" #include "chunk.h" #include "debug_tok.h" #include "error.h" #include "dmalloc_loc.h" #include "arg_check.h" /* * Dummy function for checking strlen's arguments. */ static int loc_strlen(const char *file, const int line, const char *func, const char *str) { int len = 0; const char *str_p; if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, func, str, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in %s", func); } } for (str_p = str; *str_p != '\0'; str_p++) { len++; } return len; } #if HAVE_ATOI /* * Dummy function for checking atoi's arguments. */ int _dmalloc_atoi(const char *file, const int line, const char *str) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "atoi", str, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in atoi"); } } return atoi(str); } #endif /* HAVE_ATOI */ #if HAVE_ATOL /* * Dummy function for checking atol's arguments. */ long _dmalloc_atol(const char *file, const int line, const char *str) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "atol", str, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in atol"); } } return atol(str); } #endif /* HAVE_ATOL */ #if HAVE_BCMP /* * Dummy function for checking bcmp's arguments. */ int _dmalloc_bcmp(const char *file, const int line, const void *b1, const void *b2, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "bcmp", b1, 0 /* not exact */, len)) || (! dmalloc_verify_pnt(file, line, "bcmp", b2, 0 /* not exact */, len))) { dmalloc_message("bad pointer argument found in bcmp"); } } return bcmp(b1, b2, len); } #endif /* HAVE_BCMP */ #if HAVE_BCOPY /* * Dummy function for checking bcopy's arguments. */ void _dmalloc_bcopy(const char *file, const int line, const void *from, void *to, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "bcopy", from, 0 /* not exact */, len)) || (! dmalloc_verify_pnt(file, line, "bcopy", to, 0 /* not exact */, len))) { dmalloc_message("bad pointer argument found in bcopy"); } } bcopy(from, to, len); } #endif /* HAVE_BCOPY */ #if HAVE_BZERO /* * Dummy function for checking bzero's arguments. */ void _dmalloc_bzero(const char *file, const int line, void *buf, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "bzero", buf, 0 /* not exact */, len)) { dmalloc_message("bad pointer argument found in bzero"); } } bzero(buf, len); } #endif /* HAVE_BZERO */ #if HAVE_INDEX /* * Dummy function for checking index's arguments. */ char *_dmalloc_index(const char *file, const int line, const char *str, const char ch) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "index", str, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in index"); } } return (char *)index(str, ch); } #endif /* HAVE_INDEX */ #if HAVE_MEMCCPY /* * Dummy function for checking memccpy's arguments. */ void *_dmalloc_memccpy(const char *file, const int line, void *dest, const void *src, const int ch, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { const char *src_p; int min_size; /* so we have to figure out the max length of the buffer directly here */ for (src_p = (char *)src; src_p < (char *)src + len; src_p++) { if (*src_p == ch) { src_p++; break; } } min_size = src_p - (char *)src; /* maybe len maybe first ch */ if ((! dmalloc_verify_pnt(file, line, "memccpy", dest, 0 /* not exact */, min_size)) || (! dmalloc_verify_pnt(file, line, "memccpy", src, 0 /* not exact */, min_size))) { dmalloc_message("bad pointer argument found in memccpy"); } } return (void *)memccpy(dest, src, ch, len); } #endif /* HAVE_MEMCCPY */ #if HAVE_MEMCHR /* * Dummy function for checking memchr's arguments. */ void *_dmalloc_memchr(const char *file, const int line, const void *s1, const int ch, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "memchr", s1, 0 /* not exact */, len)) { dmalloc_message("bad pointer argument found in memchr"); } } return (void *)memchr(s1, ch, len); } #endif /* HAVE_MEMCHR */ #if HAVE_MEMCMP /* * Dummy function for checking memcmp's arguments. */ int _dmalloc_memcmp(const char *file, const int line, const void *b1, const void *b2, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "memcmp", b1, 0 /* not exact */, len)) || (! dmalloc_verify_pnt(file, line, "memcmp", b2, 0 /* not exact */, len))) { dmalloc_message("bad pointer argument found in memcmp"); } } return memcmp(b1, b2, len); } #endif /* HAVE_MEMCMP */ #if HAVE_MEMCPY /* * Dummy function for checking memcpy's arguments. */ void *_dmalloc_memcpy(const char *file, const int line, void *to, const void *from, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "memcpy", to, 0 /* not exact */, len)) || (! dmalloc_verify_pnt(file, line, "memcpy", from, 0 /* not exact */, len))) { dmalloc_message("bad pointer argument found in memcpy"); } #if HAVE_MEMMOVE /* * If memmove exists, dump out a warning if memcpy is being used * for overlapping memory segments. */ if (((char *)from < (char *)to && (char *)from + len > (char *)to) || ((char *)to < (char *)from && (char *)to + len > (char *)from)) { dmalloc_message("%s:%d: WARNING: memory overlap in memcpy, should use memmove", file, line); } #endif } return (void *)memcpy(to, from, len); } #endif /* HAVE_MEMCPY */ #if HAVE_MEMMOVE /* * Dummy function for checking memmove's arguments. */ void *_dmalloc_memmove(const char *file, const int line, void *to, const void *from, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "memmove", to, 0 /* not exact */, len)) || (! dmalloc_verify_pnt(file, line, "memmove", from, 0 /* not exact */, len))) { dmalloc_message("bad pointer argument found in memmove"); } } return (void *)memmove(to, from, len); } #endif /* HAVE_MEMMOVE */ #if HAVE_MEMSET /* * Dummy function for checking memset's arguments. */ void *_dmalloc_memset(const char *file, const int line, void *buf, const int ch, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "memset", buf, 0 /* not exact */, len)) { dmalloc_message("bad pointer argument found in memset"); } } return (void *)memset(buf, ch, len); } #endif /* HAVE_MEMSET */ #if HAVE_RINDEX /* * Dummy function for checking rindex's arguments. */ char *_dmalloc_rindex(const char *file, const int line, const char *str, const char ch) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "rindex", str, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in rindex"); } } return (char *)rindex(str, ch); } #endif /* HAVE_RINDEX */ #if HAVE_STRCASECMP /* * Dummy function for checking strcasecmp's arguments. */ int _dmalloc_strcasecmp(const char *file, const int line, const char *s1, const char *s2) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "strcasecmp", s1, 0 /* not exact */, -1)) || (! dmalloc_verify_pnt(file, line, "strcasecmp", s2, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strcasecmp"); } } return strcasecmp(s1, s2); } #endif /* HAVE_STRCASECMP */ #if HAVE_STRCAT /* * Dummy function for checking strcat's arguments. */ char *_dmalloc_strcat(const char *file, const int line, char *to, const char *from) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "strcat", to, 0 /* not exact */, loc_strlen(file, line, "strcat", to) + loc_strlen(file, line, "strcat", from) + 1)) || (! dmalloc_verify_pnt(file, line, "strcat", from, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strcat"); } } return (char *)strcat(to, from); } #endif /* HAVE_STRCAT */ #if HAVE_STRCHR /* * Dummy function for checking strchr's arguments. */ char *_dmalloc_strchr(const char *file, const int line, const char *str, const int ch) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "strchr", str, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in strchr"); } } return (char *)strchr(str, ch); } #endif /* HAVE_STRCHR */ #if HAVE_STRCMP /* * Dummy function for checking strcmp's arguments. */ int _dmalloc_strcmp(const char *file, const int line, const char *s1, const char *s2) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "strcmp", s1, 0 /* not exact */, -1)) || (! dmalloc_verify_pnt(file, line, "strcmp", s2, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strcmp"); } } return strcmp(s1, s2); } #endif /* HAVE_STRCMP */ #if HAVE_STRCPY /* * Dummy function for checking strcpy's arguments. */ char *_dmalloc_strcpy(const char *file, const int line, char *to, const char *from) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "strcpy", to, 0 /* not exact */, loc_strlen(file, line, "strcpy", from) + 1)) || (! dmalloc_verify_pnt(file, line, "strcpy", from, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strcpy"); } } return (char *)strcpy(to, from); } #endif /* HAVE_STRCPY */ #if HAVE_STRCSPN /* * Dummy function for checking strcspn's arguments. */ int _dmalloc_strcspn(const char *file, const int line, const char *str, const char *list) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "strcspn", str, 0 /* not exact */, -1)) || (! dmalloc_verify_pnt(file, line, "strcspn", list, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strcspn"); } } return strcspn(str, list); } #endif /* HAVE_STRCSPN */ #if HAVE_STRLEN /* * Dummy function for checking strlen's arguments. */ DMALLOC_SIZE _dmalloc_strlen(const char *file, const int line, const char *str) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "strlen", str, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in strlen"); } } return loc_strlen(file, line, "strlen", str); } #endif #if HAVE_STRNCASECMP /* * Dummy function for checking strncasecmp's arguments. */ int _dmalloc_strncasecmp(const char *file, const int line, const char *s1, const char *s2, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { const char *s1_p, *s2_p; int min_size; /* we go through both pointers up to the length characters */ for (s1_p = s1, s2_p = s2; s1_p < s1 + len; s1_p++, s2_p++) { if (*s1_p == '\0' || *s2_p == '\0') { s1_p++; break; } } min_size = s1_p - s1; if ((! dmalloc_verify_pnt(file, line, "strncasecmp", s1, 0 /* not exact */, min_size)) || (! dmalloc_verify_pnt(file, line, "strncasecmp", s2, 0 /* not exact */, min_size))) { dmalloc_message("bad pointer argument found in strncasecmp"); } } return strncasecmp(s1, s2, len); } #endif /* HAVE_STRNCASECMP */ #if HAVE_STRNCAT /* * Dummy function for checking strncat's arguments. */ char *_dmalloc_strncat(const char *file, const int line, char *to, const char *from, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { const char *from_p; int min_size; /* so we have to figure out the max length of the buffers directly here */ for (from_p = from; from_p < from + len; from_p++) { if (*from_p == '\0') { /* no need to do ++ here because we +1 for the \0 anyway */ break; } } min_size = from_p - from; /* either len or nullc */ if ((! dmalloc_verify_pnt(file, line, "strncat", to, 0 /* not exact */, loc_strlen(file, line, "strncat", to) + min_size + 1)) || (! dmalloc_verify_pnt(file, line, "strncat", from, 0 /* not exact */, min_size))) { dmalloc_message("bad pointer argument found in strncat"); } } return (char *)strncat(to, from, len); } #endif /* HAVE_STRNCAT */ #if HAVE_STRNCMP /* * Dummy function for checking strncmp's arguments. */ int _dmalloc_strncmp(const char *file, const int line, const char *s1, const char *s2, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { const char *s1_p, *s2_p; int min_size; /* so we have to figure out the max length of the buffers directly here */ for (s1_p = s1, s2_p = s2; s1_p < s1 + len; s1_p++, s2_p++) { if (*s1_p == '\0' || *s2_p == '\0') { s1_p++; break; } } min_size = s1_p - s1; /* either len or nullc */ if ((! dmalloc_verify_pnt(file, line, "strncmp", s1, 0 /* not exact */, min_size)) || (! dmalloc_verify_pnt(file, line, "strncmp", s2, 0 /* not exact */, min_size))) { dmalloc_message("bad pointer argument found in strncmp"); } } return strncmp(s1, s2, len); } #endif /* HAVE_STRNCMP */ #if HAVE_STRNCPY /* * Dummy function for checking strncpy's arguments. */ char *_dmalloc_strncpy(const char *file, const int line, char *to, const char *from, const DMALLOC_SIZE len) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { const char *from_p; int min_size; /* so we have to figure out the max length of the buffers directly here */ for (from_p = from; from_p < from + len; from_p++) { if (*from_p == '\0') { from_p++; break; } } min_size = from_p - from; /* len or until nullc */ if ((! dmalloc_verify_pnt(file, line, "strncpy", to, 0 /* not exact */, min_size)) || (! dmalloc_verify_pnt(file, line, "strncpy", from, 0 /* not exact */, min_size))) { dmalloc_message("bad pointer argument found in strncpy"); } } return (char *)strncpy(to, from, len); } #endif /* HAVE_STRNCPY */ #if HAVE_STRPBRK /* * Dummy function for checking strpbrk's arguments. */ char *_dmalloc_strpbrk(const char *file, const int line, const char *str, const char *list) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "strpbrk", str, 0 /* not exact */, -1)) || (! dmalloc_verify_pnt(file, line, "strpbrk", list, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strpbrk"); } } return (char *)strpbrk(str, list); } #endif /* HAVE_STRPBRK */ #if HAVE_STRRCHR /* * Dummy function for checking strrchr's arguments. */ char *_dmalloc_strrchr(const char *file, const int line, const char *str, const int ch) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if (! dmalloc_verify_pnt(file, line, "strrchr", str, 0 /* not exact */, -1)) { dmalloc_message("bad pointer argument found in strrchr"); } } return (char *)strrchr(str, ch); } #endif /* HAVE_STRRCHR */ #if HAVE_STRSPN /* * Dummy function for checking strspn's arguments. */ int _dmalloc_strspn(const char *file, const int line, const char *str, const char *list) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "strspn", str, 0 /* not exact */, -1)) || (! dmalloc_verify_pnt(file, line, "strspn", list, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strspn"); } } return strspn(str, list); } #endif /* HAVE_STRSPN */ #if HAVE_STRSTR /* * Dummy function for checking strstr's arguments. */ char *_dmalloc_strstr(const char *file, const int line, const char *str, const char *pat) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((! dmalloc_verify_pnt(file, line, "strstr", str, 0 /* not exact */, -1)) || (! dmalloc_verify_pnt(file, line, "strstr", pat, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strstr"); } } return (char *)strstr(str, pat); } #endif /* HAVE_STRSTR */ #if HAVE_STRTOK /* * Dummy function for checking strtok's arguments. */ char *_dmalloc_strtok(const char *file, const int line, char *str, const char *sep) { if (BIT_IS_SET(_dmalloc_flags, DEBUG_CHECK_FUNCS)) { if ((str != NULL && (! dmalloc_verify_pnt(file, line, "strtok", str, 0 /* not exact */, -1))) || (! dmalloc_verify_pnt(file, line, "strtok", sep, 0 /* not exact */, -1))) { dmalloc_message("bad pointer argument found in strtok"); } } return (char *)strtok(str, sep); } #endif /* HAVE_STRTOK */ dmalloc-5.5.2/dmallocrc000640 001751 001751 00000010215 10622115666 014771 0ustar00graygray000000 000000 # # Sample RC file for the debug malloc library # Rename this to .dmallocrc and place in your $HOME directory to # activate. See dmalloc.info for more information. # # $Id: dmallocrc,v 1.32 1998/11/12 21:42:31 gray Exp $ # # # This file maps tags to certain combinations of debug tokens. The # tags here are provided as an example. You can also roll your own. # Lines in this file should have the form: # # tag token1, token2, ... # # To use the above line you say 'dmalloc tag' which enables the # debugging facilities token1, token2, ... You must pass the output # from dmalloc through your shell's eval command to change your # environment. See malloc.info for more information. # # Lines can end with a \ meaning it continues onto the next line. # Lines beginning with '#' and empty lines are ignored # # # Token: Description: ########################################################################### # none no debugging functionality # # log-stats log general statistics # log-non-free log non-freed memory pointers on shutdown # log-trans log memory transactions # log-admin log full administrative information # log-blocks log detailed block information in heap_map # log-unknown log unknown non-freed memory pointers too # log-bad-space log actual bytes from bad pointers # log-nonfree-space log actual bytes in non-freed pointers # log-elapsed-time log elapsed-time for allocated pointer # log-current-time log current-time for allocated pointers # # check-fence check fence-post areas # check-heap do general heap checking # check-lists verify internal heap linked-lists # check-blank check to see if blank space is overwritten # check-funcs check the arguments of some routines # # catch-signals shutdown the library on SIGHUP, SIGINT, SIGTERM # realloc-copy always copy data to a new pointer when realloc # free-blank overwrite space that is freed # error-abort abort the program (and dump core) on errors # alloc-blank blank space that is to be alloced # heap-check-map log a heap-map every time the heap is checked # print-messages print errors and messages to STDERR # catch-null abort program if library can't get sbrk space # never-reuse never reuse memory that has been freed # allow-nonlinear allow non-linear heap space # allow-free-null allow the freeing of NULL pointers # error-dump dump core on error and then continue # # no debugging (for disabling memory checking) none none # basic runtime tests runtime log-stats, log-non-free, log-blocks, log-bad-space, \ log-unknown, \ check-fence, \ catch-null # minimal checking low log-stats, log-non-free, log-blocks, log-bad-space, \ log-unknown, log-elapsed-time, \ check-fence, \ free-blank, error-abort, alloc-blank, catch-null # significant checking medium log-stats, log-non-free, log-blocks, log-bad-space, \ log-unknown, log-elapsed-time, \ check-fence, check-heap, check-lists, \ realloc-copy, free-blank, error-abort, alloc-blank, \ catch-null # extensive checking high log-stats, log-non-free, log-blocks, log-bad-space, \ log-unknown, log-elapsed-time, \ check-fence, check-heap, check-lists, check-blank, \ check-funcs, \ realloc-copy, free-blank, error-abort, alloc-blank, \ catch-null # full logging of statistics log log-stats, log-non-free, log-trans, log-admin, log-blocks, \ log-unknown, log-bad-space, log-elapsed-time, \ check-fence, \ catch-null # immediate logging of problems in a text-based programs text log-bad-space, log-unknown, \ check-fence, \ catch-null, print-messages # full logging of statistics in text programs verbose log-stats, log-non-free, log-trans, log-admin, log-blocks, \ log-unknown, log-bad-space, log-elapsed-time, \ check-fence, \ catch-null, print-messages # the kitchen-sink minus a couple special tokens: # log-current-time, print-messages, allow-nonlinear, allow-free-null, # error-dump all log-stats, log-non-free, log-trans, log-admin, log-blocks, \ log-unknown, log-bad-space, log-elapsed-time, \ check-fence, check-heap, check-lists, check-blank, \ check-funcs, \ catch-signals, realloc-copy, free-blank, error-abort, \ alloc-blank, heap-check-map, catch-null, never-reuse dmalloc-5.5.2/RELEASE.html000640 001751 001751 00000006522 10622115666 015062 0ustar00graygray000000 000000 Dmalloc Release Notes - 5.5.2

Debug Malloc (Dmalloc) Library Release Notes

Version: Release 5.5.2
Last-Version: 5.5.1
Date: May 14, 2007

Overview    New Functionality    Dmalloc Utility    Debug Tokens    settings.dist    Installation    Programming    Environmental Variables    Bugs Fixed

Overview

Bug fix release to fix a couple stupid build and install problems.

New Functionality

None.

Dmalloc Utility Changes

None.

Changes in the Debug Tokens

None.

Changes to the settings.dist File

None.

Installation Changes

  • Removed any reference to the info file in the document installation process. Added in the installation of dmalloc.pdf.

Programming Notes

None.

Environmental Variable Changes

None.

Bugs Fixed

  • Removed some left-over references to the dmalloc.info file which was causing the installdocs Makefile target to fail.
  • Fixed some unsigned/signed issues in one of the dmalloc_t tests that was causing occasional false failures of dmalloc_t.
  • Fixed problems with configure and SL_LINK_OBJS. Not sure what I was trying to attempt with this but it was not correct.

Dmalloc Home Page. Copyright 2007 Gray Watson.






















































dmalloc-5.5.2/README000644 001751 001751 00000007302 10622115666 013775 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- Debug Malloc Library ******************** Version 5.5.2 - May 2007 The debug memory allocation or "dmalloc" library has been designed as a drop in replacement for the system's `malloc', `realloc', `calloc', `free' and other memory management routines while providing powerful debugging facilities configurable at runtime. These facilities include such things as memory-leak tracking, fence-post write detection, file/line number reporting, and general logging of statistics. The library is reasonably portable having been run successfully on at least the following operating systems: AIX, DGUX, Free/Net/OpenBSD, GNU/Hurd, HPUX, Irix, Linux, Mac OSX, NeXT, OSF/DUX, SCO, Solaris, Ultrix, Unixware, MS Windows, and Unicos on a Cray T3E. It also provides support for the debugging of threaded programs. *Note Using With Threads::. The package includes the library, configuration scripts, debug utility application, test program, and documentation. Online documentation as well as the full source is available at URL `http://dmalloc.com/'. Details on the library's mailing list are available there as well. Please use the forums at URL `http://dmalloc.com/' to discuss any problems or to request features. If you are still having problems, the author can be reached via his home page at URL `http://256.com/gray/' with questions or feedback. Please include the version number of the library that you are using, your machine and operating system types, and the value of the DMALLOC_OPTIONS environment variable. Gray Watson. ------------------------------------------------------------------------------- See the INSTALL file for building, installation, and quick-start notes. ------------------------------------------------------------------------------- DOCUMENTATION: Examine the dmalloc.html file which contains the user-documentation for the dmalloc subsystem. There also is an dmalloc.info file which can be installed in the emacs info directory and read with emacs/info or the info program available from the texinfo package at GNU archive sites. It is also suitable for reading as text. The source of all documation is the dmalloc.texi texinfo file which also can generate postscript or TeX hardcopy output with the help of the texinfo.tex file. You can download the full documentation package or read it online from the repository. http://dmalloc.com/ ------------------------------------------------------------------------------- ARGV LIBRARY: My argv library should have been included with this package (argv.[ch], argv_loc.h). I use it with all my binaries. It functions similar to the getopt routines in that it provides a standardized way of processing arguments. However, that is where the similarity ends. You have to write no C code to do the actual processing, it handles short -l and long --logfile style options, gives standard short and long usage messages, and many other features while trying to comply with POSIX specs. The newest versions of the argv library are available on the web: http://256.com/sources/argv/ ------------------------------------------------------------------------------- THANKS: Many net folk contributed to the design, development, and overall library and my thanks goes out to them all. ------------------------------------------------------------------------------- AUTHOR: If you have any questions, comments, or problems feel free to send me mail. Gray Watson http://256.com/gray/ ------------------------------------------------------------------------------- $Id: README.1,v 1.58 2000/03/30 19:31:56 gray Exp $ ------------------------------------------------------------------------------- dmalloc-5.5.2/NEWS000640 001751 001751 00000061137 10622115666 013616 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- $Id: NEWS,v 1.129 2007/05/14 17:23:42 gray Exp $ ------------------------------------------------------------------------------- Version 5.5.2 (5/14/2007): * Removed some left-over references to the dmalloc.info file. * Fixed some unsigned/signed issues in one of the dmalloc_t tests. * Fixed problems with configure and SL_LINK_OBJS. Version 5.5.1 (3/25/2007): * Fixed some problems with str[n]dup argument checking. * Fixed bug where LOG_PNT_SEEN_COUNT=0 caused dmalloc_examine segfault. * Fixed bug with the checking of the MAX_FILE_LENGTH. * Revamped the tests for user pointers. Added better support for sizes. * Added dmalloc_verify_pnt_strsize to support strnlen size testing. * Added missing DMALLOC_FUNC_CHECK routines: atoi, atol, memmove * Added a number of special checks for DMALLOC_FUNC_CHECK stuff. * Fixed all of the DMALLOC_FUNC_CHECK arguments. Version 5.5.0 (2/8/2007): * Fixed a problem with Cygwin env parsing. * Improved regression tests on argument checking functions. * Fixed some problems with function argument checking and length args. * Added handling of strndup function. * Added overlapping memory check for memcpy if memmove exists. * Added __FILE__ and __LINE__ arguments to function checks. * Added patches to [hopefully] improve the building under Mac OSX. * Added dmalloc_get_stats function to report on internal heap stats. * Fixed a problem with double free not reporting ERROR_ALREADY_FREE. * Added better checking for mmap compatibility during autoconfig. * Improved the usage output for dmalloc. * Improved some of the error values to better identify internal errors. * Fixed when LARGEST_ALLOCATION was 0 it was still being tested. * Increased the basic block default to 32k. * Improved test program output; * Fixed the global Makefile to install libs as 755 not 644. * Added some fixes for Compaq's C compiler. * Improved testing of small heap areas. Version 5.4.2 (10/19/2004): * Fixed a couple of longer standing stupid alloc/free blank bugs. Version 5.4.1 (10/12/2004): * Found and fixed a stupid little testing bug. Version 5.4.0 (10/12/2004): * Added return.h support for ARM processors. * Made allocation of 0 sized chunks the default. * Fixed some missing ; and a int/unsigned-int bug. * Added return.h support for AIX 4.3 RS/6000. * Added backwards compatibility for %d usage in logfile name. * Removed force-linear token because made invalid with mmap addition. * Added mmap usage inside of the library. Should it be the default? * Internal random algorithm now seeded with fixed value. * Really improved the logging of error information about pointers. * Added return.h support for ia64 machine type. * Increased the maximum source file length from 10k to 30k. * Added compat and arg_checking of atoi, atol, and memmove. * Added arg checking to internal strdup functions. Version 5.3.0 (01/28/2004): * Fixed bad bug where arch_check funcs weren't locking point checks. * Added dmalloc_verify_pnt function for proper external pointer checks. * Added dmalloc_memory_allocated function to help memory size checks. * Added --start-size to dmalloc to start checks after alloc X bytes. * Added check-shutdown token and support to check pointers on shutdown. * Added dmalloc_count_changed function. * Added ability to disable the LARGEST_ALLOCATION setting it to 0. Version 5.2.4 (11/18/2003): * Fixed bug with check-fence and check-funcs interaction. Thanks John. * Added support for rc shell. Thanks Michael. * Fixed a logfile NULL pointer printf. Thanks John. * Fleshed out the error code documentation. * Fixed Makefile.in to properly refer to docs directory. Thanks Mike. * Improved the docs about alias creation and usage. * Added testing for destructors in configure. Version 5.2.3 (09/29/2003): * Added new GetEnvironmentVariableA Cygwin call. Thanks to Rolf. * Added quick checks for the constructor attribute. * Changed configure script to define HAVE_... to 0 or 1. Thanks Brian. * Removed usage of environ from dmalloc_argv.c. Thanks Brian. Version 5.2.2 (09/08/2003): * Added a Cygwin section to the manual. * Added GETENV_SAFE testing for Cygwin environments. Feedback needed. * Fixed bug in function args pnt checking. Thanks TJ and Philippe. * Improved pnt checking code to properly check free space above alloc. * Fixed possible lock leak in the shutdown code. Thanks TJ. * Changed the installing of libraries to install-data. Version 5.2.1 (07/08/2003): * Fixed problems with macro arguments not in (). Thanks Paul. * Fixed problem with strdup not returning char *. Thanks Dan, Juhani. Version 5.2.0 (06/10/2003): * Renamed the "max memory space wasted" to "max unused memory space". * Added PDF documentation files to the installation. * Fixed a problem with the global Makefile and dmalloc_t. Thanks Bert. * Added new logfile expansion of %u as getuid() output. * Added new logfile expansion of %h as gethostname() output. * Added new logfile expansion of %t as time() output. * Added new logfile expansion of %p as getpid() output. * Added new logfile expansion of %i as thread-id output. * Removed the old logfile % processing. %d no longer expands to pid. * Added LOG_PID to settings.dist to log pid on each line of logfile. * Added LOG_REOPEN to reopen log if pid changes (fork). Thanks James. * Renamed LOG_ITERATION_COUNT to LOG_ITERATION in settings.dist. * Renamed STORE_SEEN_COUNT to LOG_PNT_SEEN_COUNT in settings.dist. * Renamed STORE_ITERATION_COUNT to LOG_PNT_ITERATION in settings.dist. * Renamed STORE_TIME to LOG_PNT_TIME in settings.dist. * Renamed STORE_TIMEVAL to LOG_PNT_TIMEVAL in settings.dist. * Renamed LOG_THREAD_ID to LOG_PNT_THREAD_ID in settings.dist. * Improved the log_stats and log_changed output a bit. Version 5.1.0 (06/08/2003): * Fixed the FREED_POINTER_DELAY functionality. * Removed PROTECT_BLOCKS from settings.dist because was unused. * Added contrib/tsecs perl script which converts epoch secs to ctime. * Removed the unused check-lists debug token. * Fixed the realloc-copy and never-reuse functionality. * Improved the stats output. * Added many automatic tests to dmalloc_t. * Expanded the arguments to dmalloc_examine to return more information. * Found/fixed problem where last-used mark was not set right properly. * Found/fixed bad problem where leaked memory was not being reported. Version 5.0.2 (06/04/2003): * Fixed some problems and improved code in the test utility dmalloc_t. * Integrated an internal random number generator to stop recursion. * Improved some of the configure script internals. * Added support for a.exe and other cc output forms for Windoze. Version 5.0.1 (05/20/2003): * Updated configure.ac script. * Added dmalloc_page_size() function. * Improved the auto-testing in dmalloc_t. * Found a [bad] problem with putting pointers back on the free list. * Added some checking of pointers on the free list. * Added the per-pointer checking for cleared free memory. * Compressed the per-pointer admin structure by 8 bytes. Version 5.0.0 (05/16/2003): * Added -M --memory-limit argument to dmalloc to limit allocations. * Deprecated log-blocks and heap-check-map debug tokens. * Added a currently in use stats to log-stats. * Removed a number of old error codes. * Fixed some literal ranlib entries in the Makefile.in. * Removed the USE_DMALLOC_LEAP functionality to simplify. * Added a function to re-open the logfile when processing flags. * Added section to docs about debugging daemon and CGI processes. * Made some cosmetic improvements to the configure.in script. * Due to public pressure, I've made free(0L) not an error by default. * Added separate characters for blanking allocs (0xda) vs frees (0xdf). * Removed short token support. Was anyone using this? * Did some more work on testing and chunk.c changes. * Added better autoconf checking of thread libraries for FreeBSD. * Added dmalloc_debug_setup function to set dmalloc flags thru a call. * Significantly changed how the library manages fence protected allocs. * Renamed _dmalloc_logpath to dmalloc_logpath to match the docs and .h. * Solved problem with dmalloc_t and no sbrk. * Added INTERNAL_MEMORY_SPACE setting to the settings.dist file. * Added the 'How It Works' section to the manual. * Removed necessity of strcat. * Removed use of strcpy internally. * Fixed problem with use of start-count and start-file. Version 4.8.2 (02/26/2001): * Installed new configure script to remove C++ requirement. * Added more information to error messages on freed memory overwrite. * Added heap checking when we shutdown if check-blank is enabled. * Added separate ALLOC_BLANK_CHAR and FREE_BLANK_CHAR to settings.dist. Version 4.8.1 (11/14/2000): * Added --enable-shlib to configure to enable building of shared libs. * Added autoconf handling of the shlibdir for installing shared libs. * Added improvements to the shared library creation in the Makefile. * Fixed the #ident "..."; semi-colon problem. Version 4.8.0 (11/10/2000): * Added OpenBSD port information. Hopefully Free/Net/... BSD as well. * Renamed malloc.h to malloc_funcs.h to avoid system conflicts. * Made log-unknown the default and depreciated the token. * Added log-known token to _only_ report on known (file/line) memory. * malloc_verify, dmalloc_verify now return [D]MALLOC_VERIFY_[NO]ERROR. * Just about every dmalloc function now initializes the library. * dmalloc_debug now takes unsigned-int flags and returns the old flags. * debug_current now returns an unsigned int flag value. * Added autoconfig handling of #ident. I hate Unix's lack of standards. * Fixed a bug in chunk.c. Version 4.7.1 (07/25/2000): * Fixed problem with check-blank on but not free-blank or alloc-blank. Version 4.7.0 (07/24/2000): * Added support for --disable-cxx and --enable-threads to configure. * Added autoconf code to see if the return macros work for an system. * Renamed USE_RET_ADDRESS to USE_RETURN_MACROS in settings.dist/h. * Added threaded C++ library support to Makefile. * Fixed problems with -p and -m not setting the debug flags. * Added 'force-linear' and depreciated the 'allow-nonlinear' token. Version 4.6.0 (05/17/2000): * Reworked internal init values for env vars pointed out by Carlton. * Fixed bug found by Mcvey where the 1st dblock alloc in block missed. * Moved to 'make cxx' and 'make installcxx' for building C++ library. * Removed DMALLOC_VERIFY_[NO]ERROR and replaced with DMALLOC_[NO]ERROR. * dmalloc_examine now returns DMALLOC_[NO]ERROR not [NO]ERROR. * Added initial mprotect configuration and stub functions. * Added autoconf building of cxx library per Dimitri's comments. * Revamped rpm.spec and renamed to dmalloc.rpm per Dimitri's comments. Version 4.5.2 (04/18/2000): * Fixed bug in chunk.c pointer checking. Thanks Ezra. * Cleaned up some of the compat.[ch] headers to better match reality. * Reorganized dmalloc.texi documentation and moved to using makeinfo. Version 4.5.1 (03/30/2000): * Fixed a compilation problem in dmalloc_lp.c. Version 4.5.0 (03/29/2000): * Added new dmalloc_mark() and dmalloc_log_changed() functions. Version 4.4.0 (03/20/2000): * Removed the stupid old Deansify.pl script. * Added rpm.spec file to the distribution. * Added code to fix some recursive problems with open and atexit. * Basically encorporated Randell's changes [finally]. Thanks dude. * Removed the stupid chunk.c unions. Why did I ever do that? * www.dmalloc.com -> dmalloc.com. * Added better help messages to dmalloc. * Fixed Makefile.dep creation with _th.o special objects. * Fixed the outputting of gratuitous colons. * Added @uref texinfo tags and new texinfo.tex. Version 4.3.0 (11/08/1999): * Fixed problems on Linux with the strdup macro. * Added copyright and url info for ident and what. * Added support for PTHREAD_MUTEX_INITIALIZER. * Added USE_DMALLOC_LEAP define in the settings.dist file. * Dmalloc now looks in the current directory for .dmallocrc before ~. * Rewrote a significant piece of the dmalloc utility. * Increased the filename size from 40 to 100 characters. Version 4.2.0 (03/11/1999): * Improved the autoconfig of abort and qsort safety. * Added memory tracking function to be called on each mem transaction. * Added DUMP_UNFREED_SUMMARY_ONLY variable to settings.dist. * Added MEMORY_TABLE_SIZE and MEMORY_TABLE_LOG vars to settings.dist. * Fixed problem with valloc exposed by moving to random(). * Fixed long standing problem with the NEVER-REUSE token. * Added memory table code for grouping of allocated and non-freed mem. * Removed a number of static variables for string buffers. * Removed PERMISSION file and all references to commercial-ness. * Moved to internal sprintf code for snprintf, etc.. * Added dmalloc_message to the exported list of functions. Version 4.1.2 (12/11/1998): * Fixed really bad bug which basically killed pthread support. Version 4.1.1 (11/16/1998): * Fixed signal autoconfiguration. Version 4.1.0 (11/16/1998): * Added HTML versions of the manuals to the releases. * Added FREED_POINTER_DELAY in settings.h. Delays pointer reuse. * Renamed allow-zero token to be allow-free-null. * Added LOG_TIME_NUMBER and LOG_CTIME_STRING to the settings.h. * Disabled the log-thread-id macro. Use LOG_THREAD_ID in settings.h. * Disabled the log-stamp macro. Use LOG_TIME_NUMBER in settings.h. * Added -g (--gdb) flag to dmalloc utility along with gdb script. * Added missing delete[] function to the C++ code. * Moved some settings from chunk_loc.h into settings.dist. * Improved the handling of free(NULL) and malloc(0) settings. * Added initial memalign support with a first-time error message. * Renamed print-error token to print-messages. * Increased the default max memory size from 16mb to 64mb. Version 4.0.3 (10/15/1998): * Found and fixed a bug when reallocing a previous valloced section. Version 4.0.2 (10/15/1998): * Fixed a problem in return.h and DMALLOC_UNKNOWN_FILE. Version 4.0.1 (10/08/1998): * Added startup messages acknowledging the thread status. * Fixed problem with thread compilation and chunk.c. * Fixed possible race condition with synchronizing with external sbrks. * Migrated in new argv code. Version 4.0.0 (10/04/1998): * Made a small change to the solaris return.h code. * Added recalloc support into the library. * Cleaned up the calloc special handling and accounting. * Added valloc support to the library for OSF thread libraries. * Improved the pthread autoconfiguration and the code. * Got rid of the _dmalloc_file and _dmalloc_line crap. * Added FTX return.h information. * Added direct strdup support to the library. Version 3.3.1 (02/10/1998): * Shifted some flags to ints instead of longs. * Improved error string handling. * Removed allocation macros from the docs and the header. * Added realloc(pnt, 0) works like free(pnt). * Reworked log_error_info routine's dumping of the upper fence post. Version 3.3.0 (12/08/1997): * Added THREAD_LOCK_INIT_VAL autoconfigure. * Performed some long overdue major code cleaning. * Renamed argv.[ch] to dmalloc_argv.[ch] to not clash with argv files. * Added return address handling for SGI. * Added better C++ overload functions. * Added test for DMALLOC_SIZE unsigned-ness. * Added a FINI_DMALLOC setting to settings.dist for OSF __fini_ stuff. * Added pthread lock_on -o environmental settings. Version 3.2.1 (03/21/1997): * Added to dmalloc the ability to recognize its internal tags. * Added better documentation of auto-dmalloc_shutdown. * Fixed a number of signed/unsigned problems. * Removed autoconf rule in Makefile.all. * Cleaned up pthreads locking delay code. Version 3.2.0 (01/17/1997): * Added catch-signals debug token. * Improved configure script to use cache and new autoconf macros. * Updated the GNU support scripts and configure. * Fixed the locking for pthread programs. Dumb errors. * Ran new fillproto on h-files. IMPORT -> extern. Version 3.1.3 (12/28/1995): * Removed silent dumps of test program. * Removed some unresolved references in argv.c: strcasecmp, strdup. * Fixed some porting problems to Unixware. Unsigned chars!! Version 3.1.2 (10/10/1995): * Changes to basic-block handling in chunk. Fixed non-linear code. * Added inital thread locking for debugging threaded programs. * Added settings.dist file which is copied to settings.h during config. * New attempts to auto-configure DMALLOC_SIZE for size_t. * Added dmalloc_aborting flag in case kill or abort recurses. * Added new[] C++ function. Version 3.1.1 (08/18/1995): * Added better non-linear processing. * Made non-linear now default behaviour with internal dmalloc tags. * Fixed up dmalloc_t to propogate errors better. Version 3.1.0 (07/14/1995): * pulled manual settings out of conf.h to settings.h. * Added error-dump token for dumping-core and continuing on errors. Version 3.0.7 (05/31/1995): * New release to fix some version problems. Version 3.0.6 (05/12/1995): * Added Web pointers to online documentation. * Added abort() auto-configuration for KILL_PROCESS. * Fixed problem with NEVER_REUSE and realloc same block-size. * Logged starting/ending time in logfile. * Added thread-id tracking with conf.h option. * Added pointer-count tracking with conf.h option. * Added interation-count tracking with conf.h option. * Added global/relative time tracking with conf.h option. * Better tag output from dmalloc -t. * New version of argv files. * Fixed problem with dmalloc -c and start-count. * Added some messages about upcoming errors in dmalloc_t. * Added allow-zero token for not minding malloc(0) and free(0L). * Made all chunk.c global counters longs. Version 3.0.5 (01/02/1995): * Fixed some old references to malloc in docs. Version 3.0.4 (12/15/1994): * Definitions for DMALLOC_PNT and DMALLOC_FREE_RET. * Removed all STRDUP and BDUP macros. Was anyone using them? * Added a "dying" message when _malloc_die is called. * Reworked the manual a ton. Added Quick-Start+Installation sections. Version 3.0.3 (11/03/1994): * Added dmalloc.cc C++ file to distribution. * Default is now to build/install a libdmalloclp.a library. * Removed the log-error tag. If logfile set then errors are logged. * Fixed problem with new args clearing all old ones. * Added dmalloc.h.2 creation to config.status file. * Added a startup message with the debug flags used to logfile. * Fixed errors with FUNC_CHECK code. * Added default tags: default,low,medium,high,all to dmalloc. * Renamed 'check-free' token to 'check-blank'. * Made many changes to make it easier to get running with dmalloc. * Added long(-L)/short(-S) options to output debug-tokens in env. * Changed some dmalloc options: * -T (list-tokens) -> -D (debug-tokens) * -L (list-tags) -> -t (list-tags) * Added better error logging in chunk. * Added DG/UX code to return.h and atexit.c to contrib. Version 3.0.2 (09/26/1994): * Fixed strtok error in dmallocrc file processing. * Fixed problems with env code when sprintf doesn't returns int. * Library now dumps the proper fence-bottom bytes on 1st pointer error. * Fixed casting problems on OSF. Version 3.0.1 (09/20/1994): * Combined all env variables into DMALLOC_OPTIONS. * Added -n flag to dmalloc program for printing/not-doing actions. * Fixed zsh and [t]csh alias messages in documentation. # Added mkinstalldirs and install.sh to distribution. * Renamed _dmalloc_error to dmalloc_error. * Removed time() and getpid() from compat functions. * Changed DMALLOC_DEBUG_DISABLE flag to DMALLOC_DISABLE. * Fixed some include file auto-include messages. Version 3.0.0 (09/08/1994): * Fixed a problem with some list checking. * Fixed possible recursion problem. * Tons of name changes going from malloc_dbg -> dmalloc. Version 2.2.1 (08/27/1994): * Small fix to malloc_dbg.3 to remove IMPORT's. Version 2.2.0 (08/08/1994): * Fixed xmalloc,xrealloc,etc. override functions. * Added xstrdup to the x override function list. * Added ability to combine adjacent free blocks into one. * 0 or negative MALLOC_INTERVAL values act as if no interval value. * Made a 'malloc_dbg -i 0' undefine MALLOC_INTERVAL. * Fixed calloc return-address problem. * Added KILL_PROCESS macro to configuration scripts. * Marty Leisner compiles library on MS-DOG! * Fixed some problems with malloc_errno set after call to error. Version 2.1.0 (05/11/1994): * Fixed problem with never-reuse going on/off and check-lists. * Added -r (random-debug) option to malloc_t. * Fixed nasty bug in realloc with alloc-blank + no realloc-copy token. * Fixed problem with ANSI-C configure on AIX systems. * Fixed some race conditions with sbrk failure. * Added -p max-pointers argument to malloc_t. * Added 'log-nonfree-space' token for logging unfreed memory space. * Added iteration count label to all logfile output. See conf.h. * Added xmalloc,xrealloc,etc. override functions. * Added better mechanisms for const definition. * Lots of install, notes, misc. changes. * Renamed token 'log-perror' and 'print-perror' to '...-error'. Version 2.0.1 (02/27/1994): * Cleaned up a number of configure/compat functions. * Fixed tons of __STDC__ defines. Finally I hope. * Added more commands to malloc_t to log information, etc. Version 2.0.0 (02/18/1994): * Lots of changes to add argv files in place of argv subdir. * Added initial support for external block locating. * Added 'allow-nonlinear' token to remove special checks. * Renamed dbg_tokens.h -> debug_tok.h and dbg_values.h -> debug_val.h * Added -V option to malloc_dbg and desc field for debug-token list. * Added a debugging section to the manual. * Added light and heavy makefile targets for automatic testing. * Much improved heap code with per-block allocations (not base 2). * Better free list management with block splitting. Version 1.3.6 (11/22/1993): * Fixed some compilation errors with non-STDC systems. Version 1.3.5 (11/22/1993): * More automatic and comprehensive malloc_t testing facilities. * Added -T (list-tokens) to malloc_dbg: for listing of debug tokens. * Added 'never-reuse' token to never reuse free'd memory. * Added on_exit and atexit support to auto-call malloc_shutdown. * Added hooks to all malloc utility functions to malloc_lp.o. * Removed debug token log-ra since log-unknown should be enough. * malloc_heap_map() -> malloc_log_heap_map() for consistency. * Added malloc_log_unfreed() to dump non-free memory to logfile. * Added -m (minus) option to malloc_dbg to allow removing of tokens. * Added -p flag to malloc_dbg to allow adding of tokens to debug value. * Added DEBUG_LOG_STAMP to add timestamps to log entries. * Added malloc_log_stats() to dump stats to a file. * Re-added cfree() call. No reason not to have it. Version 1.3.4 (09/26/1993): * Fixed compat function problems, added checks for -std1 cc flags. * Fixed debug messages to reflect reality. * Added malloc_debug_current and changed #if __STDC__ -> #ifdef * Removed log-bad-pnt. What an unnecessary token! Version 1.3.3 (09/20/1993): * Fixed configuration problems with memcpy/bcopy and memcmp/bcmp. * Added free's file/line to log_bad_pnt messages. * Renamed all error codes to ERROR_*. Version 1.3.2 (08/26/1993): * Removed MALLOC_TRACE and -t, replaced with MALLOC_ADDRESS:0. * Fixed some const problems. * Added ability of MALLOC_LOGFILE.%d for getpid Version 1.3.1 (08/24/1993): * Added 'log-ra' token to log return-address info (NOTE: later removed) * Added the beginnings of return-address handling * Added -L or --list to malloc_dbg to list all the rc-file tags. Version 1.3.0 (08/17/1993): * Added MALLOC_TRACE variable and malloc_dbg -t (NOTE: later removed) * Added some C++ from Peter Miller to the manual. * Removed LGPL and replaced it with fully free software notices. * _malloc_perror renamed to _malloc_error * Made malloc_address exported so it can be setable by debugger. * Added auto-sensing of shell by malloc_dbg and -C option. * Removed dblock checking tokens 'check-dblock-fence' + 'check-dblock'. Version 1.2.6 (07/13/1993): * Added 'catch-null' token for quitting as soon as we get sbrk failure. Version 1.2.5 (06/15/1993): * Added -r and -k options for auto-unsetting or keeping of variables. * Added 'log-bad-space' token and added expand_buf into chunk.c. * Create log_bad_pnt in chunk. Version 1.2.4 (05/13/1993): * Added -v option to malloc_dbg to provide verbose output. Version 1.2.3 (04/19/1993): * Renamed malloc.h to malloc_dbg.h and libmalloc.a to libmalloc_dbg.a. Version 1.2.2 (04/14/1993): * Added some more point checking tests to malloc_str. Version 1.2.1 (04/09/1993): * Changed to void * internally, put STDC defines in malloc.h for ANSI. * Made a number of changes per suggestions from the net. Version 1.2.0 (04/06/1993): * Uploaded to comp.sources.unix dmalloc-5.5.2/INSTALL000644 001751 001751 00000475211 10622115666 014156 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- 2.1 How to Install the Library ============================== To configure, compile, and install the library, follow these steps carefully. 1. Make sure you have downloaded the latest version of the library available from the home page at URL `http://dmalloc.com/'. 2. The release files have a `.tgz' file extension which means that they are a tar'd gzip'd directory of files. You will need to ungzip and then untar the release file into your source work directory. You may have to rename the file to `.tar.gz' to get some old zip programs to handle the file correctly. 3. You may want to edit or at least review the settings in `settings.dist' to tune specific features of the library. The `configure' script will copy this file to `settings.h' which is where you should be adding per-architecture settings. 4. Type `sh ./configure' to configure the library. You may want to first examine the `config.help' file for some information about configure. You may want to use the `--disable-cxx' option if you do not want the Makefile to build the C++ version of dmalloc. You may want to use the `--enable-threads' option to build the threaded version of dmalloc. You may want to use the `--enable-shlib' option to build the shared versions of the dmalloc libraries. `sh ./configure --help' lists the available options to configure. Configure should generate the `Makefile' and configuration files automatically. 5. You may want to examine the `Makefile' and `conf.h' files created by configure to make sure it did its job correctly. 6. You might want to tune the settings in `settings.h' file to tune the library to the local architecture. This file contains relevant settings if you are using pthreads or another thread library. *Note Using With Threads::. The `configure' script created this file from the `settings.dist' file. Any permanent changes to these settings should made to the `settings.dist' file. You then can run `config.status' to re-create the `settings.h' file. 7. The `DMALLOC_SIZE' variable gets auto-configured in `dmalloc.h.2' but it may not generate correct settings for all systems. You may have to alter the definitions in this file to get things to stop complaining when you go to compile about the size arguments to malloc routines. Comments on this please. 8. Typing `make' should be enough to build `libdmalloc.a', and `dmalloc' program. If it does not work, please see if there are any notes in the contrib directory about your system-type. If not and you figure your problem out, please send me some notes so future users can profit from your experiences. _NOTE_: You may experience some errors compiling some of the `return.h' assembly macros which attempt to determine the callers address for logging purposes. *Note Portability::. You may want to first try disabling any compiler optimization flags. If this doesn't work then you may need to disable the `USE_RETURN_MACROS' variable in the `settings.h' file. _NOTE_: The code is dependent on an ANSI-C compiler. If the configure script gives the `WARNING' that you do not have an ANSI-C compiler, you may still be able to add some sort of option to your compiler to make it ANSI. If there such is an option, please send it to the author so it can be added to the configure script. 9. If you use threads and did not add the `--enable-threads' argument to configure, typing `make threads' should be enough to build `libdmallocth.a' which is the threaded version of the library. This may or may not work depending on the configuration scripts ability to detect your local thread functionality. Feel free to send me mail with improvements. See the section of the manual on threads for more information about the operation of the library with your threaded program. *Note Using With Threads::. 10. If you have a C++ compiler installed, the library should have automatically built `libdmallocxx.a' which is the C++ version of the library. If it was not done automatically, you can build it by typing `make cxx'. You should link this library into your C++ programs instead of `libdmalloc.a'. See the `dmallocc.cc' C++ file which contains basic code to overload the `new', `new[]', `delete', and `delete[]' C++ operators. My apologies on the minimal C++ support. I am still living in a mostly C world. Any help improving this interface without sacrificing portability would be appreciated. 11. Typing `make light' should build and run the `dmalloc_t' test program through a set of light trials. By default this will execute `dmalloc_t' 5 times - each time will execute 10,000 malloc operations in a very random manner. Anal folks can type `make heavy' to up the ante. Use `dmalloc_t --usage' for the list of all `dmalloc_t' options. 12. Typing `make install' should install the `libdmalloc.a' library in `/usr/local/lib', the `dmalloc.h' include file in `/usr/local/include', and the `dmalloc' utility in `/usr/local/bin'. You may also want to type `make installth' to install the thread library into place and/or `make installcc' to install the C++ library into place. You may have specified a `--prefix=PATH' option to configure in which case `/usr/local' will have been replaced with `PATH'. See the "Getting Started" section to get up and running with the library. *Note Getting Started::. ------------------------------------------------------------------------------- 2.2 Getting Started with the Library ==================================== This section should give you a quick idea on how to get going. Basically, you need to do the following things to make use of the library: 1. Make sure you have downloaded the latest version of the library available from the home page at URL `http://dmalloc.com/'. 2. Follow the installation instructions on how to configure, make, and install the library (i.e. type: `make install'). *Note Installation::. 3. You need to make sure that the library configuration and build process above was able to locate one of the `on_exit' function, `atexit' function, or had compiler destructor support. If one of these functions or support is available then the dmalloc library should be able to automatically shut itself down when the program exits. This causes the memory statistics and unfreed information to be dumped to the log file. However, if your system has none of the above, then you will need to call `dmalloc_shutdown' yourself before your program exits. 4. To get the dmalloc utility to work you need to add an alias for dmalloc to your shell's runtime configuration file if supported. The idea is to have the shell capture the dmalloc program's output and adjust the environment. After you add the alias to the shell config file you need to log out and log back in to have it take effect, or you can execute the appropriate command below on the command line directly. After you setup the alias, if you enter `dmalloc runtime' and see any output with DMALLOC_OPTIONS in it then the alias did not take effect. Bash, ksh, and zsh (`http://www.zsh.org/') users should add the following to their `.bashrc', `.profile', or `.zshrc' file respectively (notice the `-b' option for bourne shell output): function dmalloc { eval `command dmalloc -b $*`; } If your shell does not support the `command' function then try: function dmalloc { eval `\dmalloc -b $*`; } or function dmalloc { eval `/usr/local/bin/dmalloc -b $*`; } If you are still using csh or tcsh, you should add the following to your `.cshrc' file (notice the `-C' option for c-shell output): alias dmalloc 'eval `\dmalloc -C \!*`' If you are using rc shell, you should add the following to your `.rcrc' file (notice the `-R' option for rc-shell output): fn dmalloc {eval `{/usr/local/bin/dmalloc $*}} 5. Although not necessary, you may want to include `dmalloc.h' in your C files and recompile. This will allow the library to report the file/line numbers of calls that generate problems. *Note Allocation Macros::. It should be inserted at the _bottom_ of your include files as to not conflict with wother includes. You may want to ifdef it as well and compile with `cc -DDMALLOC ...': /* other includes above ^^^ */ #ifdef DMALLOC #include "dmalloc.h" #endif 6. Another optional task is to compile all of your source with the `dmalloc.h' with the `DMALLOC_FUNC_CHECK' compilation flag. This willallow the library to check all of the arguments of a number of common string and utility routines. *Note Argument Checking::. cc -DDMALLOC -DDMALLOC_FUNC_CHECK file.c 7. Link the dmalloc library into your program. The dmalloc library should probably be placed at or near the end of the library list. 8. Enable the debugging features by typing `dmalloc -l logfile -i 100 low' (for example). You should not see any messages printed by the dmalloc utility (see NOTE below). This will: * Set the malloc logfile name to `logfile' (`-l logfile'). For programs which change directories, you may want to specify the full path to your logfile. * Have the library check itself every 100 iterations (`-i 100'). This controls how fast your program will run. Larger numbers check the heap less and so it will run faster. Lower numbers will be more likely to catch memory problems. * Enable a number of debug features (`low'). You can also try `runtime' for minimal checking or `medium' or `high' for more extensive heap verification. * By default, the low, medium, and high values enable the `error-abort' token which will cause the library to abort and usually dump core immediately upon seeing an error. *Note Dumping Core::. You can disable this feature by entering `dmalloc -m error-abort' (-m for minus) to remove the `error-abort' token and your program will just log errors and continue. `dmalloc --usage' will provide verbose usage info for the dmalloc program. *Note Dmalloc Program::. You may also want to install the `dmallocrc' file in your home directory as `.dmallocrc'. This allows you to add your own combination of debug tokens. *Note RC File::. _NOTE_: The output from the dmalloc utility should be captured by your shell. If you see a bunch of stuff which includes the string `DMALLOC_OPTIONS' then the alias you should have created above is not working and he environmental variables are not being set. Make sure you've logged out and back in to have the alias take effect. 9. Run your program, examine the logfile that should have been created by `dmalloc_shutdown', and use its information to help debug your program. File: dmalloc.info, Node: Allocation Basics, Next: Features, Prev: Getting Started, Up: Overview 2.3 Basic Description of Terms and Functions ============================================ * Menu: * Basic Definitions:: General memory terms and concepts. * Malloc Functions:: Functionality supported by all malloc libs. File: dmalloc.info, Node: Basic Definitions, Next: Malloc Functions, Prev: Allocation Basics, Up: Allocation Basics 2.3.1 General Memory Terms and Concepts --------------------------------------- Any program can be divided into 2 logical parts: text and data. Text is the actual program code in machine-readable format and data is the information that the text operates on when it is executing. The data, in turn, can be divided into 3 logical parts according to where it is stored: "static", "stack", and "heap". Static data is the information whose storage space is compiled into the program. /* global variables are allocated as static data */ int numbers[10]; main() { ... } Stack data is data allocated at runtime to hold information used inside of functions. This data is managed by the system in the space called stack space. void foo() { /* this local variable is stored on the stack */ float total; ... } main() { foo(); } Heap data is also allocated at runtime and provides a programmer with dynamic memory capabilities. main() { /* the address is stored on the stack */ char * string; ... /* * Allocate a string of 10 bytes on the heap. Store the * address in string which is on the stack. */ string = (char *)malloc(10); ... /* de-allocate the heap memory now that we're done with it */ (void)free(string); ... } It is the heap data that is managed by this library. Although the above is an example of how to use the malloc and free commands, it is not a good example of why using the heap for runtime storage is useful. Consider this: You write a program that reads a file into memory, processes it, and displays results. You would like to handle files with arbitrary size (from 10 bytes to 1.2 megabytes and more). One problem, however, is that the entire file must be in memory at one time to do the calculations. You don't want to have to allocate 1.2 megabytes when you might only be reading in a 10 byte file because it is wasteful of system resources. Also, you are worried that your program might have to handle files of more than 1.2 megabytes. A solution: first check out the file's size and then, using the heap-allocation routines, get enough storage to read the entire file into memory. The program will only be using the system resources necessary for the job and you will be guaranteed that your program can handle any sized file. File: dmalloc.info, Node: Malloc Functions, Prev: Basic Definitions, Up: Allocation Basics 2.3.2 Functionality Supported by All Malloc Libraries ----------------------------------------------------- All malloc libraries support 4 basic memory allocation commands. These include "malloc", "calloc", "realloc", and "free". For more information about their capabilities, check your system's manual pages - in unix, do a `man 3 malloc'. -- Function: void *malloc ( unsigned int SIZE ) Usage: `pnt = (type *)malloc(size)' The malloc routine is the basic memory allocation routine. It allocates an area of `size' bytes. It will return a pointer to the space requested. -- Function: void *calloc ( unsigned int NUMBER, unsigned intSIZE ) Usage: `pnt = (type *)calloc(number, size)' The calloc routine allocates a certain `number' of items, each of `size' bytes, and returns a pointer to the space. It is appropriate to pass in a `sizeof(type)' value as the size argument. Also, calloc nulls the space that it returns, assuring that the memory is all zeros. -- Function: void *realloc ( void *OLD_PNT, unsigned int NEW_SIZE ) Usage: `new_pnt = (type *)realloc(old_pnt, new_size)' The realloc function expands or shrinks the memory allocation in `old_pnt' to `new_size' number of bytes. Realloc copies as much of the information from `old_pnt' as it can into the `new_pnt' space it returns, up to `new_size' bytes. If there is a problem allocating this memory, 0L will be returned. If the `old_pnt' is 0L then realloc will do the equivalent of a `malloc(new_size)'. If `new_size' is 0 and `old_pnt' is not 0L, then it will do the equivalent of `free(old_pnt)' and will return 0L. -- Function: void free ( void *PNT ) Usage: `free(pnt)' The free routine releases allocation in `pnt' which was returned by malloc, calloc, or realloc back to the heap. This allows other parts of the program to re-use memory that is not needed anymore. It guarantees that the process does not grow too big and swallow a large portion of the system resources. _WARNING_: there is a quite common myth that all of the space that is returned by malloc libraries has already been cleared. _Only_ the `calloc' routine will zero the memory space it returns. File: dmalloc.info, Node: Features, Next: How It Works, Prev: Allocation Basics, Up: Overview 2.4 General Features of the Library =================================== The debugging features that are available in this debug malloc library can be divided into a couple basic classifications: file and line number information One of the nice things about a good debugger is its ability to provide the file and line number of an offending piece of code. This library attempts to give this functionality with the help of "cpp", the C preprocessor. *Note Allocation Macros::. return-address information To debug calls to the library from external sources (i.e. those files that could not use the allocation macros), some facilities have been provided to supply the caller's address. This address, with the help of a debugger, can help you locate the source of a problem. *Note Return Address::. fence-post (i.e. bounds) checking "Fence-post" memory is the area immediately above or below memory allocations. It is all too easy to write code that accesses above or below an allocation - especially when dealing with arrays or strings. The library can write special values in the areas around every allocation so it will notice when these areas have been overwritten. *Note Fence-Post Overruns::. _NOTE_: The library cannot notice when the program _reads_ from these areas, only when it writes values. Also, fence-post checking will increase the amount of memory the program allocates. heap-constancy verification The administration of the library is reasonably complex. If any of the heap-maintenance information is corrupted, the program will either crash or give unpredictable results. By enabling heap-consistency checking, the library will run through its administrative structures to make sure all is in order. This will mean that problems will be caught faster and diagnosed better. The drawback of this is, of course, that the library often takes quite a long time to do this. It is suitable to enable this only during development and debugging sessions. _NOTE_: the heap checking routines cannot guarantee that the tests will not cause a segmentation-fault if the heap administration structures are properly (or improperly if you will) overwritten. In other words, the tests will verify that everything is okay but may not inform the user of problems in a graceful manner. logging statistics One of the reasons why the debug malloc library was initially developed was to track programs' memory usage - specifically to locate "memory leaks" which are places where allocated memory is never getting freed. *Note Memory Leaks::. The library has a number of logging capabilities that can track un-freed memory pointers as well as runtime memory usage, memory transactions, administrative actions, and final statistics. examining freed memory Another common problem happens when a program frees a memory pointer but goes on to use it again by mistake. This can lead to mysterious crashes and unexplained problems. To combat this, the library can write special values into a block of memory after it has been freed. This serves two purposes: it will make sure that the program will get garbage data if it trying to access the area again, and it will allow the library to verify the area later for signs of overwriting. If any of the above debugging features detect an error, the library will try to recover. If logging is enabled then an error will be logged with as much information as possible. The error messages that the library displays are designed to give the most information for developers. If the error message is not understood, then it is most likely just trying to indicate that a part of the heap has been corrupted. The library can be configured to quit immediately when an error is detected and to dump a core file or memory-image. This can be examined with a debugger to determine the source of the problem. The library can either stop after dumping core or continue running. *Note Dumping Core::. _NOTE_: do not be surprised if the library catches problems with your system's routines. It took me hours to finally come to the conclusion that the localtime call, included in SunOS release 4.1, overwrites one of its fence-post markers. File: dmalloc.info, Node: How It Works, Prev: Features, Up: Overview 2.5 How the Library Checks Your Program ======================================= This is one of the newer sections of the library implying that it is incomplete. If you have any questions or issues that you'd like to see handled here, please let me know. The dmalloc library replaces the heap library calls normally found in your system libraries with its own versions. When you make a call to malloc (for example), you are calling dmalloc's version of the memory allocation function. When you allocate memory with these functions, the dmalloc library keeps track of a number of pieces of debugging information about your pointer including: where it was allocated, exactly how much memory was requested, when the call was made, etc.. This information can then be verified when the pointer is freed or reallocated and the details can be logged on any errors. Whenever you reallocate or free a memory address, the dmalloc library always performs a number of checks on the pointer to make sure that it is valid and has not been corrupted. You can configure the library to perform additional checks such as detected fence-post writing. The library can also be configured to overwrite memory with non-zeros (only if calloc is not called) when it is allocated and erase the memory when the pointers are freed. In addition to per-pointer checks, you can configure the library to perform complete heap checks. These complete checks verify all internal heap structures and include walking all of the known allocated pointers to verify each one in turn. You need this level of checking to find random pointers in your program which got corrupted but that won't be freed for a while. To turn on these checks, you will need to enable the `check-heap' debug token. *Note Debug Tokens::. By default this will cause the heap to be fully checked each and every time dmalloc is called whether it is a malloc, free, realloc, or another dmalloc overloaded function. Performing a full heap check can take a good bit of CPU and it may be that you will want to run it sporadically. This can be accomplished in a couple different ways including the '-i' interval argument to the dmalloc utility. *Note Dmalloc Program::. This will cause the check to be run every N-th time. For instance, 'dmalloc -i 3' will cause the heap to be checked before every 3rd call to a memory function. Values of 100 or even 1000 for high memory usage programs are more useful than smaller ones. You can also cause the program to start doing detailed heap checking after a certain point. For instance, with 'dmalloc -s 1000' option, you can tell the dmalloc library to enable the heap checks after the 1000th memory call. Examine the dmalloc log file produced and use the iteration count if you have `LOG_ITERATION_COUNT' enabled in your `settings.h' file. The start option can also have the format `file:line'. For instance, if it is set to `dmalloc_t.c:126', dmalloc will start checking the heap after it sees a dmalloc call from the `dmalloc_t.c' file, line number 126. If you use `dmalloc_t.c:0', with a 0 line number, then dmalloc will start checking the heap after it sees a call from anywhere in the `dmalloc_t.c' file. File: dmalloc.info, Node: Programming, Next: Dmalloc Program, Prev: Overview, Up: Top 3 How to Program with the Library ********************************* * Menu: * Allocation Macros:: Macros providing file and line information. * Return Address:: Getting caller address information. * Argument Checking:: Checking of function arguments. * Dumping Core:: Generating a core file on errors for debugging. * Extensions:: Additional non-standard routines. * Error Codes:: Description of the internal error numbers. * Disabling the Library:: How to disable the library. * Using With C++:: Using the library with C++. * Using With a Debugger:: Using a debugger with the library. * Using With Threads:: Using the library with a thread package. * Using With Cygwin:: Using the library with Cygwin environment. * Debugging A Server:: Debugging memory in a server or cgi-bin process. * Logfile Details:: Explanation of the Logfile Output. * Other Hints:: Various other hints that may help. File: dmalloc.info, Node: Allocation Macros, Next: Return Address, Prev: Programming, Up: Programming 3.1 Macros Providing File and Line Information ============================================== By including `dmalloc.h' in your C files, your calls to malloc, calloc, realloc, recalloc, memalign, valloc, strdup, and free are replaced with calls to _dmalloc_malloc, _dmalloc_realloc, and _dmalloc_free with various flags. Additionally the library replaces calls to xmalloc, xcalloc, xrealloc, xrecalloc, xmemalign, xvalloc, xstrdup, and xfree with associated calls. These macros use the c-preprocessor `__FILE__' and `__LINE__' macros which get replaced at compilation time with the current file and line-number of the source code in question. The routines use this information to produce verbose reports on memory problems. not freed: '0x38410' (22 bytes) from 'dmalloc_t.c:92' This line from a log file shows that memory was not freed from file `dmalloc_t.c' line 92. *Note Memory Leaks::. You may notice some non standard memory allocation functions in the above list. Recalloc is a routine like realloc that reallocates previously allocated memory to a new size. If the new memory size is larger than the old, recalloc initializes the new space to all zeros. This may or may not be supported natively by your operating system. Memalign is like malloc but should insure that the returned pointer is aligned to a certain number of specified bytes. Currently, the memalign function is not supported by the library. It defaults to returning possibly non-aligned memory for alignment values less than a block-size. Valloc is like malloc but insures that the returned pointer will be aligned to a page boundary. This may or may not be supported natively by your operating system but is fully supported by the library. Strdup is a string duplicating routine which takes in a null terminated string pointer and returns an allocated copy of the string that will need to be passed to free later to deallocate. The X versions of the standard memory functions (xmalloc, xfree, etc.) will print out an error message to standard error and will stop if the library is unable to allocate any additional memory. It is useful to use these routines instead of checking everywhere in your program for allocation routines returning NULL pointers. _WARNING_: If you are including the `dmalloc.h' file in your sources, it is recommended that it be at the end of your include file list because dmalloc uses macros and may try to change declarations of the malloc functions if they come after it. File: dmalloc.info, Node: Return Address, Next: Argument Checking, Prev: Allocation Macros, Up: Programming 3.2 Getting Caller Address Information ====================================== Even though the allocation macros can provide file/line information for some of your code, there are still modules which either you can't include `dmalloc.h' (such as library routines) or you just don't want to. You can still get information about the routines that call dmalloc function from the return-address information. To accomplish this, you must be using this library on one of the supported architecture/compilers. *Note Portability::. The library attempts to use some assembly hacks to get the return-address or the address of the line that called the dmalloc function. If you have unfreed memory that does not have associated file and line information, you might see the following non-freed memory messages. not freed: '0x38410' (22 bytes) from 'ra=0xdd2c' not freed: '0x38600' (10232 bytes) from 'ra=0x10234d' not freed: '0x38220' (137 bytes) from 'ra=0x82cc' With the help of a debugger, these return-addresses (or ra) can then be identified. I've provided a `ra_info.pl' perl script in the `contrib/' directory with the dmalloc sources which seems to work well with gdb. You can also use manual methods for gdb to find the return-address location. *Note Translate Return Addresses::. File: dmalloc.info, Node: Argument Checking, Next: Dumping Core, Prev: Return Address, Up: Programming 3.3 Checking of Function Arguments ================================== One potential problem with the library and its multitude of checks and diagnoses is that they only get performed when a dmalloc function is called. One solution this is to include `dmalloc.h' and compile your source code with the `DMALLOC_FUNC_CHECK' flag defined and enable the `check-funcs' token. *Note Debug Tokens::. cc -DDMALLOC -DDMALLOC_FUNC_CHECK file.c _NOTE_: Once you have compiled your source with DMALLOC_FUNC_CHECK enabled, you will have to recompile with it off to disconnect the library. *Note Disabling the Library::. _WARNING_: You should be sure to have `dmalloc.h' included at the end of your include file list because dmalloc uses macros and may try to change declarations of the checked functions if they come after it. When this is defined dmalloc will override a number of functions and will insert a routine which knows how to check its own arguments and then call the real function. Dmalloc can check such functions as `bcopy', `index', `strcat', and `strcasecmp'. For the full list see the end of `dmalloc.h'. When you call `strlen', for instance, dmalloc will make sure the string argument's fence-post areas have not been overwritten, its file and line number locations are good, etc. With `bcopy', dmalloc will make sure that the destination string has enough space to store the number of bytes specified. For all of the arguments checked, if the pointer is not in the heap then it is ignored since dmalloc does not know anything about it. File: dmalloc.info, Node: Dumping Core, Next: Extensions, Prev: Argument Checking, Up: Programming 3.4 Generating a Core File on Errors ==================================== If the `error-abort' debug token has been enabled, when the library detects any problems with the heap memory, it will immediately attempt to dump a core file. *Note Debug Tokens::. Core files are a complete copy of the program and it's state and can be used by a debugger to see specifically what is going on when the error occurred. *Note Using With a Debugger::. By default, the low, medium, and high arguments to the library utility enable the `error-abort' token. You can disable this feature by entering `dmalloc -m error-abort' (-m for minus) to remove the `error-abort' token and your program will just log errors and continue. You can also use the `error-dump' token which tries to dump core when it sees an error but still continue running. *Note Debug Tokens::. When a program dumps core, the system writes the program and all of its memory to a file on disk usually named `core'. If your program is called `foo' then your system may dump core as `foo.core'. If you are not getting a `core' file, make sure that your program has not changed to a new directory meaning that it may have written the core file in a different location. Also insure that your program has write privileges over the directory that it is in otherwise it will not be able to dump a core file. Core dumps are often security problems since they contain all program memory so systems often block their being produced. You will want to check your user and system's core dump size ulimit settings. The library by default uses the `abort' function to dump core which may or may not work depending on your operating system. If the following program does not dump core then this may be the problem. See `KILL_PROCESS' definition in `settings.dist'. main() { abort(); } If `abort' does work then you may want to try the following setting in `settings.dist'. This code tries to generate a segmentation fault by dereferencing a `NULL' pointer. #define KILL_PROCESS { int *_int_p = 0L; *_int_p = 1; } File: dmalloc.info, Node: Extensions, Next: Error Codes, Prev: Dumping Core, Up: Programming 3.5 Additional Non-standard Routines ==================================== The library has a number of variables that are not a standard part of most malloc libraries: -- Variable: int dmalloc_errno This variable stores the internal dmalloc library error number like errno does for the system calls. It can be passed to `dmalloc_strerror()' (see below) to get a string version of the error. It will have a value of zero if the library has not detected any problems. -- Variable: char* dmalloc_logpath This variable can be used to set the dmalloc log filename. The env variable `DMALLOC_LOGFILE' overrides this variable. Additionally the library provides a number of non-standard malloc routines: -- Function: void dmalloc_shutdown ( void ) This function shuts the library down and logs the final statistics and information especially the non-freed memory pointers. The library has code to support auto-shutdown if your system has the `on_exit()' call, `atexit()' call, or compiler destructor support (see `conf.h'). If you do not have these, then `dmalloc_shutdown' should be called right before `exit()' or as the last function in `main()'. main() { ... dmalloc_shutdown(); exit(0); } -- Function: int dmalloc_verify ( char * PNT ) This function verifies individual memory pointers that are suspect of memory problems. To check the entire heap pass in a NULL or 0 pointer. The routine returns DMALLOC_VERIFY_ERROR or DMALLOC_VERIFY_NOERROR. _NOTE_: `dmalloc_verify()' can only check the heap with the functions that have been enabled. For example, if fence-post checking is not enabled, `dmalloc_verify()' cannot check the fence-post areas in the heap. -- Function: unsigned-int dmalloc_debug ( const unsigned int FLAGS ) This routine sets the debug functionality flags and returns the previous flag value. It is helpful in server or cgi-bin programs where environmental variables cannot be used. *Note Debugging A Server::. For instance, if debugging should never be enabled for a program, a call to `dmalloc_debug(0)' as the first call in `main()' will disable all the memory debugging from that point on. _NOTE_: you cannot add or remove certain flags such as signal handlers since they are setup at initialization time only. _NOTE_: you can also use `dmalloc_debug_setup' below. -- Function: unsigned-int dmalloc_debug_current ( void ) This routine returns the current debug functionality value value. This allows you to save a copy of the debug dmalloc settings to be changed and then restored later. -- Function: void dmalloc_debug_setup ( const char * OPTIONS_STR ) This routine sets the global debugging functionality as an option string. Normally this would be passed in in the DMALLOC_OPTIONS environmental variable. This is here to override the env or for circumstances where modifying the environment is not possible or does not apply such as servers or cgi-bin programs. *Note Debugging A Server::. Some examples: /* * debug tokens high, threaded lock-on at 20, * log to dmalloc.%p (pid) */ dmalloc_debug_setup("debug=0x4f46d03,lockon=20,log=dmalloc.%p"); /* * turn on some debug tokens directly and log to the * file 'logfile' */ dmalloc_debug_setup( "log-stats,log-non-free,check-fence,log=logfile"); -- Function: int dmalloc_examine ( const DMALLOC_PNT PNT, DMALLOC_SIZE * USER_SIZE_P, DMALLOC_SIZE * TOTAL_SIZE_P, char ** FILE_P, int * LINE_P, DMALLOC_PNT * RET_ADDR_P, unsigned long * USER_MARK_P, unsigned long * SEEN_P ) This function returns the size of a pointer's allocation as well as the total size given including administrative overhead, file and line or the return-address from where it was allocated, the last pointer when the pointer was "used", and the number of times the pointer has been "seen". It will return DMALLOC_NOERROR or DMALLOC_ERROR depending on whether pnt is good or not. _NOTE_: This function is _certainly_ not provided by most if not all other malloc libraries. -- Function: void dmalloc_track ( const dmalloc_track_t TRACK_FUNC ) Register an allocation tracking function which will be called each time an allocation occurs. Pass in NULL to disable. To take a look at what information is provided, see the dmalloc_track_t function typedef in dmalloc.h. -- Function: unsigned-long dmalloc_mark ( void ) Return to the caller the current "mark" which can be used later to log the pointers which have changed since this mark with the `dmalloc_log_changed' function. Multiple marks can be saved and used. This is very useful when using the library with a server which does not exit. You can then save a mark before a transaction or event happens and then check to see what has changed using the `dmalloc_log_changed' function below. *Note Debugging A Server::. If you `LOG_ITERATION' enabled in your `settings.h' file then the entries in the log file will be prepended with the number of memory transactions that the library has handled so far. You can also enable `LOG_PNT_ITERATION' in `settings.h' to store the memory transaction number with each pointer. -- Function: unsigned-long dmalloc_memory_allocated ( void ) Return to the caller the total number of bytes that have been allocated by the library. This is not the current in use but the total number of bytes returned by allocation functions. -- Function: unsigned-int dmalloc_page_size ( void ) Return to the caller the memory page-size being used by the library. This should be the same value as the one returned by the `getpagesize()' function, if available. -- Function: unsigned-long dmalloc_count_changed ( const unsigned long MARK, const int NOT_FREED_B, const int FREE_B ) Count the pointers that have changed since the mark which was returned by `dmalloc_mark'. If `not_freed_b' is set to non-0 then count the pointers that have not been freed. If `free_b' is set to non-0 then count the pointers that have been freed. This can be used in conjunction with the `dmalloc_mark()' function to help servers which never exit ensure that transactions or events are not leaking memory. *Note Debugging A Server::. unsigned long mark = dmalloc_mark() ; ... assert(dmalloc_count_changed(mark, 1, 0) == 0) ; -- Function: void dmalloc_log_stats ( void ) This routine outputs the current dmalloc statistics to the log file. -- Function: void dmalloc_log_unfreed ( void ) This function logs the unfreed-memory information to the log file. This is also useful to log the currently allocated points to the log file to be compared against another dump later on. -- Function: void dmalloc_log_changed ( const unsigned long MARK, const int NOT_FREED_B, const int FREED_B, const int DETAILS_B ) Log the pointers that have changed since the mark which was returned by `dmalloc_mark'. If `not_freed_b' is set to non-0 then log the pointers that have not been freed. If `free_b' is set to non-0 then log the pointers that have been freed. If `details_b' set to non-0 then log the individual pointers that have changed otherwise just log the summaries. This can be used in conjunction with the `dmalloc_mark()' function to help servers which never exit find transactions or events which are leaking memory. *Note Debugging A Server::. -- Function: void dmalloc_vmessage ( const char * FORMAT, va_list ARGS ) Write a message into the dmalloc logfile using vprintf-like arguments. -- Function: void dmalloc_message ( const char * FORMAT, ... ) Write a message into the dmalloc logfile using printf-like arguments. -- Function: void dmalloc_get_stats ( DMALLOC_PNT * HEAP_LOW_P, DMALLOC_PNT * HEAP_HIGH_P, unsigned long * TOTAL_SPACE_P, unsigned long * USER_SPACE_P, unsigned long * CURRENT_ALLOCATED_P, unsigned long * CURRENT_PNT_NP, unsigned long * MAX_ALLOCATED_P, unsigned long * MAX_PNT_NP, unsigned long * MAX_ONE_P) This function return a number of statistics about the current heap. The pointers `heap_low_p' and `heap_high_p' will be set to the low and high spots in the heap. `total_space_p' will be set to the total space in the heap including user space, administrative space, and overhead. `user_space_p' will be set to the space given to the user process (allocated and free space). `current_allocated_p' will be set to the current allocated space given to the user process. `current_pnt_np' will be set to the current number of pointers allocated by the user process. `max_allocated_p' will be set to the maximum allocated space given to the user process. `max_pnt_np' will be set to the maximum number of pointers allocated by the user process. `max_on_p' will be set to the maximum space allocated with one call by the user process. -- Function: const-char* dmalloc_strerror ( const int ERROR_NUMBER ) This function returns the string representation of the error value in `error_number' (which probably should be dmalloc_errno). This allows the logging of more verbose memory error messages. You can also display the string representation of an error value by a call to the `dmalloc' program with a `-e #' option. *Note Dmalloc Program::. File: dmalloc.info, Node: Error Codes, Next: Disabling the Library, Prev: Extensions, Up: Programming 3.6 Description of the Internal Error Codes =========================================== The following error codes are defined in `error_val.h'. They are used by the library to indicate a detected problem. They can be caused by the user (`ERROR_TOO_BIG') or can indicate an internal library problem (`ERROR_SLOT_CORRUPT'). The `dmalloc' utility can give you the string version of the error with the `-e' argument: $ dmalloc -e 60 dmalloc: dmalloc_errno value '60' = 'pointer is not on block boundary' Here are the error codes set by the library. They are non contiguous on purpose because I add and delete codes all of the time and there are sections for various error-code types. `1 (ERROR_NONE) no error' No error. It is good coding practice to set the no-error code to be non-0 value because it forces you to set it explicitly. `2 (INVALID_ERROR)' Invalid error number. If the library outputs this error then your dmalloc utility may be out of date with the library you linked against. This will be returned with all error codes not listed here. `10 (ERROR_BAD_SETUP) initialization and setup failed' Bad setup value. This is currently unused but it is intended to report on invalid setup configuration information. `11 (ERROR_IN_TWICE) malloc library has gone recursive' Library went recursive. This usually indicates that you are not using the threaded version of the library. Or if you are then you are not using the `-o' "lock-on" option. *Note Using With Threads::. `13 (ERROR_LOCK_NOT_CONFIG) thread locking has not been configured' Thread locking has not been configured. This indicates that you attempted to use the `-o' "lock-on" option without linking with the thread version of the library. You should probably be using `-ldmallocth' _not_ `-ldmalloc' when you are linking. Or you should include `.../lib/libdmallocth.a' on your compilation line. `20 (ERROR_IS_NULL) pointer is null' Pointer is null. The program passed a NULL (0L) pointer to `free' and you have the `error-free-null' token enabled. `21 (ERROR_NOT_IN_HEAP) pointer is not pointing to heap data space' Pointer is not pointing to heap data space. This means that the program passed an out-of-bounds pointer to `free' or `realloc'. This could be someone trying to work with a wild pointer or trying to free a pointer from a different source than `malloc'. `22 (ERROR_NOT_FOUND) cannot locate pointer in heap' Cannot locate pointer in heap. The user passed in a pointer which the heap did not know about. Either this pointer was allocated by some other mechanism (like `mmap' or `sbrk' directly) or it is a random invalid pointer. In some rare circumstances, sometimes seen with shared libraries, there can be two separate copies of the dmalloc library in a program. Each one does not know about the pointers allocated by the other. `23 (ERROR_IS_FOUND) found pointer the user was looking for' This indicates that the pointer specified in the address part of the environmental variable was discovered by the library. *Note Environment Variable::. This error is useful so you can put a breakpoint in a debugger to find where a particular address was allocated. *Note Using With a Debugger::. `24 (ERROR_BAD_FILE) possibly bad .c filename pointer' A possibly invalid filename was discovered in the dmalloc administrative sections. This could indicate some corruption of the internal tables. It also could mean that you have a source file whose name is longer than 100 characters. See `MAX_FILE_LENGTH' in the `settings.dist' file. `25 (ERROR_BAD_LINE) possibly bad .c file line-number' A line-number was out-of-bounds in the dmalloc administrative sections. This could indicate some corruption of the internal tables. It also could mean that you have a source file containing more than `30000' lines of code. See `MAX_LINE_NUMBER' in the `settings.dist' file. `26 (ERROR_UNDER_FENCE) failed UNDER picket-fence magic-number check' This indicates that a pointer had its lower bound picket-fence magic number overwritten. If the `check-fence' token is enabled, the library writes magic values above and below allocations to protect against overflow. Most likely this is because a pointer below it went past its allocate and wrote into the next pointer's space. `27 (ERROR_OVER_FENCE) failed OVER picket-fence magic-number check' This indicates that a pointer had its upper bound picket-fence magic space overwritten. If the `check-fence' token is enabled, the library writes magic values above and below allocations to protect against overflow. Most likely this is because an array or string allocation wrote past the end of the allocation. Check for improper usage of `strcat', `sprintf', `strcpy', and any other functions which work with strings and do not protect themselves by tracking the size of the string. These functions should _always_ be replaced with: `strncat', `snprintf', `strncpy', and others. `28 (ERROR_WOULD_OVERWRITE) use of pointer would exceed allocation' This error is generated by the function pointer checking code usually enabled with the `check-funcs' token. Dmalloc overloads a number of string and memory copying functions and verifies that the buffers (if allocated in the heap) would not be overwritten by the function. `30 (ERROR_NOT_START_BLOCK) pointer is not to start of memory block' This indicates that the user passed in a pointer to be freed or reallocated that was not at the start of the allocation. You would get this error, for example, if you allocate and get pointer `X' but then try to free `X+1'. `40 (ERROR_BAD_SIZE) invalid allocation size' This error indicates that a size value in the internal structures of the library were corrupted. This could be a random pointer problem, pointer overflow, or some other corruption. `41 (ERROR_TOO_BIG) largest maximum allocation size exceeded' An allocation asked for memory larger than the configured maximum. This is a user configured setting. See `LARGEST_ALLOCATION' in the `settings.dist' file. It is used to protect against wild allocation sizes. If you have super large allocation sizes then you should tune the `LARGEST_ALLOCATION' value appropriately. `43 (ERROR_ALLOC_FAILED) could not grow heap by allocating memory' The library could not allocate more heap space and the program has run out of memory. This could indicate that you've overflowed some system imposed limit. On many operation systems, the `ulimit' call can tune system defaults. The library uses a lot more memory compared to the system malloc library because it stores a lot more information about the allocated pointers. _NOTE_: This also may be due to an inability of your operating system to use the `mmap' system call to allocate memory. You may need to force the `USE_MMAP' setting to be 0. Please use the forums at URL `http://dmalloc.com/' to report issues with this. `45 (ERROR_OVER_LIMIT) over user specified allocation limit' The library has allocated more memory than was specified in the memory-limit environmental variable. *Note Environment Variable::. `60 (ERROR_NOT_ON_BLOCK) pointer is not on block boundary' The user tried to free or realloc a pointer that was not pointing to a block boundary. You would get this error, for example, if you allocate and get pointer `X' but then try to free `X+1'. `61 (ERROR_ALREADY_FREE) tried to free previously freed pointer' The user tried to free a pointer than has already been freed. This is a very common mistake and can lead to serious problems. It can be because a destructor is being called twice for some reason. Although tracking down the specific source is highly recommended, it is good to set pointers to NULL (0L) after you free them as a rule. `67 (ERROR_FREE_OVERWRITTEN) free space has been overwritten' If either the `free-blank' or `check-blank' tokens are enabled then the library will overwrite memory when it is freed with the "dmalloc-free" byte (hex 0xdf, octal 0337, decimal 223). If the program writes into this space, then the library will detect the write and trigger this error. This could indicate that the program is using a pointer after it has been freed. `70 (ERROR_ADMIN_LIST) bad admin structure list' An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption. `72 (ERROR_ADDRESS_LIST) internal address list corruption' An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption. `73 (ERROR_SLOT_CORRUPT) internal memory slot corruption' An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption. File: dmalloc.info, Node: Disabling the Library, Next: Using With C++, Prev: Error Codes, Up: Programming 3.7 How to Disable the library ============================== If you would like to disable the library's detailed checking features during a particularly allocation intensive section of code, you can do something like the following: unsigned int dmalloc_flags; ... /* turn off all debug flags and save a copy of old value */ dmalloc_flags = dmalloc_debug(0); /* section of a lot of allocations */ ... /* end of section */ /* restore the dmalloc flag setting */ dmalloc_debug(dmalloc_flags); When you are finished with the development and debugging sessions, you may want to disable the dmalloc library and put in its place either the system's memory-allocation routines, gnu-malloc, or maybe your own. Attempts have been made to make this a reasonably painless process. The ease of the extraction depends heavily on how many of the library's features your made use of during your coding. Reasonable suggestions are welcome as to how to improve this process while maintaining the effectiveness of the debugging. * If you want to _totally_ disable the dmalloc library then you will need to recompile all the C files that include `dmalloc.h' while defining `DMALLOC_DISABLE'. This will cause the dmalloc macros to not be applied. *Note Allocation Macros::. cc -g -DDMALLOC_DISABLE file.c An alternative is to surround the `dmalloc.h' inclusion or any direct dmalloc references with an `#ifdef DMALLOC' and then just remove the -DDMALLOC. #ifdef DMALLOC #include "dmalloc.h" #endif main() { ... #ifdef DMALLOC dmalloc_verify(0L); #endif return 0; } // to get dmalloc information $ cc -DDMALLOC main.c // without dmalloc information $ cc main.c * If you compiled any of your source modules with `DMALLOC_FUNC_CHECK' defined then you must first recompile all those modules without the flag enabled. If you have disabled dmalloc with the `DMALLOC_DISABLED' flag or never included `dmalloc.h' in any of your C files, then you will not need to recompile your sources when you need to disable the library. If you get unresolved references like `_dmalloc_malloc' or `_dmalloc_bcopy' then something was not disabled as it should have been. File: dmalloc.info, Node: Using With C++, Next: Using With a Debugger, Prev: Disabling the Library, Up: Programming 3.8 Using the Library with C++ ============================== For those people using the C++ language, the library tries to configure and build `libdmallocxx.a' library. This library should be linked into your C++ programs instead of `libdmalloc.a'. Dmalloc is not as good with C++ as C because the dynamic memory routines in C++ are `new()' and `delete()' as opposed to `malloc()' and `free()'. Since new and delete are usually not used as functions but rather as `x = new type', there is no easy way for dmalloc to pass in file and line information unfortunately. The `libdmallocxx.a' library provides the file `dmallocc.cc' which effectively redirects `new' to the more familiar `malloc' and `delete' to the more familiar `free'. _NOTE_: The author is not a C++ hacker so feedback in the form of other hints and ideas for C++ users would be much appreciated. File: dmalloc.info, Node: Using With a Debugger, Next: Using With Threads, Prev: Using With C++, Up: Programming 3.9 Using Dmalloc With a Debugger ================================= Here are a number of possible scenarios for using the dmalloc library to track down problems with your program. You should first enable a logfile filename and turn on a set of debug features. You can use `dmalloc -l logfile low' to accomplish this. If you are interested in having the error messages printed to your terminal as well, enable the `print-messages' token by typing `dmalloc -p print-messages' afterwards. *Note Dmalloc Program::. Now you can enter your debugger (I use the _excellent_ GNU debugger gdb), and put a break-point in `dmalloc_error()' which is the internal error routine for the library. When your program is run, it will stop there if a memory problem is detected. If you are using GDB, I would recommend adding the contents of `dmalloc.gdb' in the `contrib' subdirectory to your `.gdbinit' file in your home directory. This enables the `dmalloc' command which will prompt you for the arguments to the dmalloc command and will set a break point in `dmalloc_error()' automatically. If you are using shared libraries, you may want to execute the following commands initially to load in dmalloc and other library symbols: (gdb) sharedlibrary (gdb) add-shared-symbol-files * Menu: * General Errors:: Diagnosing general problems with a debugger. * Memory Leaks:: Tracking down non-freed memory. * Fence-Post Overruns:: Diagnosing fence-post overwritten memory. * Translate Return Addresses:: Convert ra return-addresses into a location. File: dmalloc.info, Node: General Errors, Next: Memory Leaks, Prev: Using With a Debugger, Up: Using With a Debugger 3.9.1 Diagnosing General Problems with a Debugger ------------------------------------------------- If your program stops at the `dmalloc_error()' routine then one of a number of problems could be happening. Incorrect arguments could have been passed to a malloc call: asking for negative number of bytes, trying to realloc a non-heap pointer, etc.. There also could be a problem with the system's allocations: you've run out of memory, some other function in your program is using the heap allocation functions `mmap' or `sbrk', etc.. However, it is most likely that some code that has been executed was naughty. To get more information about the problem, first print via the debugger the dmalloc_errno variable to get the library's internal error code. You can suspend your debugger and run `dmalloc -e value-returned-from-print' to get an English translation of the error. A number of the error messages are designed to indicate specific problems with the library administrative structures and may not be user-friendly. If the problem was due to the arguments or system allocations then the source of the problem has been found. However, if some code did something wrong, you may have some more work to do to locate the actual problem. The `check-heap' token should be enabled and the interval setting disabled or set to a low value so that the library can find the problem as close as possible to its source. The code that was execute right before the library halted, can then be examined closely for irregularities. *Note Debug Tokens::, *Note Dmalloc Program::. You may also want to put calls to `dmalloc_verify(0)' in your code before the section which generated the error. This should locate the problem faster by checking the library's structures at that point. *Note Extensions::. File: dmalloc.info, Node: Memory Leaks, Next: Fence-Post Overruns, Prev: General Errors, Up: Using With a Debugger 3.9.2 Tracking Down Non-Freed Memory ------------------------------------ So you've run your program, examined the log-file and discovered (to your horror) some un-freed memory. Memory leaks can become large problems since even the smallest and most insignificant leak can starve the program given the right circumstances. not freed: '0x45008' (12 bytes) from 'ra=0x1f8f4' not freed: '0x45028' (12 bytes) from 'unknown' not freed: '0x45048' (10 bytes) from 'argv.c:1077' known memory not freed: 1 pointer, 10 bytes unknown memory not freed: 2 pointers, 24 bytes Above you will see a sample of some non-freed memory messages from the logfile. In the first line the `0x45008' is the pointer that was not freed, the `12 bytes' is the size of the unfreed block, and the `ra=0x1f8f4' or return-address shows where the allocation originated from. *Note Translate Return Addresses::. The systems which cannot provide return-address information show `unknown' instead, as in the 2nd line in the sample above. The `argv.c:1077' information from the 3rd line shows the file and line number which allocated the memory which was not freed. This information comes from the calls from C files which included `dmalloc.h'. *Note Allocation Macros::. At the bottom of the sample it totals the memory for you and breaks it down to known memory (those calls which supplied the file/line information) and unknown (the rest). Often, you may allocate memory in via `strdup()' or another routine, so the logfile listing where in the `strdup' routine the memory was allocated does not help locate the true source of the memory leak - the routine that called `strdup'. Without a mechanism to trace the calling stack, there is no way for the library to see who the caller of the caller (so to speak) was. However, there is a way to track down unfreed memory in this circumstance. You need to compile the library with `STORE_SEEN_COUNT' defined in `conf.h'. The library will then record how many times a pointer has been allocated or freed. It will display the unfreed memory as: not freed: '0x45008|s3' (12 bytes) from 'ra=0x1f8f4' The `STORE_SEEN_COUNT' option adds a `|s#' qualifier to the address. This means that the address in question was seen `#' many times. In the above example, the address `0x45008' was seen `3' times. The last time it was allocated, it was not freed. How can a pointer be "seen" 3 times? Let say you `strdup' a string of 12 characters and get address `0x45008' - this is #1 time the pointer is seen. You then free the pointer (seen #2) but later `strdup' another 12 character string and it gets the `0x45008' address from the free list (seen #3). So to find out who is allocating this particular 12 bytes the 3rd time, try `dmalloc -a 0x45008:3'. The library will stop the program the third time it sees the `0x45008' address. You then enter a debugger and put a break point at `dmalloc_error'. Run the program and when the breakpoint is reached you can examine the stack frame to determine who called `strdup' to allocate the pointer. To not bother with the `STORE_SEEN_COUNT' feature, you can also run your program with the `never-reuse' token enabled. This token will cause the library to never reuse memory that has been freed. Unique addresses are always generated. This should be used with caution since it may cause your program to run out of memory. File: dmalloc.info, Node: Fence-Post Overruns, Next: Translate Return Addresses, Prev: Memory Leaks, Up: Using With a Debugger 3.9.3 Diagnosing Fence-Post Overwritten Memory ---------------------------------------------- For a definition of fence-posts please see the "Features" section. *Note Features::. To detect fence-post overruns, you need to enable the `check-fence' token. *Note Debug Tokens::. This pads your allocations with some extra bytes at the front and the end and watches the space to make sure that they don't get overwritten. _NOTE:_ The library cannot detect if this space gets read, only written. If you have encountered a fence-post memory error, the logfile should be able to tell you the offending address. free: failed UNDER picket-fence magic-number checking: pointer '0x1d008' from 'dmalloc_t.c:427' Dump of proper fence-bottom bytes: '\e\253\300\300\e\253\300\300' Dump of '0x1d008'-8: '\e\253\300\300WOW!\003\001pforger\023\001\123' The above sample shows that the pointer `0x1d008' has had its lower fence-post area overwritten. This means that the code wrote below the bottom of the address or above the address right below this one. In the sample, the string that did it was `WOW!'. The library first shows you what the proper fence-post information should look like, and then shows what the pointer's bad information was. If it cannot print the character, it will display the value as `\ddd' where ddd are three octal digits. By enabling the `check-heap' debugging token and assigning the interval setting to a low number, you should be able to locate approximately when this problem happened. *Note Debug Tokens::, *Note Dmalloc Program::. File: dmalloc.info, Node: Translate Return Addresses, Prev: Fence-Post Overruns, Up: Using With a Debugger 3.9.4 Translating Return Addresses into Code Locations ------------------------------------------------------ The following gdb commands help you translate the return-addresses (ra=) entries in the logfile into locations in your code. I've provided a `ra_info.pl' perl script in the `contrib/' directory with the dmalloc sources which seems to work well with gdb. But, if you need to do it manually, here are the commands in gdb to use. # you may need to add the following commands to load in shared libraries (gdb) sharedlibrary (gdb) add-shared-symbol-files (gdb) x 0x10234d 0x10234d <_findbuf+132>: 0x7fffceb7 (gdb) info line *(0x82cc) Line 1092 of argv.c starts at pc 0x7540 and ends at 0x7550. In the above example, gdb was used to find that the two non-freed memory pointers were allocated in `_findbuf()' and in file argv.c line 1092 respectively. The `x address' (for examine) can always be used on the return-addresses but the `info line *(address)' will only work if that file was compiled using the `-g' option and has not been stripped. This limitation may not be true in later versions of gdb. File: dmalloc.info, Node: Using With Threads, Next: Using With Cygwin, Prev: Using With a Debugger, Up: Programming 3.10 Using the Library with a Thread Package ============================================ Threads are special operating system facilities which allow your programs to have multiple threads of execution (hence the name). In effect your program can be doing a number of things "at the same time". This allows you to take full advantage of modern operating system scheduling and multi-processor hardware. If I've already lost you or if any of the terminology below does not make sense, see manuals about POSIX threads (pthreads) before going any further. O'Reilly publishes a pretty good pthreads manual for example. To use dmalloc with your threaded program, you will first need to make sure that you are linking with `libdmallocth.a' which is the threaded version of the library. The support for threads in dmalloc should be adequate for most if not all testing scenarios. It provides support for mutex locking itself to protect against race conditions that result in multiple simultaneous execution. One of the major problems is that most thread libraries uses malloc themselves. Since all of dmalloc's initialization happens when a call to malloc is made, we may be attempting to initialize or lock the mutex while the thread library is booting up. A very bad thing since thread libraries don't expect to recurse. The solution to this problem is to have the library not initialize or lock its mutex variable until after a certain number of allocation calls have been completed. If the library does not wait before initializing the locks, the thread library will probably core dump. If it waits too long then it can't protect itself from multiple execution and it will abort or other bad things might happen. You adjust the number of times to wait at runtime with the `lock-on' option to the dmalloc program (for example `dmalloc -o 20'). *Note Dmalloc Program::. Times values between 5 and 30 are probably good although operating systems will vary significantly. You know its too low if your program immediately core dumps and too high if the dmalloc library says its gone recursive although with low values, you might get either problem. An additional complexity is when we are initializing the lock before mutex locking around the library. As mentioned, the initialization itself may generate a malloc call causing the library to go recursive and the pthread library to possibly core dump. With the THREAD_INIT_LOCK setting defined in `settings.h', you can tune how many times before we start locking to try and initialize the mutex lock. It defaults to 2 which seems to work for me. If people need to have this runtime configurable or would like to present an alternative default, please let me know. So to use dmalloc with a threaded program, follow the following steps carefully. 1. Follow the installation instructions on how to configure, make, and install the library but make sure to add the `--enable-threads' argument to configure. *Note Installation::. 2. Typing `make' should be enough to build the threaded versions of the libraries including `libdmallocth.a'. 3. Link the dmalloc threaded library into your program. The dmalloc library should probably be placed at or near the end of the library list. 4. Enable the debugging options that you need by typing `dmalloc -l logfile -i 100 low' (for example). `dmalloc --usage' will provide verbose usage info for the dmalloc program. *Note Dmalloc Program::. 5. Enable the "lock-on" option (for example `dmalloc -o 20'). As explained above, you may have to try different values before getting it right. Values between 5 and 30 are probably good. 6. If you get a dmalloc error #13 `thread locking has not been configured' then you have not compiled you program with the threaded version of dmalloc or there was a problem building it. 7. If everything works, you should be able to run your program, have it not immediately crash, and the dmalloc library should not complain about recursion. If you have any specific questions or would like addition information posted in this section, please let me know. Experienced thread programmers only please. File: dmalloc.info, Node: Using With Cygwin, Next: Debugging A Server, Prev: Using With Threads, Up: Programming 3.11 Using the library with Cygwin environment. =============================================== The Cygwin environment is a Linux-like environment for Windows. It provides Linux look and feel as well as a programming environment. See URL `http://www.cygwin.com/' for more details. Cygwin uses the `GetEnvironmentVariableA' function to read in environmental variables instead of `getenv'. This functions are used to get the value of the `DMALLOC_OPTIONS' variable which sets the debugging options. *Note Environment Variable::. As of right now, dmalloc is not detecting the `GetEnvironmentVariableA' function correctly so you may need to tune the `conf.h' file to get it to work. See the sections on `HAVE_GETENVIRONMENTVARIABLEA' and `GETENV_SAVE' settings. Feedback is welcome here. If you still have problems reading in the environmental variables, you can work around this issue. You can add some code into the `main' function in your program to initialize the dmalloc flags yourself. Here is a code sample: main(int argc, char **argv) { #ifdef DMALLOC /* * Get environ variable DMALLOC_OPTIONS and pass the settings string * on to dmalloc_debug_setup to setup the dmalloc debugging flags. */ dmalloc_debug_setup(getenv("DMALLOC_OPTIONS")); #endif /* rest of code in main starts here */ ... } The `#ifdef' is just a good idea. I means that when debugging with dmalloc you need to compile your code with `-DDMALLOC'. When you are done debugging you can remove the flag and the call to `dmalloc_debug_setup' will be removed. Please let me know if there is a better way to do this. File: dmalloc.info, Node: Debugging A Server, Next: Logfile Details, Prev: Using With Cygwin, Up: Programming 3.12 Debugging Memory in a Server or Cgi-Bin Process ==================================================== There are some specified challenges when trying to debug allocations in processes which do not startup, run, and then shutdown. Server processes (often called daemons) are those that are started (often at system boot time) and run perpetually. Other processes which are difficult to debug are CGI programs which are spawned by web servers or when you want to start debugging inside of a child process. 1. Build your server or cgi-bin program with the dmalloc library like any other program. *Note Getting Started::. 2. Add code into your program to enable the library flags to perform the memory checks that you require. Since these programs often do not run from the command line, you cannot use the dmalloc utility program and modify the process environment. *Note Dmalloc Program::. The library provides a couple of functions to set the debugging flags when a program is running. 3. To set the memory debugging flags, use the `dmalloc_debug_setup' function which takes a string in the same format of the `DMALLOC_OPTIONS' environmental variable. *Note Environment Variable::. Use the dmalloc utility with the `-n' no-changes argument to see the appropriate settings for the `DMALLOC_OPTIONS' environmental variable. > dmalloc -n -l logfile high Outputed: DMALLOC_OPTIONS=debug=0x4f4ed03,log=logfile export DMALLOC_OPTIONS So if you want to turn on `high' debugging and log to the file `logfile' then you would copy the above `DMALLOC_OPTIONS' value into a call to `dmalloc_debug_setup'. Notice that I have surrounded the dmalloc code with an `#ifdef DMALLOC' so you'll have to compile using the `-DDMALLOC' flag. main() { #ifdef DMALLOC /* set the 'high' flags */ dmalloc_debug_setup("debug=0x4f47d03,log=logfile"); #endif ... } _Please note_ that the `dmalloc_debug_setup' function does not know about `high', `low', or other debug tokens but needs the actual flag values. 4. For earlier versions of the library (before 5.0.0) without `dmalloc_debug_setup', the `dmalloc_debug' function is available to set the flags directly, but it cannot adjust the logfile name and the other environment settings. You can use the dmalloc utility program to see what the numerical equivalent of the `high' token. > dmalloc -n high Outputed: DMALLOC_OPTIONS=debug=0x4f4ed03 export DMALLOC_OPTIONS You can then take the `0x4f4ed03' hexadecimal number and call `dmalloc_debug' with that number. main() { #ifdef DMALLOC /* set the 'high' flags */ dmalloc_debug(0x4f4ed03); #endif ... } 5. Even with the settings enabled, you may have problems getting the logfile to be written if your program is running as `nobody' or another user without permissions for security reasons. This is especially true for cgi-bin programs. In this case you should specify a full path to your malloc logfile in a world writable directory (ex. `dmalloc_debug_setup("debug=0x4f47d03,log=/var/tmp/malloc");'). Watch for programs which change into other directories and which may cause logfiles specified as relative or local paths to be dropped in other locations. You may always want to use a full path logfile. 6. Once you have your settings enabled and your log is being generated, you may now want to check out how your process is doing in terms of unfreed memory. Since it is not shutting down, the automatic unfreed log entries are not being dropped to the logfile. By using the `dmalloc_mark' and `dmalloc_log_changed' functions, you can set a mark point at a certain place inside of your program, and then later see whether there are any unfreed pointers since the mark. main() { #ifdef DMALLOC /* set the 'high' flags */ dmalloc_debug_setup("debug=0x4f47d03,log=logfile"); #endif while (1) { /* accept a connection from a client */ accept_connection(); while (1) { #ifdef DMALLOC unsigned long mark; /* get the current dmalloc position */ mark = dmalloc_mark() ; #endif /* process the connection */ if (process_connection() != PROCESS_OK) { break; } #ifdef DMALLOC /* * log unfreed pointers that have been added to * the heap since mark */ dmalloc_log_changed(mark, 1 /* log unfreed pointers */, 0 /* do not log freed pointers */, 1 /* log each pnt otherwise summary */); #endif } /* close the connection with the client */ close_connection(); } ... } Usually you would set the mark after the initializations and before each transaction is processed. Then for each transaction you can use `dmalloc_log_changed' to show the unfreed memory. *Note Extensions::. 7. You can also use the `dmalloc_log_stats' function to dump general information about the heap. Also, remember that you can use the `dmalloc_message' and `dmalloc_vmessage' routines to annotate the dmalloc logfile with details to help you debug memory problems. *Note Extensions::. File: dmalloc.info, Node: Logfile Details, Next: Other Hints, Prev: Debugging A Server, Up: Programming 3.13 Explanation of the Logfile Output ====================================== Most of time you will be using the logfile output from library as the sole information source for diagnosing problems in and getting statistics for your program. 1098918225: 3: Dmalloc version 'Version 5.5.2' 1098918225: 3: flags = 0x4f4e503, logfile '/tmp/dmalloc.log' 1098918225: 3: interval = 500, addr = 0, seen # = 0, limit = 0 1098918225: 3: starting time = 1098918225 1098918225: 3: process pid = 32406 1098918226: 4: WARNING: tried to free(0) from foo.c:708' 1098918228: 20: *** free: at 'unknown' pnt '0xed310080|s2': \ size 12, alloced at 'bar.c:102' 1098918230: 50: ERROR: heap_check: free space was overwritten (err 67) 1098918230: 50: error details: checking free pointer 1098918230: 50: pointer '0x291c5' from 'unknown' prev access 'foo.c:787' Here is a short example of some logfile information. Each of the lines are prefixed by the time (in epoch seconds since 1/1/1970) and the iteration or call count which is the number of times the library has been called from malloc, free, verify, etc.. In the above example, the first 5 log entries where written at epoch 1098918225 or `Wed Oct 27 19:03:45 2004 EST' and they were generated by the 3rd call to the library. See the `settings.dist' file entries to tune what elements appear on each line: LOG_TIME_NUMBER, LOG_ITERATION, LOG_PID, etc.. You can convert the epoch seconds to a date from the command line with the following perl code: `perl -e 'print localtime($ARGV[0])."\n";' epoch-seconds-number' The first 5 lines of the sample logfile contain header information for all logfiles. They show the version number and URL for the library as well as all of the settings that the library is currently using. These settings are tuned using the dmalloc utility program. *Note Dmalloc Program::. The 5th line of is the process-id that generated the logfile. The 6th line in the above example is what causes the logfile to be opened and the header to be written. It is a warning that tells you that you tried to free a 0L pointer at a certain location. You can disable these warnings by setting `ALLOW_FREE_NULL_MESSAGE' to 0 in `settings.dist'. Line 7 is an example of a transaction log that you get when you enable the `log-trans' debug token. *Note Debug Tokens::. This line shows that a call to free was made from an unknown location. It is unknown because the file in question did not include `dmalloc.h' to get file/line-number information. The call to free was freeing the pointer address `0xed310080' which we have "seen" 2 times (s2). We saw the pointer when it was allocated and then we are seeing it again when it was freed. Because the library is reusing pointers (reclaiming freed memory) the seen count helps to track how many times a pointer was used. The last part of the line shows that the pointer to be freed was allocated by `bar.c' line 102. Lines 8-10 is the next problem that the library caught and this one is an error. It happened 5 seconds from the start of the log (1098918230) and at the 50th call into the library. It shows that an allocation that had been freed then was overwritten. This may imply that someone tried to use memory after it was freed or that there was a loose pointer reference. The last two lines give more details about when the error was discovered, the address of the offending pointer, and when the pointer was previous accessed, in this case freed. To discover where this problem is happening, you can use a debugger. *Note Using With a Debugger::. File: dmalloc.info, Node: Other Hints, Prev: Logfile Details, Up: Programming 3.14 Various Other Hints That May Help ====================================== One of the problems that is often seen is that a program crashes in the `libc' memory code and you suspect a heap memory problem but both dmalloc and maybe valgrind don't show any problems. One of the big problems with debugging is that it is very difficult to do it without effecting how the program is run. Sometimes errors are due to subtle race conditions that are only seen when the program is running at full speed - not slowed down by debugging code. This is especially true with threaded code which is often heavily affected when used with dmalloc and valgrind. Older versions of valgrid (maybe current) forced all threads into a single virtual system by design, which often masks reentrance bugs. One way to work through these issues is to run with the library with very few debugging flags enabled. Many memory problems are fence-post areas so start with dmalloc checking just the fence post and error logging enabled: dmalloc -d 0 -l dmalloc.log -p log-stats -p log-non-free -p check-fence -p check-funcs This enabled a small number of checks and should cause your program to run at close to full speed. The library has never been optimized for speed so some performance penalties will be felt. File: dmalloc.info, Node: Dmalloc Program, Next: Source Code, Prev: Programming, Up: Top 4 Dmalloc Utility Program ************************* The dmalloc program is designed to assist in the setting of the environment variable `DMALLOC_OPTIONS'. *Note Environment Variable::. It is designed to print the shell commands necessary to make the appropriate changes to the environment. Unfortunately, it cannot make the changes on its own so the output from dmalloc should be sent through the `eval' shell command which will do the commands. * Menu: * Shell Alias:: Using a shell alias with the utility. * Utility Usage:: How to use the dmalloc program. * Environment Variable:: Environment variable name and features. * Debug Tokens:: Description of the debugging tokens. * RC File:: Format of the runtime configuration file. File: dmalloc.info, Node: Shell Alias, Next: Utility Usage, Prev: Dmalloc Program, Up: Dmalloc Program 4.1 Using a Shell Alias with the Utility ======================================== The dmalloc program is designed to assist in the setting of the environment variable `DMALLOC_OPTIONS'. *Note Environment Variable::. It is designed to print the shell commands necessary to make the appropriate changes to the environment. Unfortunately, it cannot make the changes on its own so the output from dmalloc should be sent through the `eval' shell command which will do the commands. With shells that have aliasing or macro capabilities: csh, bash, ksh, tcsh, zsh, etc., setting up an alias to dmalloc to do the eval call is recommended. Bash, ksh, and zsh users should add the following to their `.bashrc', `.profile', or `.zshrc' file respectively (notice the `-b' option for bourne shell output): function dmalloc { eval `command dmalloc -b $*`; } If your shell does not support the `command' function then try: function dmalloc { eval `\dmalloc -b $*`; } or function dmalloc { eval `/usr/local/bin/dmalloc -b $*`; } If you are _still_ using csh or tcsh, you should add the following to your `.cshrc' file (notice the `-C' option for c-shell output): alias dmalloc 'eval `\dmalloc -C \!*`' This allows the user to execute the dmalloc command as `dmalloc arguments'. Users of versions of the Bourne shell (usually known as /bin/sh) that don't have command functions will need to send the output to a temporary file and the read it back in with the "." command: $ dmalloc -b arguments ... > /tmp/out $ . /tmp/out By the way, if you are looking for a shell, I heartily recommend trying out zsh. It is a bourne shell written from scratch with much the same features as tcsh without the csh crap. _NOTE_: After you add the alias to the file you need to log out and log back in to have it take effect, or you can execute the above appropriate command on the command line. If you enter `dmalloc runtime' and see any output with DMALLOC_OPTIONS in it then the alias did not work. File: dmalloc.info, Node: Utility Usage, Next: Environment Variable, Prev: Shell Alias, Up: Dmalloc Program 4.2 How to Use the Dmalloc Program ================================== The most basic usage for the program is `dmalloc [-bC] tag'. The `-b' or `-C' (either but not both flags used at a time) are for generating Bourne or C shell type commands respectively. dmalloc will try and use the `SHELL' environment variable to determine whether bourne or C shell commands should be generated but you may want to explicitly specify the correct flag. The `tag' argument to dmalloc should match a line from the user's runtime configuration file or should be one of the built-in tags. *Note RC File::. If no tag is specified and no other option-commands used, dmalloc will display the current settings of the environment variable. It is useful to specify one of the verbose options when doing this. To find out the usage for the debug malloc program try `dmalloc --usage-long'. The standardized usage message that will be displayed is one of the many features of the argv library included with this package. It is available on the web at URL `http://256.com/sources/argv/'. See the documentation there for more information. Here is a detailed list of the flags that can passed to dmalloc: `-a address' Set the `addr' part of the `DMALLOC_OPTIONS' variable to address (or alternatively address:number). `-b' Output Bourne shell type commands. Usually handled automagically. `-C' Output C shell type commands. Usually handled automagically. `-c' Clear/unset all of the settings not specified with other arguments. You can do this automatically when you set to a new tag with the `-r' option. _NOTE_: clear will never unset the `debug' setting. Use `-d 0' or a tag to `none' to achieve this. `-d bitmask' Set the `debug' part of the `DMALLOC_OPTIONS' env variable to the bitmask value which should be in hex. This is overridden (and unnecessary) if a tag is specified. `-D' List all of the debug-tokens. Useful for finding a token to be used with the `-p' or `-m' options. Use with `-v' or `-V' verbose options. `-e errno' Print the dmalloc error string that corresponds to the error number errno. `-f filename' Use this configuration file instead of the RC file `$HOME/.dmallocrc'. `-g' Output gdb type commands for using inside of the gdb debugger. `-h (or --help)' Output a help message for the utility. `-i number' Set the checking interval to number. If the `check-heap' token is enabled, this causes the library to only check the heap every Nth time which can _significantly_ increase the running speed of your program. If a problem is found, however, this limits your ability to determine when the problem occurred. Try values of 50 or 100 initially. `-k' Do not reset all of the settings when a tag is specified. This specifically overrides the `-r' option and is provided here to override `-r' if it has been added to the dmalloc alias. `-l filename' Write the debugging output and other log-file information to the filename. Filename can include some of the following patterns which get expanded into strings: `%h' Gets expanded into the hostname if the `gethostname()' function is available. `%i' Gets expanded into the thread-id if the library has been configure to be used with threads. *Note Using With Threads::. See the end of the `settings.dist' file for settings which return the thread-id and convert it into a string. `%p' Gets expanded into the process-id if the `getpid()' function is available. `%t' Gets expanded into the time value in seconds if the `time()' function is available. `%u' Gets expanded into the user-id number if the `getuid()' function is available. Some examples: # logfile produced with pid extension: # logfile.8412 or logfile.31451 dmalloc -l logfile.%p # hostname and time extensions: # dmalloc-box1.foo.com-1055213240 dmalloc -l dmalloc-%h-%t # if threads enabled, have thread-id extension: log.thread32 dmalloc -l log.thread%i `-L' Write the debug-value into the environment not in hex but by individual debug-tokens in long form. `-m token(s)' Remove (minus) the debug capabilities of token(s) from the current debug setting or from the selected tag (or `-d' value). Multiple `-m' options can be specified. `-M limit' Set the memory allocation limit which will abort the program if the total memory allocations exceed this number of bytes. The limit can be a number with a k, m, or g at the end to indicate kilobyte, megabyte, and gigabyte respectively. Ex: 100k, 200m, 1g. If the limit is exceeded, this will generate an `ERROR_OVER_LIMIT' error. *Note Error Codes::. `-n' Without changing the environment, output the commands resulting from the supplied options. `-o times' Set the "lock-on" period which dictates to the threaded version of the library to not initialize or lock the mutex lock around the library until after a certain number of allocation calls have been made. Some number between 2 and 30 is probably good. See the "Using With Threads" section for more information about the operation of the library with threads. *Note Using With Threads::. `-p token(s)' Add (plus) the debug capabilities of token(s) to the current debug setting or to the selected tag (or `-d' value). Multiple `-p' options can be specified. `-r' Remove (unset) all settings when using a tag. This is useful when you are returning to a standard development tag and want the logfile, address, and interval settings to be cleared automatically. If you want this behavior by default, this can be put into the dmalloc alias. `-R' Output rc shell type commands. This is not for the runtime configuration file but for the rc shell program. `-s file:line' Set the `start' part of the `DMALLOC_OPTIONS' env variable to a file-name and line-number location in the source where the library should begin more extensive heap checking. The file and line numbers for heap transactions must be working for this option to be obeyed. This is used if you are trying to locate a problem and you want the extensive checking to not happen initially because it's too slow. `-S number' Set the `start' part of the `DMALLOC_OPTIONS' env variable to an dmalloc mark number. The library will begin more extensive heap checking after this number of memory transactions. If you `LOG_ITERATION' enabled in your `settings.h' file then the entries in the log file will be prepended with the number of memory transactions that the library has handled so far. This number can be used to delay the start of the fine grained heap checking which can be very slow. `--start-size size' Set the `start' part of the `DMALLOC_OPTIONS' env variable to a number of bytes. The library will begin more extensive heap checking after this amount of memory has been allocated by the library. This allows you to start the slow and detailed checking of the library later in the program execution. You can use patterns like 250m, 1g, or 102k to mean 250 megabytes, 1 gigabyte, and 102 kilobytes respectively. `-t' List all of the tags in the rc-file. Use with `-v' or `-V' verbose options. `-u (or --usage)' Output the usage information for the utility. `-v' Give verbose output. Especially useful when dumping current settings or listing all of the tags. `-V' Give very verbose output for outputting even more details about settings. `--version' Output the version string for the utility. _Please note_ that the version of the library that is installed or has been linked into your application may be different from the utility version. If no arguments are specified, dmalloc dumps out the current settings that you have for the environment variable. For example: Debug-Flags '0x40005c7' (runtime) Address 0x1f008, count = 3 Interval 100 Logpath 'malloc' Start-File not-set With a -v option and no arguments, dmalloc dumps out the current settings in a verbose manner. For example: Debug-Flags '0x40005c7' (runtime) log-stats, log-non-free, log-bad-space, check-fence, catch-null Address 0x1f008, count = 10 Interval 100 Logpath 'malloc' Start-File not-set Here are some examples of dmalloc usage: # start tough debugging, check the heap every 100 times, # send the log information to file 'logfile' dmalloc high -i 100 -l logfile # find out what error code 20 is (from the logfile) dmalloc -e 20 # cause the library to halt itself when it sees the address 0x34238 # for the 6th time. dmalloc -a 0x34238:6 # send the log information to file 'logfile' with the time in seconds # as an extension. dmalloc -l logfile.%t # return to the normal 'runtime' settings and clear out all # other settings dmalloc -c runtime # enable basic 'low' settings plus (-p) the logging of # transactions (log-trans) to file 'logfile' dmalloc low -p log-trans -l logfile # print out the current settings with Very-verbose output dmalloc -V # list the available debug malloc tokens with Very-verbose output dmalloc -DV # list the available tags from the rc file with verbose output dmalloc -tv File: dmalloc.info, Node: Environment Variable, Next: Debug Tokens, Prev: Utility Usage, Up: Dmalloc Program 4.3 Environment Variable Name and Features ========================================== An "environment variable" is a variable that is part of the user's working environment and is shared by all the programs. The `DMALLOC_OPTIONS' variable is used by the dmalloc library to enable or disable the memory debugging features, at runtime. _NOTE:_ you can also use the `dmalloc_debug_setup' function to set the option string. It can be set either by hand or with the help of the dmalloc program. *Note Dmalloc Program::. To set it by hand, Bourne shell (sh, bash, ksh, or zsh) users should use: DMALLOC_OPTIONS=value export DMALLOC_OPTIONS C shell (csh or tcsh) users need to invoke: setenv DMALLOC_OPTIONS value The value in the above examples is a comma separated list of tokens each having a corresponding value. The tokens are described below: `debug' This should be set to a value in hexadecimal which corresponds to the functionality token values added together. *Note Debug Tokens::. For instance, if the user wanted to enable the logging of memory transactions (value `0x008') and wanted to check fence-post memory (value `0x400') then `debug' should be set to `0x408' (`0x008' + `0x400'). _NOTE_: You don't have to worry about remembering all the hex values of the tokens because the dmalloc program automates the setting of this variable especially. _NOTE_: You can also specify the debug tokens directly, separated by commas. *Note Debug Tokens::. If `debug' and the tokens are both used, the token values will be added to the debug value. `lockon' Set this to a number which is the "lock-on" period. This dictates to the threaded version of the library to not initialize or lock the mutex lock around the library until after a certain number of allocation calls have been made. See the "Using With Threads" section for more information about the operation of the library with threads. *Note Using With Threads::. `log' Set this to a filename so that if `debug' has logging enabled, the library can log transactions, administration information, and/or errors to the file so memory problems and usage can be tracked. To get different logfiles for different processes, you can assign `log' to a string with `%d' in it (for instance `logfile.%d'). This will be replaced with the pid of the running process (for instance `logfile.2451'). _WARNING_: it is easy to core dump any program with dmalloc, if you send in a format with arguments other than the one `%d'. `addr' When this is set to a hex address (taken from the dmalloc log-file for instance) dmalloc will abort when it finds itself either allocating or freeing that address. The address can also have an `:number' argument. For instance, if it was set it to `0x3e45:10', the library will kill itself the 10th time it sees address `0x3e45'. By setting the number argument to 0, the program will never stop when it sees the address. This is useful for logging all activity on the address and makes it easier to track down specific addresses not being freed. This works well in conjunction with the `STORE_SEEN_COUNT' option. *Note Memory Leaks::. _NOTE_: dmalloc will also log all activity on this address along with a count. `inter' By setting this to a number X, dmalloc will only check the heap every X times. This means a number of debugging features can be enabled while still running the program within a finite amount of time. A setting of `100' works well with reasonably memory intensive programs. This of course means that the library will not catch errors exactly when they happen but possibly 100 library calls later. `start' Set this to a number X and dmalloc will begin checking the heap after X times. This means the intensive debugging can be started after a certain point in a program. `start' also has the format `file:line'. For instance, if it is set to `dmalloc_t.c:126' dmalloc will start checking the heap after it sees a dmalloc call from the `dmalloc_t.c' file, line number 126. If you use `dmalloc_t.c:0', with a 0 line number, then dmalloc will start checking the heap after it sees a call from anywhere in the `dmalloc_t.c' file. This allows the intensive debugging to be started after a certain routine or file has been reached in the program. Some examples are: # turn on transaction and stats logging and set # 'logfile' as the log-file setenv DMALLOC_OPTIONS log-trans,log-stats,log=logfile # enable debug flags 0x1f as well as heap-checking and # set the interval to be 100 setenv DMALLOC_OPTIONS debug=0x1f,check-heap,inter=100 # enable 'logfile' as the log-file, watch for # address '0x1234', and start checking when we see # file.c line 123 setenv DMALLOC_OPTIONS log=logfile,addr=0x1234,start=file.c:123 File: dmalloc.info, Node: Debug Tokens, Next: RC File, Prev: Environment Variable, Up: Dmalloc Program 4.4 Description of the Debugging Tokens ======================================= The below tokens and their corresponding descriptions are for the setting of the debug library setting in the environment variable. *Note Environment Variable::. They should be specified in the user's `.dmallocrc' file. *Note RC File::. Each token, when specified, enables a specific debugging feature. For instance, if you have the `log-stats' token enabled, the library will log general statistics to the logfile. To get this information on the fly, use `dmalloc -DV'. This will print out the Debug tokens in Very-verbose mode. *Note Dmalloc Program::. `none' No debugging functionality `log-stats' Log general statistics when dmalloc_shutdown or dmalloc_log_stats is called. `log-non-free' Log non-freed memory pointers when dmalloc_shutdown or dmalloc_log_unfreed is called. `log-known' Log only known memory pointers that have not been freed. Pointers which do not have file/line or return-address information will not be logged. `log-trans' Log general memory transactions (quite verbose). `log-admin' Log administrative information (quite verbose). `log-bad-space' Log actual bytes in and around bad pointers. `log-nonfree-space' Log actual bytes in non-freed pointers. `log-elapsed-time' Log elapsed-time for allocated pointers (see `conf.h'). `log-current-time' Log current-time for allocated pointers (see `conf.h'). `check-fence' Check fence-post memory areas. `check-heap' Verify heap administrative structure. `check-blank' Check to see if space that was blanked when a pointer was allocated or when it was freed has been overwritten. If this is enabled then it will enable `free-blank' and `alloc-blank' automatically. `check-funcs' Check the arguments of some functions (mostly string operations) looking for bad pointers. `check-shutdown' Check all of the pointers in the heap when the program exits. `catch-signals' Shutdown the library automatically on SIGHUP, SIGINT, or SIGTERM. This will cause the library to dump its statistics (if requested) when you press control-c on the program (for example). `realloc-copy' Always copy data to a new pointer when realloc. `free-blank' Write special "dmalloc-free" byte (hexadecimal `0xdf', octal `0337', decimal `223') into space when it is freed. You can set this to be something else in the `settings.dist' file. This ensures that your program is not using memory after it has been freed. You can check to see if areas have been improperly overwritten with the `check-blank' token. If the free space has been overwritten, then `ERROR_FREE_OVERWRITTEN' is triggered. *Note Error Codes::. `error-abort' Abort the program (and dump core) on errors. See `error-dump' below. *Note Dumping Core::. `alloc-blank' Write special "dmalloc-alloc" byte (hexadecimal `0xda', octal `0332', decimal `218') into space when it is allocated. You can set this to be something else in the `settings.dist' file. If you are not using `calloc' this will overwrite the user space with the special bytes ensuring that your program is initializing its dynamic memory appropriately. Also, if you ask for 35 bytes and the library has to give you a block of 64 because of rounding issues, it will overwrite the extra memory with the special byte. You can then check to see if the extra areas have been improperly overwritten by enabling the `check-blank' token. `print-messages' Log any errors and messages to the screen via standard-error. `catch-null' Abort the program immediately if the library fails to get more heap space from the heap allocation routine `mmap' or `sbrk'. `never-reuse' Have the heap never use space that has been used before and freed. *Note Memory Leaks::. _WARNING_: This should be used with caution since you may run out of heap space. `error-dump' Dump core on error and then continue. Later core dumps overwrite earlier ones if the program encounters more than one error. See `error-abort' above. *Note Dumping Core::. _NOTE_: This will only work if your system supports the `fork' system call and the configuration utility was able to fork without going recursive. `error-free-null' By default the library will not generate an error when a program tries to free a NULL pointer. By enabling this token, you can change this behavior so an error is reported. See also the ALLOW_FREE_NULL and ALLOW_FREE_NULL_MESSAGE settings in the `settings.h' file to change the default behavior. File: dmalloc.info, Node: RC File, Prev: Debug Tokens, Up: Dmalloc Program 4.5 Format of the Runtime Configuration File ============================================ By using a "RC File" (or runtime configuration file) you can alias tags to combinations of debug tokens. *Note Debug Tokens::. _NOTE_: For beginning users, the dmalloc program has a couple of tags built into it so it is not necessary for you to setup a RC file: `runtime' Enables basic runtime tests including fence-post checking, null handling, and logging of any errors. `low' Runtime settings plus minimal checking of heap structures and overwriting of allocated and freed space. `medium' Low settings plus checking of all heap structures on each memory call, always relocates block on realloc, and aborts on errors. You may want to use `-i' option to the dmalloc utility. *Note Dmalloc Program::. `high' Medium settings plus checking of overwritten freed and allocated memory and checking of arguments to a number of common functions. You may want to use `-i' option to the dmalloc utility. *Note Dmalloc Program::. For expert users, a sample `dmallocrc' file has been provided but you are encouraged to roll your own combinations. The name of default rc-file is `$HOME/.dmallocrc'. The `$HOME' environment variable should be set by the system to point to your home-directory. The file should contain lines in the general form of: tag token1, token2, ... `tag' is to be matched with the tag argument passed to the dmalloc program, while `token1, token2, ...' are debug capability tokens. *Note Dmalloc Program::, *Note Debug Tokens::. A line can be finished with a `\' meaning it continues onto the next line. Lines beginning with `#' are treated as comments and are ignored along with empty lines. Here is an example of a `.dmallocrc' file: # # Dmalloc runtime configuration file for the debug malloc library # # no debugging none none # basic debugging debug1 log-stats, log-non-free, check-fence # more logging and some heap checking debug2 log-stats, log-non-free, log-trans, \ check-fence, check-heap, error-abort # good utilities debug3 log-stats, log-non-free, log-trans, \ log-admin, check-fence, check-heap, realloc-copy, \ free-blank, error-abort ... For example, with the above file installed, you can type `dmalloc debug1' after setting up your shell alias. *Note Dmalloc Program::. This enables the logging of statistics, the logging of non-freed memory, and the checking of fence-post memory areas. Enter `dmalloc none' to disable all memory debugging features. File: dmalloc.info, Node: Source Code, Next: Troubleshooting, Prev: Dmalloc Program, Up: Top 5 Information on the Source Code ******************************** * Menu: * Definitions:: Definition of terms and other information. * Compatibility:: General compatibility concerns. * Portability:: Issues important for porting the library. File: dmalloc.info, Node: Definitions, Next: Compatibility, Prev: Source Code, Up: Source Code 5.1 Definition of Terms and other Information ============================================= Here are a couple definitions and other information for those interested in "picking the brain" of the library. The code is a little ugly here and there and it conforms to the Gray-Watson handbook of coding standards only. "bblock" basic block containing 2 ^ BASIC_BLOCK bytes of info "bblock_adm" administration for a set of basic blocks "dblock" divided block containing some base 2 number of blocks smaller than a basic block. "dblock_adm" administration for a set of divided blocks "chunk" some anonymous amount of memory For more information about administration structures, see the code and comments from `chunk_loc.h'. File: dmalloc.info, Node: Compatibility, Next: Portability, Prev: Definitions, Up: Source Code 5.2 General Compatibility Concerns ================================== * Realloc() backwards compatibility with being able to realloc from the last freed block is _not_ supported. The author is interested to know who is using this (cough, cough) feature and for what reason. * Realloc() of a NULL pointer is supported in which case the library will just make a call to malloc(). This can be disabled with the help of the `ALLOW_REALLOC_NULL' manual compilation option in the `settings.h' file to adjust the library's default behavior. * Some systems allow free(0) to not be an error for some reason. Since 0 is not a valid address returned by the malloc call, it is debatable that this should be allowed. See `settings.h' for the `ALLOW_FREE_NULL' manual compilation option to adjust the library's default behavior. * Aside from possibly being slower than the system's memory allocation functions, the library should be fully compatible with the standard memory routines. If this is _not_ the case, please bring this to my attention. File: dmalloc.info, Node: Portability, Prev: Compatibility, Up: Source Code 5.3 Issues Important for Porting the Library ============================================ General portability issues center around: * mmap, sbrk, or compatible function usages. The library does support a preallocated memory chunk heap. See the `INTERNAL_MEMORY_SPACE' define in the `settings.dist' file. * The locating of the caller's address from the dmalloc functions. This is useful in locating problems from dmalloc functions called from C files which did not include `dmalloc.h': C library calls for instance. See `return.h' for the available architecture/compiler combinations. You may want to examine the assembly code from gcc (GNUs superior c-compiler) version 2+ being run on the following code. It should give you a good start on building a hack for your box. static char * x; a() { x = __builtin_return_address(0); } main() { a(); } ------------------------------------------------------------------------------- 6 Some Solutions to Common Problems *********************************** This section provides some answers to some common problems and questions. Please send me mail with any additions to this list - either problems you are still having or tips that you would like to pass on. When diagnosing a problem, if possible, always make sure you are running the most up to date version of Dmalloc available from the home page at URL `http://dmalloc.com/'. Problems are often fixed and a new release can be published before people encounter them. `Why does my program run so slow?' This library has never been (and maybe never will be) optimized for space nor speed. Some of its features make it unable to use some of the organizational methods of other more efficient heap libraries. If you have the `check-heap' token enabled, your program might run slow or seem to hang. This is because by default, the library will run a full check of the heap with every memory allocation or free. You can have the library check itself less frequently by using the `-i' option to the dmalloc utility. *Note Dmalloc Program::. If you are using the `high' token and you need your program to run faster, try the `medium' or `low' tokens which don't check as many heap features and so run faster although they will not catch as many problems. *Note RC File::. `Why was a log-file not produced after I ran my program?' This could be caused by a number of different problems. 1. Are you sure you followed all of the items in the "Getting Started" section? Please review them if there is any doubt. *Note Getting Started::. 2. Use the `env' or `printenv' commands to make sure that the `DMALLOC_OPTIONS' variable is set in your exported environment. *Note Environment Variable::. 3. Make sure that your program has been compiled correctly with the dmalloc library. The `ident' program should show chunk.c and other dmalloc files compiled into your program. You can also do `strings -a your-program | grep chunk.c' and look for something like `$Id: chunk.c,v 1.152 1999/08/25 12:37:01 gray Exp $' with different versions and date information. If this doesn't show up then chances are dmalloc was not linked into your program. 4. If your program changes its working directory, it may write the dmalloc log-file somewhere else in the filesystem. You will need to check both where the program was started and to where it might change directory. 5. The logfile is only produced when `dmalloc_shutdown()' is called. By default it will be called when `exit()' gets called. If you are running your program and press `Control-C' under Unix the program will stop immediately and `dmalloc_shutdown()' will not get called. You can either setup a signal handler for `SIGINTR' and call exit yourself, or you can enable the `catch-signals' token. *Note Debug Tokens::. 6. If your program is segfaulting or otherwise crashing when it exits, the `exit()' routine may not being called. You will have to resolve these issues so the dmalloc library can gracefully exit and write its log file. 7. You may want to call `dmalloc_log_stats()' and `dmalloc_log_unfreed()' (or `dmalloc_log_changed()') directly to have the library write its log file. Some system modules may not have shutdown if you call this before `exit()' so extra unfreed memory may be reported. `I don't see any information about my non-freed (leaked) memory?' The library will not (by default) report on "unknown" non-freed memory. Unknown means memory that does not have associated file and line information. This will be necessary if you are _not_ including `dmalloc.h' in all of your C files or if you are interested in tracking leaks in system functions. `Dmalloc is returning the error "malloc library has gone recursive"' This most likely indicates that you are using the Dmalloc library within a threaded application and two threads are trying to use the dmalloc library at once. Please see the section of the manual about threads for more information about properly configuring the library. *Note Using With Threads::. If you are not using threads, then your program could have caught a signal while within Dmalloc, which then in turn called a memory allocation routine. It is unwise to allocate memory on the heap in most signal handlers. Lastly, some functions called by the library may call memory routines that it does not anticipate. If you think this the case, please report the problem and include a stack trace, operating system version/type, and the version of Dmalloc you are using. File: dmalloc.info, Node: Index of Concepts, Prev: Troubleshooting, Up: Top Index of Concepts ***************** [index] * Menu: * %h: Utility Usage. (line 89) * %i: Utility Usage. (line 93) * %p: Utility Usage. (line 100) * %t: Utility Usage. (line 104) * %u: Utility Usage. (line 108) * -disable-cxx: Installation. (line 23) * -enable-shlib: Installation. (line 23) * -enable-threads: Installation. (line 23) * .dmallocrc file: RC File. (line 6) * 0332 character: Debug Tokens. (line 94) * 0337 character: Debug Tokens. (line 80) * 0xda character: Debug Tokens. (line 94) * 0xdf character: Debug Tokens. (line 80) * 1, error code: Error Codes. (line 20) * 10, error code: Error Codes. (line 30) * 11, error code: Error Codes. (line 34) * 13, error code: Error Codes. (line 40) * 2, error code: Error Codes. (line 24) * 20, error code: Error Codes. (line 47) * 21, error code: Error Codes. (line 51) * 218 character: Debug Tokens. (line 94) * 22, error code: Error Codes. (line 57) * 223 character: Debug Tokens. (line 80) * 23, error code: Error Codes. (line 68) * 24, error code: Error Codes. (line 75) * 25, error code: Error Codes. (line 82) * 26, error code: Error Codes. (line 89) * 27, error code: Error Codes. (line 97) * 28, error code: Error Codes. (line 110) * 30, error code: Error Codes. (line 117) * 332 character: Debug Tokens. (line 94) * 337 character: Debug Tokens. (line 80) * 40, error code: Error Codes. (line 123) * 41, error code: Error Codes. (line 128) * 43, error code: Error Codes. (line 135) * 45, error code: Error Codes. (line 148) * 60, error code: Error Codes. (line 152) * 61, error code: Error Codes. (line 157) * 67, error code: Error Codes. (line 165) * 70, error code: Error Codes. (line 173) * 72, error code: Error Codes. (line 178) * 73, error code: Error Codes. (line 183) * abort: Dumping Core. (line 31) * address list error: Error Codes. (line 178) * address locating: Environment Variable. (line 65) * address setting: Environment Variable. (line 65) * admin list error: Error Codes. (line 173) * alias, shell <1>: Getting Started. (line 27) * alias, shell: Shell Alias. (line 13) * alloc failed error: Error Codes. (line 135) * alloc-blank: Debug Tokens. (line 94) * allocation basics: Allocation Basics. (line 6) * allocation macros: Allocation Macros. (line 6) * Allocation of zeros: Malloc Functions. (line 20) * ALLOW_FREE_NULL: Debug Tokens. (line 127) * ALLOW_FREE_NULL settings.h option: Compatibility. (line 16) * ALLOW_FREE_NULL_MESSAGE <1>: Logfile Details. (line 41) * ALLOW_FREE_NULL_MESSAGE: Debug Tokens. (line 127) * ALLOW_REALLOC_NULL settings.h option: Compatibility. (line 11) * already free error: Error Codes. (line 157) * ANSI-C compiler: Installation. (line 64) * argument checking: Argument Checking. (line 6) * assembly hacks: Return Address. (line 14) * atexit: Getting Started. (line 17) * atexit function: Extensions. (line 26) * author: Top. (line 8) * automatic shutdown: Getting Started. (line 17) * bad admin structure list: Error Codes. (line 173) * bad file error: Error Codes. (line 75) * bad line error: Error Codes. (line 82) * bad setup error: Error Codes. (line 30) * bad size error: Error Codes. (line 123) * bash shell <1>: Getting Started. (line 27) * bash shell: Shell Alias. (line 13) * bash usage: Environment Variable. (line 14) * basic allocation information: Allocation Basics. (line 6) * basic definitions: Basic Definitions. (line 6) * beginning: Getting Started. (line 6) * blank space: Debug Tokens. (line 80) * blanking memory: Debug Tokens. (line 94) * bounds checking: Features. (line 23) * Bourne shell usage: Environment Variable. (line 14) * building the library: Installation. (line 6) * C shell usage: Environment Variable. (line 20) * c++ usage: Using With C++. (line 6) * caller address translation: Translate Return Addresses. (line 12) * caller's address: Return Address. (line 6) * calloc: Malloc Functions. (line 20) * cannot locate pointer in heap: Error Codes. (line 57) * catch-null: Debug Tokens. (line 109) * catch-signals: Debug Tokens. (line 72) * cgi-bin process debugging: Debugging A Server. (line 6) * cgi-bin usage of dmalloc: Debugging A Server. (line 6) * changed memory log: Extensions. (line 174) * check-blank <1>: Error Codes. (line 165) * check-blank: Debug Tokens. (line 59) * check-fence: Debug Tokens. (line 53) * check-funcs: Debug Tokens. (line 65) * check-heap <1>: Debug Tokens. (line 56) * check-heap <2>: Troubleshooting. (line 17) * check-heap: How It Works. (line 28) * check-shutdown: Debug Tokens. (line 69) * checking arguments: Argument Checking. (line 6) * checking bounds: Features. (line 23) * checkpoint memory usage: Extensions. (line 174) * child process debugging: Debugging A Server. (line 6) * clearing memory: Debug Tokens. (line 94) * comma separated tokens in env variable: Environment Variable. (line 39) * common problems: Troubleshooting. (line 6) * compatibility: Compatibility. (line 6) * compiling the library: Installation. (line 6) * conf.h file: Installation. (line 23) * configuration file: RC File. (line 6) * configure script: Installation. (line 23) * configuring the library: Installation. (line 6) * constancy verification: Features. (line 35) * copying: Copying. (line 6) * core dump <1>: Dumping Core. (line 6) * core dump <2>: Debug Tokens. (line 90) * core dump <3>: Features. (line 84) * core dump: Debug Tokens. (line 118) * core dump, none: Dumping Core. (line 19) * core file: Dumping Core. (line 19) * could not grow heap by allocating memory: Error Codes. (line 135) * count changed: Extensions. (line 148) * count number of bytes changed since mark: Extensions. (line 148) * cpp: Features. (line 10) * csh shell <1>: Shell Alias. (line 27) * csh shell: Getting Started. (line 50) * csh usage: Environment Variable. (line 20) * current debug value: Extensions. (line 66) * cygwin: Using With Cygwin. (line 6) * da character: Debug Tokens. (line 94) * daemon process debugging: Debugging A Server. (line 6) * debug setting: Environment Variable. (line 28) * debug tokens: Debug Tokens. (line 6) * debugger: Dumping Core. (line 6) * debugger usage with dmalloc: Using With a Debugger. (line 6) * debugging cgi-bin processes: Debugging A Server. (line 6) * debugging child processes: Debugging A Server. (line 6) * debugging daemon processes: Debugging A Server. (line 6) * debugging server processes: Debugging A Server. (line 6) * decimal 218 character: Debug Tokens. (line 94) * decimal 223 character: Debug Tokens. (line 80) * delay heap checking: Utility Usage. (line 180) * destructor: Getting Started. (line 17) * df character: Debug Tokens. (line 80) * diagnosing errors: General Errors. (line 6) * disabling library checking: Disabling the Library. (line 6) * disabling the library: Disabling the Library. (line 6) * dmalloc program: Dmalloc Program. (line 6) * dmalloc utility: Dmalloc Program. (line 6) * dmalloc.h file: Allocation Macros. (line 6) * dmalloc_debug: Disabling the Library. (line 6) * dmalloc_debug function: Extensions. (line 52) * dmalloc_debug_current function: Extensions. (line 66) * dmalloc_debug_setup: Extensions. (line 72) * dmalloc_debug_setup function: Debugging A Server. (line 23) * dmalloc_debug_setup usage: Using With Cygwin. (line 26) * dmalloc_errno number: Extensions. (line 9) * dmalloc_error() routine: Using With a Debugger. (line 15) * dmalloc_examine function: Extensions. (line 96) * DMALLOC_FUNC_CHECK: Getting Started. (line 73) * DMALLOC_FUNC_CHECK flag: Argument Checking. (line 6) * dmalloc_get_stats function: Extensions. (line 200) * dmalloc_log_changed function: Extensions. (line 174) * dmalloc_log_stats function: Extensions. (line 164) * dmalloc_log_unfreed function: Extensions. (line 168) * dmalloc_logpath variable: Extensions. (line 17) * dmalloc_mark function: Extensions. (line 118) * dmalloc_memory_allocated function: Extensions. (line 136) * dmalloc_message function: Extensions. (line 195) * DMALLOC_OPTIONS <1>: Troubleshooting. (line 39) * DMALLOC_OPTIONS: Environment Variable. (line 6) * dmalloc_shutdown function: Extensions. (line 25) * DMALLOC_SIZE option: Installation. (line 45) * dmalloc_strerror function: Extensions. (line 222) * dmalloc_t test program: Installation. (line 92) * dmalloc_track function: Extensions. (line 111) * dmalloc_verify function: Extensions. (line 41) * dmalloc_verify() routine: General Errors. (line 32) * dmalloc_vmessage function: Extensions. (line 189) * dmallocc.cc: Using With C++. (line 10) * dmallocc.cc file: Using With C++. (line 6) * dmallocrc file: RC File. (line 6) * dump core <1>: Dumping Core. (line 6) * dump core <2>: Features. (line 84) * dump core: Debug Tokens. (line 118) * env: Troubleshooting. (line 39) * environment variable: Environment Variable. (line 6) * errno value is not valid: Error Codes. (line 24) * error code 10: Error Codes. (line 30) * error code 11: Error Codes. (line 34) * error code 13: Error Codes. (line 40) * error code 20: Error Codes. (line 47) * error code 21: Error Codes. (line 51) * error code 22: Error Codes. (line 57) * error code 23: Error Codes. (line 68) * error code 24: Error Codes. (line 75) * error code 25: Error Codes. (line 82) * error code 26: Error Codes. (line 89) * error code 27: Error Codes. (line 97) * error code 28: Error Codes. (line 110) * error code 30: Error Codes. (line 117) * error code 40: Error Codes. (line 123) * error code 41: Error Codes. (line 128) * error code 43: Error Codes. (line 135) * error code 45: Error Codes. (line 148) * error code 60: Error Codes. (line 152) * error code 61: Error Codes. (line 157) * error code 67: Error Codes. (line 165) * error code 70: Error Codes. (line 173) * error code 72: Error Codes. (line 178) * error code 73: Error Codes. (line 183) * error code, 1: Error Codes. (line 20) * error code, 2: Error Codes. (line 24) * error codes: Error Codes. (line 6) * error message: Extensions. (line 222) * error number: Extensions. (line 9) * error-abort <1>: Debug Tokens. (line 90) * error-abort: Dumping Core. (line 6) * error-dump <1>: Debug Tokens. (line 118) * error-dump: Dumping Core. (line 6) * error-free-null: Debug Tokens. (line 127) * error-free-null token: Error Codes. (line 47) * ERROR_ADDRESS_LIST: Error Codes. (line 178) * ERROR_ADMIN_LIST: Error Codes. (line 173) * ERROR_ALLOC_FAILED: Error Codes. (line 135) * ERROR_ALREADY_FREE: Error Codes. (line 157) * ERROR_BAD_FILE: Error Codes. (line 75) * ERROR_BAD_LINE: Error Codes. (line 82) * ERROR_BAD_SETUP: Error Codes. (line 30) * ERROR_BAD_SIZE: Error Codes. (line 123) * ERROR_FREE_OVERWRITTEN <1>: Debug Tokens. (line 80) * ERROR_FREE_OVERWRITTEN: Error Codes. (line 165) * ERROR_IN_TWICE: Error Codes. (line 34) * ERROR_IS_FOUND: Error Codes. (line 68) * ERROR_IS_NULL: Error Codes. (line 47) * ERROR_LOCK_NOT_CONFIG: Error Codes. (line 40) * ERROR_NONE: Error Codes. (line 20) * ERROR_NOT_FOUND: Error Codes. (line 57) * ERROR_NOT_IN_HEAP: Error Codes. (line 51) * ERROR_NOT_ON_BLOCK: Error Codes. (line 152) * ERROR_NOT_START_BLOCK: Error Codes. (line 117) * ERROR_OVER_FENCE: Error Codes. (line 97) * ERROR_OVER_LIMIT <1>: Utility Usage. (line 135) * ERROR_OVER_LIMIT: Error Codes. (line 148) * ERROR_SLOT_CORRUPT: Error Codes. (line 183) * ERROR_TOO_BIG: Error Codes. (line 128) * ERROR_UNDER_FENCE: Error Codes. (line 89) * ERROR_WOULD_OVERWRITE: Error Codes. (line 110) * examine a pointer: Extensions. (line 96) * extensions: Extensions. (line 6) * failed over picket-fence magic-number check: Error Codes. (line 97) * failed under picket-fence magic-number check: Error Codes. (line 89) * faq: Troubleshooting. (line 6) * features: Features. (line 6) * fence-post checking: Features. (line 23) * fence-post errors: Fence-Post Overruns. (line 6) * file/line numbers: Features. (line 10) * found pointer the user was looking for: Error Codes. (line 68) * free: Malloc Functions. (line 46) * free null token: Error Codes. (line 47) * free overwritten error: Error Codes. (line 165) * free space has been overwritten: Error Codes. (line 165) * free-blank <1>: Debug Tokens. (line 80) * free-blank: Error Codes. (line 165) * freed memory: Features. (line 65) * gcc: Portability. (line 17) * gdb: Using With a Debugger. (line 15) * gdb with shared libraries: Using With a Debugger. (line 26) * general errors: General Errors. (line 6) * generating core dump: Dumping Core. (line 6) * get heap statistics: Extensions. (line 200) * getenv, problems with: Using With Cygwin. (line 10) * GETENV_SAVE conf.h option: Using With Cygwin. (line 15) * GetEnvironmentVariableA, using with: Using With Cygwin. (line 10) * gethostname function usage: Utility Usage. (line 89) * getpid function usage: Utility Usage. (line 100) * getting started: Getting Started. (line 6) * getuid function usage: Utility Usage. (line 108) * hanging program: Troubleshooting. (line 16) * HAVE_GETENVIRONMENTVARIABLEA: Using With Cygwin. (line 15) * heap memory: Basic Definitions. (line 39) * heap statistics function: Extensions. (line 200) * help: Troubleshooting. (line 6) * hexadecimal 0xda character: Debug Tokens. (line 94) * hexadecimal 0xdf character: Debug Tokens. (line 80) * high token: RC File. (line 26) * hints that may help: Other Hints. (line 6) * hostname in logfile path: Utility Usage. (line 89) * how do i...: Troubleshooting. (line 6) * how to begin: Getting Started. (line 6) * HUP signal: Debug Tokens. (line 72) * ident: Troubleshooting. (line 43) * in twice error: Error Codes. (line 34) * initialization and setup failed: Error Codes. (line 30) * installing the library: Installation. (line 6) * INT signal: Debug Tokens. (line 72) * interaction count <1>: Extensions. (line 118) * interaction count: Utility Usage. (line 180) * internal address list corruption: Error Codes. (line 178) * internal error number: Extensions. (line 9) * internal memory slot corruption: Error Codes. (line 183) * INTERNAL_MEMORY_SPACE: Portability. (line 8) * interval setting <1>: Environment Variable. (line 83) * interval setting: Utility Usage. (line 72) * introduction: Top. (line 8) * invalid allocation size: Error Codes. (line 123) * invalid errno value: Error Codes. (line 24) * INVALID_ERROR: Error Codes. (line 24) * is found error: Error Codes. (line 68) * is null error: Error Codes. (line 47) * iteration count: How It Works. (line 48) * jump start: Getting Started. (line 6) * kill process: Dumping Core. (line 31) * KILL_PROCESS: Dumping Core. (line 31) * ksh shell <1>: Shell Alias. (line 13) * ksh shell: Getting Started. (line 27) * ksh usage: Environment Variable. (line 14) * largest maximum allocation size exceeded: Error Codes. (line 128) * leaking memory <1>: Memory Leaks. (line 6) * leaking memory: Features. (line 55) * libdmallocxx.a: Using With C++. (line 6) * library permissions: Copying. (line 6) * library utility: Dmalloc Program. (line 6) * library version: Utility Usage. (line 214) * license: Copying. (line 6) * lock on <1>: Using With Threads. (line 27) * lock on: Utility Usage. (line 147) * lock-on: Error Codes. (line 34) * lock-on not configured: Error Codes. (line 40) * lockon setting: Environment Variable. (line 44) * log memory changes: Extensions. (line 174) * log statistics: Extensions. (line 164) * log unfreed memory: Extensions. (line 168) * log-admin: Debug Tokens. (line 38) * log-bad-space: Debug Tokens. (line 41) * log-current-time: Debug Tokens. (line 50) * log-elapsed-time: Debug Tokens. (line 47) * log-known: Debug Tokens. (line 30) * log-non-free: Debug Tokens. (line 26) * log-nonfree-space: Debug Tokens. (line 44) * log-stats: Debug Tokens. (line 22) * log-trans: Debug Tokens. (line 35) * LOG_ITERATION <1>: Extensions. (line 118) * LOG_ITERATION: Utility Usage. (line 180) * LOG_ITERATION_COUNT: How It Works. (line 48) * logfile format: Logfile Details. (line 6) * logfile message writer: Extensions. (line 189) * logfile name: Extensions. (line 17) * logfile not produced: Troubleshooting. (line 32) * logfile setting: Environment Variable. (line 52) * logging information to disk: Environment Variable. (line 52) * logging statistics: Features. (line 55) * low token: RC File. (line 16) * macros, allocation: Allocation Macros. (line 6) * making the library: Installation. (line 6) * malloc: Malloc Functions. (line 11) * malloc functions: Malloc Functions. (line 6) * malloc library has gone recursive: Error Codes. (line 34) * mark count: Utility Usage. (line 180) * mark memory position: Extensions. (line 118) * medium token: RC File. (line 20) * memalign: Allocation Macros. (line 23) * memory allocated function: Extensions. (line 136) * memory definitions: Basic Definitions. (line 6) * memory leaks <1>: Memory Leaks. (line 6) * memory leaks: Features. (line 55) * memory limit <1>: Error Codes. (line 148) * memory limit: Utility Usage. (line 135) * memory position marker: Extensions. (line 118) * memory problems in system functions: Features. (line 90) * memory transaction count <1>: Utility Usage. (line 180) * memory transaction count: How It Works. (line 48) * missing core dump: Dumping Core. (line 19) * mmap <1>: General Errors. (line 6) * mmap <2>: Error Codes. (line 57) * mmap <3>: Debug Tokens. (line 109) * mmap: Error Codes. (line 143) * mmap, usage without: Portability. (line 8) * name of host in logfile path: Utility Usage. (line 89) * never-reuse: Debug Tokens. (line 113) * no core dump: Dumping Core. (line 19) * no error: Error Codes. (line 20) * no logfile produced: Troubleshooting. (line 32) * none token: Debug Tokens. (line 19) * not found error: Error Codes. (line 57) * not in heap error: Error Codes. (line 51) * not on block boundary error: Error Codes. (line 152) * not start block error: Error Codes. (line 117) * number bytes changed since mark: Extensions. (line 148) * number of bytes allocated: Extensions. (line 136) * octal 332 character: Debug Tokens. (line 94) * octal 337 character: Debug Tokens. (line 80) * on_exit: Getting Started. (line 17) * on_exit function: Extensions. (line 26) * other hints: Other Hints. (line 6) * over fence error: Error Codes. (line 97) * over limit error: Error Codes. (line 148) * over user specified allocation limit error: Error Codes. (line 148) * override debug settings: Extensions. (line 52) * overview: Overview. (line 6) * overwriting memory: Debug Tokens. (line 94) * page size: Extensions. (line 142) * permissions of the library: Copying. (line 6) * pid in logfile path: Utility Usage. (line 100) * pointer information: Extensions. (line 96) * pointer is not on block boundary: Error Codes. (line 152) * pointer is not pointing to heap data space: Error Codes. (line 51) * pointer is not to start of memory block: Error Codes. (line 117) * pointer is null error: Error Codes. (line 47) * pointer not found error: Error Codes. (line 57) * pointer not in heap error: Error Codes. (line 51) * pointer seen count: Memory Leaks. (line 42) * portability: Portability. (line 6) * possibly bad .c file line-number: Error Codes. (line 82) * possibly bad .c filename pointer: Error Codes. (line 75) * preallocated memory heap: Portability. (line 8) * print-messages: Debug Tokens. (line 106) * printenv: Troubleshooting. (line 39) * problems: Troubleshooting. (line 6) * process-id in logfile path: Utility Usage. (line 100) * program core: Dumping Core. (line 19) * programming: Programming. (line 6) * pthreads: Using With Threads. (line 6) * questions: Troubleshooting. (line 6) * quick start: Getting Started. (line 6) * ra: Return Address. (line 6) * ra_info.pl <1>: Return Address. (line 24) * ra_info.pl: Translate Return Addresses. (line 6) * rc file: RC File. (line 6) * rc shell: Getting Started. (line 55) * reading environment, problems with: Using With Cygwin. (line 10) * realloc: Malloc Functions. (line 31) * realloc-copy: Debug Tokens. (line 77) * recalloc: Allocation Macros. (line 23) * recursion: Error Codes. (line 34) * report heap statistics: Extensions. (line 200) * restoring library flags: Disabling the Library. (line 6) * return-address <1>: Return Address. (line 6) * return-address <2>: Features. (line 16) * return-address: Portability. (line 12) * return-address translation: Translate Return Addresses. (line 12) * return.h file: Return Address. (line 6) * runtime token: RC File. (line 12) * runtime-config file: RC File. (line 6) * sbrk <1>: General Errors. (line 6) * sbrk <2>: Error Codes. (line 57) * sbrk: Debug Tokens. (line 109) * sbrk, usage without: Portability. (line 8) * seen count <1>: Extensions. (line 100) * seen count <2>: Memory Leaks. (line 42) * seen count: Logfile Details. (line 47) * server process debugging: Debugging A Server. (line 6) * set debug functionality flags: Extensions. (line 52) * settings.dist file: Installation. (line 18) * settings.h file: Installation. (line 37) * setup debug flags: Extensions. (line 72) * sh usage: Environment Variable. (line 14) * shared libraries with gdb: Using With a Debugger. (line 26) * shell usage: Environment Variable. (line 14) * shutdown on signal: Debug Tokens. (line 72) * shutdown the library: Extensions. (line 25) * shutdown, automatic: Getting Started. (line 17) * SIGHUP: Debug Tokens. (line 72) * SIGINT: Debug Tokens. (line 72) * signal shutdown: Debug Tokens. (line 72) * SIGTERM: Debug Tokens. (line 72) * size of memory pages: Extensions. (line 142) * slot corrupt error: Error Codes. (line 183) * slow running: Troubleshooting. (line 16) * source code: Source Code. (line 6) * source definitions: Definitions. (line 6) * stack memory: Basic Definitions. (line 23) * start heap check later: Utility Usage. (line 180) * start setting: Environment Variable. (line 94) * static memory: Basic Definitions. (line 12) * statistics: Features. (line 55) * statistics logging: Extensions. (line 164) * STORE_SEEN_COUNT conf.h option: Memory Leaks. (line 42) * strdup: Allocation Macros. (line 23) * string error message: Extensions. (line 222) * string of debug tokens: Extensions. (line 72) * strings: Troubleshooting. (line 43) * system memory problems: Features. (line 90) * tcsh shell <1>: Shell Alias. (line 27) * tcsh shell: Getting Started. (line 50) * tcsh usage: Environment Variable. (line 20) * TERM signal: Debug Tokens. (line 72) * testing the library: Installation. (line 92) * thread locking has not been configured: Error Codes. (line 40) * thread-id in logfile path: Utility Usage. (line 93) * threads: Using With Threads. (line 6) * time function usage: Utility Usage. (line 104) * time in logfile path: Utility Usage. (line 104) * token high: RC File. (line 26) * token low: RC File. (line 16) * token medium: RC File. (line 20) * token runtime: RC File. (line 12) * tokens, debug: Debug Tokens. (line 6) * too big error: Error Codes. (line 128) * too slow: Troubleshooting. (line 16) * track memory calls: Extensions. (line 111) * tracking addresses: Environment Variable. (line 65) * transaction count <1>: Extensions. (line 118) * transaction count: Utility Usage. (line 180) * tried to free previously freed pointer: Error Codes. (line 157) * troubleshooting: Troubleshooting. (line 6) * turning off library flags: Disabling the Library. (line 6) * uid in logfile path: Utility Usage. (line 108) * under fence error: Error Codes. (line 89) * unfreed memory log: Extensions. (line 168) * usage of dmalloc in a daemon: Debugging A Server. (line 6) * usage of dmalloc in a server: Debugging A Server. (line 6) * usage of dmalloc with cgi-bin: Debugging A Server. (line 6) * usage of the utility: Utility Usage. (line 6) * use of pointer would exceed allocation: Error Codes. (line 110) * USE_MMAP conf.h option: Error Codes. (line 143) * USE_RETURN_MACROS conf.h option: Installation. (line 57) * user-id in logfile path: Utility Usage. (line 108) * using a debugger with dmalloc: Using With a Debugger. (line 6) * utility program: Dmalloc Program. (line 6) * utility usage: Utility Usage. (line 6) * utility version: Utility Usage. (line 214) * valloc: Allocation Macros. (line 23) * various hints: Other Hints. (line 6) * verify pointers: Extensions. (line 41) * verify the heap: Extensions. (line 41) * version of library: Logfile Details. (line 34) * version of utility: Utility Usage. (line 214) * where to begin: Getting Started. (line 6) * why hanging: Troubleshooting. (line 16) * why running slow: Troubleshooting. (line 16) * would overwrite error: Error Codes. (line 110) * write message to logfile: Extensions. (line 189) * zeros, allocation of: Malloc Functions. (line 20) * zsh shell <1>: Shell Alias. (line 13) * zsh shell: Getting Started. (line 27) * zsh usage: Environment Variable. (line 14) Tag Table: Node: Top1132 Node: Copying3246 Node: Overview4003 Node: Installation4531 Node: Getting Started10335 Node: Allocation Basics16089 Node: Basic Definitions16437 Node: Malloc Functions19142 Node: Features21534 Node: How It Works26077 Node: Programming29378 Node: Allocation Macros30515 Node: Return Address33137 Node: Argument Checking34561 Node: Dumping Core36246 Node: Extensions38461 Node: Error Codes48555 Node: Disabling the Library58099 Node: Using With C++60731 Node: Using With a Debugger61729 Node: General Errors63456 Node: Memory Leaks65394 Node: Fence-Post Overruns68972 Node: Translate Return Addresses70702 Node: Using With Threads71969 Node: Using With Cygwin76339 Node: Debugging A Server78151 Node: Logfile Details84186 Node: Other Hints87949 Node: Dmalloc Program89342 Node: Shell Alias90248 Node: Utility Usage92400 Node: Environment Variable102401 Node: Debug Tokens107633 Node: RC File112544 Node: Source Code115322 Node: Definitions115712 Node: Compatibility116574 Node: Portability117795 Node: Troubleshooting118897 Node: Index of Concepts124060 End Tag Table ------------------------------------------------------------------------------- dmalloc-5.5.2/ChangeLog.1000644 001751 001751 00000201513 10622115666 015026 0ustar00graygray000000 000000 2007-05-14 Gray Watson <> * Removed some left-over references to the dmalloc.info file. Thanks Bernard. * Fixed some unsigned/signed issues in one of the dmalloc_t tests. Thanks Bernard. * Fixed problems with configure and SL_LINK_OBJS. Thanks Bernard. * Releasing dmalloc version 5.5.2. 2007-03-25 Gray Watson <> * Fixed some problems with str[n]dup argument checking. * Releasing dmalloc version 5.5.1. 2007-03-24 Gray Watson <> * Fixed bug where LOG_PNT_SEEN_COUNT set to 0 caused segfault in dmalloc_examine. dmalloc_t was also not handling the setting appropriated. * Fixed bug with the checking of the MAX_FILE_LENGTH. 2007-03-23 Gray Watson <> * Revamped the chunk.c tests for user_pnt space. Added support for strnlen sizing. Added better checking of non-exact user pointers. * Added dmalloc_verify_pnt_strsize to support strnlen size testing. 2007-03-22 Gray Watson <> * Added missing DMALLOC_FUNC_CHECK routines: atoi, atol, memmove * Added a number of special checks for DMALLOC_FUNC_CHECK stuff. * Fixed all of the DMALLOC_FUNC_CHECK arguments thanks to Nickolai. 2007-03-12 Gray Watson <> * Improved some documents after user feedback. Thanks Renny. 2007-02-08 Gray Watson <> * Releasing dmalloc version 5.5.0. 2006-03-27 Gray Watson <> * Fixed a problem with arg-check dmalloc code and check-fence. 2006-03-23 Gray Watson <> * Fixed a section of the manual about Cygwin thanks to Pierre. * Fixed a problem with Cygwin env parsing. Thanks to Pierre and others. 2005-12-21 Gray Watson <> * Added a section on dumping core in the manual. * Added a number of regression tests for the arg-check code. 2005-12-19 Gray Watson <> * Fixed some problems with function argument checking and length arguments. The library was not handling strncmp correctly for example. * Added handling of strndup function. * Added overlapping memory check for memcpy if memmove exists. * Added __FILE__ and __LINE__ arguments to function checks. Not sure why they weren't there earlier. 2005-12-18 Gray Watson <> * Added patches to [hopefully] improve the building under Mac OSX. Thanks to Terry. * Added dmalloc_get_stats function to report on internal heap stats. Thanks to Sam. 2005-12-17 Gray Watson <> * Fixed a problem with the RPM .spec file. 2005-11-30 Gray Watson <> * Fixed a problem with double free not reporting ERROR_ALREADY_FREE. This was confusing. 2005-10-27 Gray Watson <> * Made some changes to the docs to address the possible mmap issues. * Added better checking for mmap compatibility during autoconfig. 2005-10-15 Gray Watson <> * Added a section to the startup docs about the .tgz file extension. 2005-07-26 Gray Watson <> * Improved some of the startup docs and installed a new version of texi2html. The old one was hiding the NOTE entries. 2005-06-05 Gray Watson <> * Improved the usage output for dmalloc. Thanks to murf. * Improved some of the error values to better identify internal dmalloc errors. * Fixed problem where if LARGEST_ALLOCATION is set to 0 the test program still checks it. Whoops. Thanks to sbied. 2005-03-18 Gray Watson <> * Increased the basic block default to 32k. * Fixed some documentation. * Added better error code output in dmalloc_t. * Fixed the global Makefile to install libs as 755 not 644. 2005-01-11 Gray Watson <> * Added some fixes for Compaq's C compiler, some include ordering fixes, and some C++ compiler defines. Thanks Burl. 2004-12-03 Gray Watson <> * Improved dmalloc_t to better detect and test a small heap area. 2004-10-19 Gray Watson <> * Releasing dmalloc version 5.4.2. * Refined the definition of the 'alloc-blank' and 'free-blank' tags. The 'alloc-blank' token clear various parts of the allocation block when it is allocated. The 'free-blank' token clears a pointer when it is freed. * Also, the library was clearing the user spaces of an allocated chunk with the alloc-blank character and the non-user spaces with the free-blank character. This seemed confusing and wrong so now all sections of an allocated chunk are cleared with the alloc-blank character. * Fixed a couple of longer standing stupid bugs via feedback from Philippe. Thanks dude. 2004-10-12 Gray Watson <> * Releasing dmalloc version 5.4.1. * Found and fixed a stupid little test bug so re-released as 5.4.1. * Releasing dmalloc version 5.4.0. * Added return.h support for ARM processors from Silvester Erdeg. * Improved the manual a bit. 2004-09-13 Gray Watson <> * Made allocating zero size chunks the default. 2004-08-13 Gray Watson <> * Fixed some missing ; and a int/unsigned-int bug from feedback from Joe Buehler. * Added return.h support for AIX 4.3 RS/6000 from Joe Buehler. * Added backwards compatibility (ugh) to %d for logfile name. 2004-07-10 Gray Watson <> * Starting release of 5.4.0 with beta. 2004-07-09 Gray Watson <> * Removed force-linear token because made invalid with mmap addition. * Removed the growing up testing and other restrictions for the heap because mmap made it invalid. Drastically reduced the various up and down macros and associated testing. * Added mmap usage inside of the library. Should it be the default? 2004-07-08 Gray Watson <> * Removed auto-seeding of internal random with variable seed. This was creating random addresses for programs making it hard to debug. 2004-07-01 Gray Watson <> * Added bigger and better debugging server section to the manual. * Added header/footer to online manual. 2004-06-29 Gray Watson <> * Really improved the logging of error information about pointers. Better formats, added prev/next for fence post errors, etc.. 2004-06-07 Gray Watson <> * Added return.h support for ia64 machine type from Didier Remy. 2004-04-09 Gray Watson <> * NOTE: next release I should increase the maximum source file length from 10k to 30k or something. * Fixed some typos in the docs and created a new gdb translate return-address section. Thanks Luk. 2004-02-18 Gray Watson <> * Fixed info install with feedback from Matt Fuller. Thanks. 2004-01-31 Gray Watson <> * Added compat and arg_checking of atoi, atol, and memmove. Thanks to Guy (guyresh) for pointing out the omissions. * Added arg checking to internal strdup functions. * Moved argv.c code to use loc_snprintf. 2004-01-28 Gray Watson <> * Releasing dmalloc version 5.3.0. * Fixed a bad bug where calls to _dmalloc_chunk_pnt_check from the arg_check.c functions were not locking. Ugh. Thanks much to Guy (guyresh). * Added dmalloc_verify_pnt function for proper external pointer checking. 2004-01-14 Gray Watson <> * Added a dmalloc_memory_allocated function to assist with the checking of the memory size start feature. * Added automatic checking of the start at file:line, iteration, and memory size features. * Added a --start-size argument to dmalloc to start the library checking the heap after we allocate a certain size of memory. Thanks to andyc_2k. * Added some more documentation about destructors. * Added a check-shutdown token and support to check the pointers heap when we shutdown the library. Thanks to Charles for the idea. 2003-11-23 Gray Watson <> * Added dmalloc_count_changed function plus tests. Thanks to Brian O'Kelley. 2003-11-20 Gray Watson <> * Added some more error code documentation. * Added ability to disable the LARGEST_ALLOCATION setting by defining it to be 0. 2003-11-18 Gray Watson <> * Released dmalloc version 5.2.4. * Fixed bug with check-fence and check-funcs interaction. Thanks to John Hetherington. 2003-11-17 Gray Watson <> * Added support for rc shell. Thanks to Michael Haardt. * Fixed a logfile NULL pointer printf. Thanks to John Hetherington. 2003-10-17 Gray Watson <> * Fleshed out the error code documentation. 2003-10-06 Gray Watson <> * Fixed Makefile.in to properly refer to the documents directory. Whoops. Thanks to Mike Castle. 2003-10-04 Gray Watson <> * Improved the docs about alias creation and usage. 2003-10-01 Gray Watson <> * Added testing for destructors in configure. 2003-09-29 Gray Watson <> * Releasing dmalloc version 5.2.3. 2003-09-12 Gray Watson <> * Added new GetEnvironmentVariableA Cygwin call. Thanks to Rolf Banting. 2003-09-10 Gray Watson <> * Added quick checks for the constructor attribute. 2003-09-09 Gray Watson <> * Removed find_slot function in chunk.c since it was only used once. 2003-09-08 Gray Watson <> * Changed the configure script to define the HAVE_... include defines to 0 or 1. Thanks to Brian Schreder. * Removed usage of environ (duh) from dmalloc_argv.c. Thanks to Brian Schreder. * Added better dmalloc.h processing. 2003-09-08 Gray Watson <> * Releasing dmalloc version 5.2.2. * Added a Cygwin section to the manual. * Added GETENV_SAFE testing for Cygwin environments. * Added a new ERROR_NOT_START_BLOCK (30) errno for addresses which are within an allocation but not pointing to the start of the block. * Worked a bit more on the function pnt checking code after some more feedback from Richard Colley. 2003-09-06 Gray Watson <> * Improved the pnt checking code to properly check free space below and above an allocation. Added regression tests for this. 2003-09-05 Gray Watson <> * Fixed possible lock leak in the shutdown code. Thanks to TJ Saunders. * Fixed bug in function pnt checking code. Not sure when this broke. Thanks to Philippe Roger. 2003-08-04 Gray Watson <> * Removed references to dmalloc leap. 2003-07-23 Gray Watson <> * Changed the installing of libraries to install-data. 2003-07-08 Gray Watson <> * Releasing version 5.2.1. 2003-06-20 Gray Watson <> * Fixed problems with macro arguments not in () thanks to Paul Hurtley. 2003-06-18 Gray Watson <> * Fixed a problem with strdup not returning char *. Thanks to Dan Nelson, Juhani Rautiainen, and Paul Hurtley. 2003-06-10 Gray Watson <> * Releasing version 5.2.0. * Renamed the "max memory space wasted" to "max unused memory space" to indicate that it is not the users fault. * Improved the admin and extern block accounting. * Added PDF doc files to the installation. * Fixed a problem with the global Makefile and dmalloc_t. Thanks to Bert Deknuydt. * Added new logfile expansion of %u as getuid() output. 2003-06-09 Gray Watson <> * Added detection of gethostname() function for %h logpath handling. * Added new logfile process with %h hostname, %t time, %p process-id, and %i for thread-id. * Removed the old logfile % processing. %d, %l, or %u no longer expands to the pid. * Added LOG_PID to drop the pid on each line of the logfile. * Added LOG_REOPEN to reopen the logfile when the pid of the process changes as with a fork. Thanks to James Hawtin. * Renamed the LOG_ITERATION_COUNT to LOG_ITERATION in settings.dist. * Renamed the STORE_SEEN_COUNT to be LOG_PNT_SEEN_COUNT. * Renamed the STORE_ITERATION_COUNT to be LOG_PNT_ITERATION. * Renamed the STORE_TIME to be LOG_PNT_TIME. * Renamed the STORE_TIMEVAL to be LOG_PNT_TIMEVAL. * Renamed the LOG_THREAD_ID to be LOG_PNT_THREAD_ID. * Improved the log_stats and log_changed output. 2003-06-08 Gray Watson <> * Releasing version 5.1.0. * Fixed the FREED_POINTER_DELAY functionality. * Removed PROTECT_BLOCKS from settings.dist because was unused. * Added the tsecs perl script to convert epoch seconds time to ctime output. * Removed the check-lists debug token which was not being used with the new heap organizations. * Fixed the never-reuse functionality and added checks to dmalloc_t for it. * Added checks to dmalloc_t for the realloc-copy functionality. * Fixed a problem where a call to dmalloc_log_changed would wipe out allocate table information. Improved other table functions. * Improved the stats output a bit. * Added additional checks to dmalloc_t for wierd realloc and free problems. 2003-06-06 Gray Watson <> * Expanded the arguments to dmalloc_examine to return more information about the pointer. This was explicitly needed to better test the library's setting of the values. * Found and fixed a problem where the last-used mark was not being set properly. Added checks to dmalloc_t for this. * Found and fixed a bad problem where the leaked memory was not being reported correctly. Very bad. Added checks in dmalloc_t for this. 2003-06-04 Gray Watson <> * Releasing dmalloc version 5.0.2. * Fixed some problems and improved the code in dmalloc_t. * Integrated an internal random number generator since random() often calls malloc. Ugh. 2003-05-22 Gray Watson <> * Removed protection filler to not confuse stuff. 2003-05-21 Gray Watson <> * Improved some of the configure script internals. * Added support for a.exe and other cc output forms for Windoze. 2003-05-20 Gray Watson <> * Releasing dmalloc version 5.0.1. * Updated configure.ac script. * New texinfo.tex macros. 2003-05-19 Gray Watson <> * Added dmalloc_page_size() function. * Improved the auto-testing in dmalloc_t. * Found a [bad] problem with putting pointers back on the free list. * Added some checking of pointers on the free list. * Removed DEBUG_NOT_REMOVABLE and DEBUG_NOT_ADDABLE flags. * Added the per-pointer checking for cleared free memory. * Compressed the per-pointer admin structure by 8 bytes. * Cleaned up the production of dmalloc.h.3 from fillproto file. 2003-05-16 Gray Watson <> * Releasing dmalloc version 5.0.0. 2003-05-14 Gray Watson <> * Removed debug_val.h and error_str.h. * Lots of bugs fixed. * Removed a number of old error codes. 2003-05-13 Gray Watson <> * Deprecated log-blocks and heap-check-map debug tokens. * Removed dmalloc_lp.[ch] stuff. * Added -M --memory-limit argument to dmalloc and ability to limit the library from allocating more than a certain number of bytes. * Getting ready for a huge checkin after a good bunch of work. 2002-06-06 Gray Watson <> * Added a currently in use stats to log-stats. Thanks Bernard. 2002-02-27 Gray Watson <> * Fixed some literal ranlib entries in the Makefile.in thanks to Ralf Fassel. 2002-02-24 Gray Watson <> * Removed the USE_DMALLOC_LEAP functionality. This was causing pains internally and I needed to simplify some of the sections. I apologize for those folks who used this a lot. 2002-02-14 Gray Watson <> * Added a function to close and re-open the dmalloc logfile when you process a new set of environmental flags. * Added a section to the docs about debugging daemon and CGI processes. 2002-01-28 Gray Watson <> * Made some cosmetic improvements to the configure.in script. 2001-11-30 Gray Watson <> * Made free(0L) not an error by default. I've been swayed by public pressure. * Removed short token support. * Did some more work on testing and chunk.c changes. 2001-07-18 Gray Watson <> * Added better autoconf checking of thread libraries to include FreeBSD's non-portable libc_r. Grrr. Thanks to Steve Roberts. 2001-07-12 Gray Watson <> * Added dmalloc_debug_setup function with which you can set the options with a function and not just the environmental variable. * Finally got the main line compiling again. Ugh. Chunk code looks a lot better however. * Before this time I've changed significantly the way the chunk routines account for pointers. Now every pointer has a flags field which says whether fence post checking should be applied to it. 2001-05-23 Gray Watson <> * Renamed _dmalloc_logpath to dmalloc_logpath to match the documentation and dmalloc.h. Thanks Christoph. 2001-05-21 Gray Watson <> * Solved problem with dmalloc_t and no sbrk. * Added INTERNAL_MEMORY_SPACE setting to the settings.dist file to help people with no sbrk function. 2001-03-29 Gray Watson <> * Fixed some additional problems with start-file, start-count, and interval. 2001-03-28 Gray Watson <> * Added the 'How It Works' section to the manual. * Removed necessity of strcat. * Removed use of strcpy internally. * Fixed problem with use of start-count and start-file not disabling the check-heap flag. Mon Feb 26 12:17:25 2001 Gray Watson <> * Releasing dmalloc version 4.8.2. * Installed new configure script to remove C++ requirement. Sun Feb 25 18:58:37 2001 Gray Watson <> * Making major changes to a number of routines. Thu Feb 22 19:24:38 2001 Gray Watson <> * Added more information to heap-check error messages on freed memory overwritten. This is now possible since I unrolled the unions from chunk_loc.h. Thanks to Robert Nielsen for pointing out this oversite. Wed Feb 21 20:16:32 2001 Gray Watson <> * Added strings to identify if the library was compiled with LOCK_THREADS enabled. Thu Nov 30 19:01:10 2000 Gray Watson <> * Added heap checking when we shutdown if check-blank is enabled. This will verify that all of the freed memory was not overwritten. Mon Nov 27 19:01:10 2000 Gray Watson <> * Added a separate ALLOC_BLANK_CHAR and FREE_BLANK_CHAR to the settings.dist file. Now the default 0xc5 character has been replaced with 0xda for dmalloc-allocated memory and 0xdf for dmalloc-freed memory. Tue Nov 14 15:09:02 2000 Gray Watson <> * Releasing dmalloc version 4.8.1. * Added --enable-shlib to configure which enables the building of shared libraries. * Added autoconf handling of the shlibdir for installing of shared libraries. Mon Nov 13 10:47:21 2000 Gray Watson <> * Added improvements to the shared library creation in the Makefile. * Fixed the #ident "..."; semi-colon problem. Thanks to Jonathan. Fri Nov 10 10:27:23 2000 Gray Watson <> * Releasing dmalloc version 4.8.0. Thu Nov 9 19:58:56 2000 Gray Watson <> * Added OpenBSD port information. Hopefully this will be close to Free/Net/... BSD as well. Tue Nov 7 11:39:26 2000 Gray Watson <> * Renamed malloc.h to malloc_funcs.h to avoid system conflicts. * Made log-unknown the default and depreciated the token. Added a log-known token to _only_ report on known (file/line) memory. * Removed INSTALL.1 file because it was basically empty. * Added Troubleshooting section to the INSTALL manual. Tue Oct 10 19:03:14 2000 Gray Watson <> * Did a pre-release of 4.7.2 with the autoconfigure handling for VA Linux release. Thanks guys. * Reorged dmalloc.h.3. Ugh. * malloc_verify and dmalloc_verify now return [D]MALLOC_VERIFY_[NO]ERROR. * Just about every function now initializes the library. This was not the case before with some information routines. * dmalloc_debug now takes an unsigned-int flags and returns the old debug flag value. debug_current now returns an unsigned int flag value. * Added autoconfig handling of #ident. I really hate Unix sometimes for its blatant disregard for anything approaching a standard. Idiots. Wed Sep 13 14:24:46 2000 Gray Watson <> * Fixed a bug in chunk.c found by Ian Badcoe. * Improved the displaying of tokens my dmalloc utility. Tue Jul 25 11:57:49 2000 Gray Watson <> * Releasing dmalloc version 4.7.1. * Fixed problem with check-blank being specified but not free-blank or alloc-blank. I thought I fixed this before. Mon Jul 24 15:30:04 2000 Gray Watson <> * Releasing dmalloc version 4.7.0. * Added support for --disable-cxx and --enable-threads for turning on or off C++ and thread support. Fri Jul 21 17:00:25 2000 Gray Watson <> * Added autoconfiguration code to see if the return macros work for an architecture. * Renamed USE_RET_ADDRESS to USE_RETURN_MACROS in return.h. * Added threaded C++ library support to Makefile. Tue Jun 20 18:30:55 2000 Gray Watson <> * Fixed problems with -p and -m not setting the debug flags. * Added 'force-linear' token and depreciated the 'allow-nonlinear' token. Non-linear heaps really are the default these days (on AIX for example). Now, you can enable the force-linear if you want to ensure a linear heap. Wed May 17 11:29:55 2000 Gray Watson <> * Releasing dmalloc version 4.6.0. * Fixed an incompatibility with the dmalloc_t -r, sbrk, and the DEBUG_ALLOW_NONLINEAR flag. * Improved the implementation of the NEVER_REUSE flag. Found problems with the dmalloc_t -r random debug flag. * Added BUILD.txt instructions to the repository. Tue May 16 14:34:14 2000 Gray Watson <> * Added BLOCK_ROUND macros to heap.h. * Made initial attempt to protect blocks in chunk.c. Got pretty hairy way too fast so backed it out. * Added SET_POINTER macro and cleaned some code. * Completely reworked the internal initialization values for the environmental variables to fix problems pointed out by Carlton Teel. I was doing a (unsigned int)-1. Yuck. * Fixed a bug found by Mcvey where the 1st dblock allocation in a block would not have been found in non-freed memory lists. Yuck. Mon May 15 11:46:21 2000 Gray Watson <> * Moved to 'make cxx' and 'make installcxx' for building and installing the C++ version of the library. * Added autoconfiguration of the presence of a C++ compiler so it will attempt to build and install libdmallocxx.a if it can. * Removed DMALLOC_VERIFY_[NO]ERROR and replaced with DMALLOC_[NO]ERROR. * dmalloc_examine now returns DMALLOC_[NO]ERROR not [NO]ERROR. * Added initial mprotect configuration and stub function to the library. Mon May 8 08:19:45 2000 Gray Watson <> * Renamed dmalloc.cc to dmallocc.cc and added the building of libdmalloc++.a per Dimitri's comments. * Renamed rpm.spec to dmalloc.rpm per Dimitri's comments. Mon May 1 20:34:18 2000 Gray Watson <> * Fixed some more function headers. Tue Apr 18 15:41:30 2000 Gray Watson <> * Releasing dmalloc version 4.5.2. * Added DGUX notes from Takis Psarogiannakopoulos. * Fixed bug in chunk.c pointer checking. Thanks Ezra. Mon Apr 17 21:55:39 2000 Gray Watson <> * Cleaned up some of the compat.[ch] headers to better match reality. Thu Mar 30 10:05:01 2000 Gray Watson <> * Reorganized the dmalloc.texi documentation and moved to using makeinfo program. * Releasing dmalloc version 4.5.1. * Fixed a problem with compilation of dmalloc_lp.c. Thanks Chip. Wed Mar 29 17:40:43 2000 Gray Watson <> * Releasing dmalloc version 4.5.0. Fri Mar 24 16:21:39 2000 Gray Watson <> * Releasing dmalloc version 4.5.0 beta 1. * Added new dmalloc_mark() and dmalloc_log_changed() functions. * Added new BBLOCK_FREE_START and redid some of the block flag checking. Tue Mar 21 13:15:46 2000 Gray Watson <> * Releasing dmalloc version 4.4.0 beta 2. * Removed the stupid old Deansify.pl script. * Added rpm.spec file to the distribution. * Fixed problem with chunk checking of dblock structures. Mon Mar 20 18:19:06 2000 Gray Watson <> * Releasing dmalloc version 4.4.0 beta 1. * Removed usage of PTHREAD_MUTEX_INITIALIZER which was delaying the mutex-init call. * Added code to fix some recursive problems with open and atexit. * Basically encorporated Randell's changes [finally]. Thanks for your patience dude. * Removed the stupid chunk.c unions. Why did I ever do that? It made debugging and absolute bear. * www.dmalloc.com -> dmalloc.com. Mon Mar 6 12:05:01 2000 Gray Watson <> * Added better help messages to dmalloc. Thu Feb 17 09:04:19 2000 Gray Watson <> * Fixed Makefile.dep creation with _th.o special objects. * Fixed the outputting of gratuitous colons. * Added @uref texinfo tags and new texinfo.tex. Mon Nov 8 15:39:44 1999 Gray Watson <> * Releasing dmalloc version 4.3.0. * Fixed some problems with char * instead of void *. Mon Oct 18 12:09:30 1999 Gray Watson <> * Added info about log-unknown to the Getting Started section and more info about ident. Fri Oct 15 18:13:39 1999 Gray Watson <> * Added power pc return.h macros from Shawn. Thu Oct 14 10:08:58 1999 Gray Watson <> * Releasing dmalloc version 4.3.0 beta 3. * Darn. Missed malloc.h in the port file. Wed Oct 13 18:38:26 1999 Gray Watson <> * Releasing dmalloc version 4.3.0 beta 2. * Changed #ifdef USE_DMALLOC_LEAP -> #if USE_DMALLOC_LEAP. Doh. Mon Oct 11 12:37:13 1999 Gray Watson <> * Releasing dmalloc version 4.3.0 beta 1. * Fixed problems on Linux with the strdup macro. Wed Aug 25 08:33:39 1999 Gray Watson <> * Added copyright and url info for ident and what. * Added support for PTHREAD_MUTEX_INITIALIZER. Tue Jul 20 12:47:14 1999 Gray Watson <> * Added USE_DMALLOC_LEAP define in the settings.dist file with which you can enable the leap functionality which previously was the default. Thu Apr 15 10:21:55 1999 Gray Watson <> * Dmalloc now looks in the current directory for .dmallocrc before checking your $HOME directory. * Rewrote a significant piece of the dmalloc utility. Much better code with regards to processing configuration files. Fri Mar 26 17:57:54 1999 Gray Watson <> * Increased the filename size from 40 to 100 characters. Thu Mar 11 17:31:00 1999 Gray Watson <> * Releasing dmalloc version 4.2.0. * Completely reworked the qsort code. Wed Mar 10 11:18:13 1999 Gray Watson <> * Improved the autoconfig of abort and qsort safety. * Fixed hash problem on 64-bit alphas. * Fixed a number of missing prototypes and include problems. * Added QSORT_OKAY switch to configure for linux. * Fixed STDC ifdefs for C++. Thanks Eric. Tue Mar 9 14:26:11 1999 Gray Watson <> * Fixed some problems with threading and the LOG_THREAD_ID ifdef. * Improved the memory table output. Renamed the table files to be dmalloc_tab.[ch] to removed clash with libtable.a. Mon Mar 8 10:50:12 1999 Gray Watson <> * Releasing dmalloc version 4.2.0-beta. * Fixed long standing problem with the NEVER-REUSE token. * Added memory tracking function so the user can register a callback function to be run whenever a memory transaction occurs. Sun Mar 7 17:58:07 1999 Gray Watson <> * Added DUMP_UNFREED_SUMMARY_ONLY variable to the settings.dist file. * Added MEMORY_TABLE_SIZE and MEMORY_TABLE_LOG variables to the settings.dist file. * Fixed problem with valloc exposed by moving to random() from rand(). Grrr. * Added memory table code for grouping of allocated and non-freed memory. Looks great! Thu Mar 4 19:28:45 1999 Gray Watson <> * Removed a number of static variables for string buffers. Yuck. * Removed PERMISSION file and all references to commercial-ness. * Moved to internal sprintf code for snprintf, etc.. * Added dmalloc_message to the exported list of functions. Had to add stdarg.h handling to dmalloc.h. Fri Dec 11 00:04:04 1998 Gray Watson <> * Releasing dmalloc version 4.1.2. * Fixed really bad bug which basically killed pthread support. Mon Nov 16 11:51:39 1998 Gray Watson <> * Releasing dmalloc version 4.1.1. * Fixed signal autoconfiguration. Bad dog. * Releasing dmalloc version 4.1.0. Thu Nov 12 10:08:58 1998 Gray Watson <> * Added HTML versions of the manuals to the releases. * Added FREED_POINTER_DELAY in settings.h which will hold a pointer from being reused for a certain amount of time. * Renamed allow-zero token to be allow-free-null. * Added LOG_TIME_NUMBER and LOG_CTIME_STRING to the settings.dist file for logging times in the logfile. * Disabled the log-thread-id macro. Use the LOG_THREAD_ID define in settings.h to control. * Disabled the log-stamp macro. Use the STORE_TIME define in settings.h to control. Tue Nov 10 12:43:00 1998 Gray Watson <> * Added Jens' cool gdb script and -g (--gdb) flag to dmalloc utility. * Added missing delete[] function to the C++ code. Thanks Jens. Mon Nov 9 11:48:29 1998 Gray Watson <> * Releasing dmalloc version 4.1.0 beta. * Moved some settings from chunk_loc.h into settings.dist. * Improved the handling of free(NULL) and malloc(0) settings. * Added initial memalign support with a error message if the alignment is less than block size which is not currently supported. * Renamed print-error token to print-messages. Wed Oct 28 10:17:13 1998 Gray Watson <> * Increased the default max memory size from 16mb to 64mb. Thu Oct 15 11:06:41 1998 Gray Watson <> * Released dmalloc version 4.0.3. * Moved to #ident for rcs-ids in GCC. * Found and fixed a bug when reallocing a previous valloced section. Not a good idea anyway since it will not preserve the block-aligned status (should it). * Released dmalloc version 4.0.2. * Fixed a problem in return.h and DMALLOC_UNKNOWN_FILE. Ugh. Thanks much to Mike Sacauskis for pointing this out. Thu Oct 8 11:07:25 1998 Gray Watson <> * Released dmalloc version 4.0.1. * Added startup messages acknowledging the thread status. Added error.o to the thread object list. Wed Oct 7 14:52:14 1998 Gray Watson <> * Fixed problem with thread compilation and chunk.c. Thanks much to Didier Verna for pointing out this problem. * Fixed possible race condition with synchronizing with external sbrk calls. Mon Oct 5 22:56:46 1998 Gray Watson <> * Migrated in new argv code. Sun Oct 4 22:56:46 1998 Gray Watson <> * Released dmalloc version 4.0.0. * Updated the manual a bit. * Made a small change to the solaris return.h code. Thanks Alexandre. Tue Sep 29 09:26:50 1998 Gray Watson <> * Releasing dmalloc version 4.0.0 beta2. * Aligned valloc to block alignment as it should have been with fence post checking installed. * Renamed some internal variables and macros better names. Mon Sep 28 17:55:24 1998 Gray Watson <> * Added better auto-configuration of valloc. * Improved the log-trans output messages. * Added the printf attribute to error.c's dmalloc_message. Fixed a number of casting problems. Fri Sep 18 13:37:23 1998 Gray Watson <> * Releasing dmalloc version 4.0.0 beta. * Added recalloc support into the library. Thanks to Nick Albright for suggesting it. * Cleaned up the calloc special handling and accounting. Simplified the local malloc functions in malloc.c. * Added valloc support to the library after it was determined that OSF thread libraries still use the function. memalign will be much harder to add. Thu Sep 17 08:42:14 1998 Gray Watson <> * Improved the pthread autoconfiguration and the code. Removed the gross macro code sections. * Lots of small code improvements. * Got rid of the _dmalloc_file and _dmalloc_line stuff which was _very_ unportable. Thanks Marty for pointed this out. Reduced the race conditions there and improved the handling of default values. * Added FTX return.h information. Thanks to Wim van Duuren. Wed Sep 16 16:28:49 1998 Gray Watson <> * Added direct strdup support to the library with the assocated leap functions. Tue Feb 10 21:12:40 1998 Gray Watson <> * Releasing version 3.3.1 to get rid of the -beta. Sun Dec 21 19:32:02 1997 Gray Watson <> * Shifted some flags to ints instead of longs. * Improved error string handling. Wed Dec 17 08:15:04 1997 Gray Watson <> * Removed allocation macros from the docs and the header. I was not using them anymore and I would think they would be confusing. * Added realloc(pnt, 0) works like free(pnt). Thanks Stefan! Mon Dec 8 04:34:14 1997 Gray Watson <> * Reworked the log_error_info routine's dumping of the fence post areas to properly dumps upper fence post bytes. Mon Dec 8 02:34:14 1997 Gray Watson <> * Releasing dmalloc version 3.3.0. * Fixed problems with pthread locking and various conditions. Added a warning if lock-on is set without allow-nonlinear. Sun Dec 7 21:44:17 1997 Gray Watson <> * Added THREAD_LOCK_INIT_VAL autoconfigure. Fri Dec 5 12:09:26 1997 Gray Watson <> * Performed some long overdue major code cleaning. Added new Lycos {}, int _b for bools, and other stuff. Wed Nov 5 11:25:09 1997 Gray Watson <> * Renamed argv.[ch] to be dmalloc_argv.[ch] to not clash with argv files. Sun Jul 20 00:40:53 1997 Gray Watson <> * Added return address handling for SGI. Thanks James. Mon Jul 7 03:12:28 1997 Gray Watson <> * Added better C++ overload functions. From whom off the Net did I get this from? * Added test for DMALLOC_SIZE unsigned-ness. * Added a FINI_DMALLOC setting to the settings.dist file to support the OSF __fini_ stuff. * Added pthread lock_on -o environmental settings. You will need to have LOCK_THREADS set to 1 in the settings.h file. Sat Mar 22 12:28:45 1997 Gray Watson <> * Added return-address tracking for gcc on alphas. Thanks Alexandre. Fri Mar 21 09:29:46 1997 Gray Watson <> * Released version 3.2.1. * Added to dmalloc the ability to recognize its internal tags. * Added better documentation of auto-dmalloc_shutdown. * Cleaned up some configuration stuff. * Fixed a number of signed/unsigned problems in chunk. Thu Mar 20 15:45:59 1997 Gray Watson <> * Removed autoconf rule in Makefile.all. * Cleaned up pthreads locking delay code. Fri Jan 17 14:25:12 1997 Gray Watson <> * Releasing version 3.2.0. * Added catch-signals debug token (about time, huh Marty?) * Revamped autoconf scripts to be more standard. * New signal handling. Thu Jan 16 15:22:06 1997 Gray Watson <> * Moved to memcpy and memcmp from the b routines. * Fixed the locking for pthread programs. Dumb errors. * Ran new fillproto on h-files. IMPORT -> extern. Thu Dec 28 20:39:00 1995 Gray Watson <> * Releasing version 3.1.3. * Added new argv versions to fix problems. * Don't allow silent dumps of test program. Tue Dec 19 19:11:19 1995 Gray Watson <> * Added registration subdirectory. Mon Nov 20 22:14:14 1995 Gray Watson <> * Removed some unresolved references in argv.c: strcasecmp, strdup. * Fixed some porting problems to Unixware. Unsigned chars. Mon Oct 21 00:23:51 1995 Gray Watson <> * Fixed bug where I called display_pnt instead of display_where. Tue Oct 10 18:43:09 1995 Gray Watson <> * Releasing version 3.1.2. Mon Sep 18 10:14:36 1995 Gray Watson <> * Finally tested fore myself the configure --srcdir option. Found lots of places with missing $(srcdir) entries. Wed Sep 6 13:33:59 1995 Gray Watson <> * Released version 3.1.2-gamma. * Added sbrk handling in the dmalloc_t test program. * Renumbered error values so inserting won't be a problem in the future. Added ERROR_EXTERNAL_HUGE. * Added new argv files. * Fixed up statistics to include external block handling. * Fixed up the external sbrk handling. I broke it with the 3.1.1 version. This re-write is much cleaner. Made some changes to dblock admin handling and heap-check * Re-added THREAD_LOCK definitions to settings.dist. Where did they go? Tue Sep 5 12:38:48 1995 Gray Watson <> * Moved install.sh to install-sh and fixed some Makefile problems. Thanks Francois. * Simplified the heap code a lot. Fixed race conditions. Sun Sep 3 12:50:30 1995 Gray Watson <> * Releasing 3.1.2-beta. * Added configure handling of 32768 page sizes. * Removed stdlib inclusion in dmalloc.h.2 for size_t. * Added some undefs for malloc, etc. for Linux. Thanks Rick. Sat Sep 2 15:34:01 1995 Gray Watson <> * Releasing 3.1.2-alpha. * Added inital thread locking for debugging threaded programs. * New attempts to auto-configure DMALLOC_SIZE for size_t. I've tried this before. We'll have to see what it screws up. * Added settings.dist which is copied by configure. Thanks Marty. Fri Sep 1 15:53:50 1995 Gray Watson <> * Started better autoconfiguring of DMALLOC_SIZE variable. Wed Aug 30 14:05:39 1995 Gray Watson <> * Added dmalloc_aborting flag in case kill or abort recurses. Thanks Stephen. Tue Aug 29 17:43:54 1995 Gray Watson <> * Added new[] C++ function. Thanks Arno. Tue Aug 28 00:00:00 1995 Gray Watson <> * Changed DMALLOC_SIZE to 'unsigned long' instead of unsigned. Fri Aug 18 11:50:03 1995 Gray Watson <> * Releasing version 3.1.1. * Moved all non-linear heap checking to heap code and improved the code immensely (read it works now). * Fixed dumb bug in argv code. * Added handling of NONLINEAR heap by default. Mon Aug 14 10:57:26 1995 Gray Watson <> * Fixed up dmalloc_t to propogate errors better. Thanks Thorsten. Sun Aug 13 16:02:27 1995 Gray Watson <> * Renamed chunk_heap_check to chunk_check. Fri Jul 14 16:58:09 1995 Gray Watson <> * Releasing version 3.1.0. First commercial release. * Added academic references to permissions sections. Wed Jul 5 19:11:03 1995 Gray Watson <> * Released version 3.1.0-beta. Mon Jul 3 19:57:05 1995 Gray Watson <> * Encorporated new configed argv files from version 2.0.1. Wed Jun 28 19:48:47 1995 Gray Watson <> * Improved header file configurations immensely. Removed all casts and other dumb coding assumptions for 64 bit machines. * Fixed dumb sparc preprocesser error. Tue Jun 20 13:56:02 1995 Gray Watson <> * Added commercial license restrictions to library. Mon Jun 19 22:06:12 1995 Gray Watson <> * Changed USE_ABORT to rely on ABORT_OKAY auto-configed setting. * Fixed problem with fence handling and 64 bit longs. * Added lots of comments about internal chunk structures. Tue Jun 13 17:34:02 1995 Gray Watson <> * pulled manual settings out of conf.h to settings.h. Tue May 31 10:30:59 1995 Gray Watson () * Finished version 3.0.7. Released later. Tue May 30 10:30:59 1995 Gray Watson () * Fixed problem with conf.h references before included. * Fixed problems with exit() calls in configure. Thanks Rik. Mon May 15 20:13:10 1995 Gray Watson () * Added error-dump token for dumping-core and continuing on errors. * Added Web pointers to online documentation. * Added abort() auto-configuration for KILL_PROCESS. * Minor fixes. Added an arg to dmalloc_die to be silent. Fri May 12 16:33:44 1995 Gray Watson () * Released version 3.0.6-beta. * Fixed problem with NEVER_REUSE and realloc same block-size. * Fixed up logging of time. Lots of ifdefs. * Added a pointer overhead structure. Fri May 5 11:39:39 1995 Gray Watson () * Renamed a number of chunk fields to remove the use of count. * Logged starting/ending time in logfile. * Added thread-id tracking with conf.h option. * Added pointer-count tracking with conf.h option. * Added interation-count tracking with conf.h option. * Added global/relative time tracking with conf.h option. Fri Mar 31 16:51:52 1995 Gray Watson () * Better tag output from dmalloc -t. * New version of argv files. * Fixed problem with dmalloc -c and start-count. * Added some messages about upcoming errors in dmalloc_t. Thu Mar 23 10:34:33 1995 Gray Watson () * Improved the manual a bit. Phased in some alpha changes. * Added some Next notes to the contrib directory. Need more. Fri Mar 10 13:29:49 1995 Gray Watson () * Added allow-zero token for not minding malloc(0) and free(0L). * Made all chunk.c global counters longs. Fri Mar 3 12:37:17 1995 Gray Watson () * Integrated into new CVS hierarchy. New copyrights. Mon Jan 2 18:51:19 1995 Gray Watson () * Released version 3.0.5. * Changed my mail address and ftp location. Fri Dec 16 15:07:29 1994 Gray Watson () * Fixed some old references to malloc in docs. Thanks Dave. Thu Dec 15 10:25:59 1994 Gray Watson () * Released version 3.0.4. Sat Nov 12 18:05:34 1994 Gray Watson () * Removed message arg to env-get routine due to various probs. * New STDC definitions of DMALLOC_PNT and DMALLOC_FREE_RET. * Removed all STRDUP and BDUP macros. Was anyone using them? Wed Nov 9 15:43:45 1994 Gray Watson () * Upgraded to autoconf 2.1. New configure script. Tue Nov 8 18:54:04 1994 Gray Watson () * Added dying message when malloc_die is called. Thanks Marty. * Reworked the manual a ton. Looks much better. Added Quick-Start + Installation sections. * Lots of changes to notes files. Thu Nov 3 17:25:29 1994 Gray Watson () * Released version 3.0.3. * Added dmalloc.cc C++ file to distribution. * Default is now to build/install a libdmalloclp.a library. Wed Oct 26 21:13:11 1994 Gray Watson () * Removed the log-error tag. Pretty worthless. If you had logpath set then it should log errors. Tue Oct 18 19:54:21 1994 Gray Watson () * Fixed problem with new args clearing all old ones. Sat Oct 15 13:55:16 1994 Gray Watson () * Added dmalloc.h.2 creation to config.status file. Thanks Dave. * Added a startup message with the debug flags used to logfile. Fri Oct 14 18:40:59 1994 Gray Watson () * Fixed dumb errors with FUNC_CHECK code. Thanks Dave. Thu Oct 13 21:25:52 1994 Gray Watson () * Added default tags: default,low,medium,high,all to dmalloc. * Renamed check-free to check-blank but left free for compat. * Made a number of changes from Dave MacKenzie. Reworking the manual fixed the Makefile, RC file, argv, etc... Wed Oct 12 13:00:48 1994 Gray Watson () * Added long/short options to dmalloc and env routines. * Changed some dmalloc options. -T -> -D, -L -> -t. Yeach! * Added better error logging in chunk. Tue Oct 4 13:39:40 1994 Gray Watson () * Added DG/UX code to return.h and atexit code and notes to the distribution. Thanks Joerg. Mon Sep 26 11:59:56 1994 Gray Watson () * Releasing version 3.0.2. * Fixed stupid strtok error in dmallocrc file processing. Mon Sep 26 11:20:17 1994 Gray Watson () * Fixed problems with env code and that sprintf returning (char *) on some archs. DUMB! Wed Sep 21 11:45:19 1994 Gray Watson () * Library now dumps the proper fence-bottom bytes on first pointer error. * Fixed 2 casting problems on OSF. Thanks Dave. Tue Sep 20 13:58:08 1994 Gray Watson () * Releasing version 3.0.1. * Combined all env variables into DMALLOC_OPTIONS. Lots of changes to dmalloc program. Fri Sep 16 14:50:26 1994 Gray Watson () * Added short token strings and values to -T very-verbose output. * Added -n flag to dmalloc program for printing/not-doing actions. Tue Sep 13 11:36:10 1994 Gray Watson () * Added mkinstalldirs to distribution. Thanks Francois. Mon Sep 12 13:12:38 1994 Gray Watson () * Fixed zsh and [t]csh alias messages in documentation. * Added install.sh to distribution. Thanks Francois. Mon Sep 12 10:07:29 1994 Gray Watson () * Renamed _dmalloc_error to dmalloc_error since it is used externally so often. Sorry folks. * Removed time() and getpid() from compat functions. Moved HAVE_... tests into the code that used them. Duhhhh. * Changed DMALLOC_DEBUG_DISABLE flag to DMALLOC_DISABLE. * Fixed some include file auto-include messages. Thanks Francois. Thu Sep 8 10:07:56 1994 Gray Watson () * Releasing version 3.0.0. * Fixed a problem with some list checking via user feedback. Fri Sep 2 17:34:02 1994 Gray Watson () * Fixed possible recursion problem. Thanks Marty. Mon Aug 29 11:08:36 1994 Gray Watson () * Tons of name changes going from malloc_dbg -> dmalloc. Lots of files, internal/external routines, variables, etc. Sat Aug 27 19:33:16 1994 Gray Watson () * Releasing 2.2.1 so I make the name shifts. * Fixed problem with IMPORT in malloc_dbg.3 via user feedback. Mon Aug 8 22:43:44 1994 Gray Watson () * Releasing version 2.2.0. Mon Aug 8 22:29:11 1994 Gray Watson () * Added no-special test option to malloc_t. * Fixed problem with merging adjacent free blocks if last/first block being freed. Wed Aug 3 14:28:20 1994 Gray Watson () * Fixed xmalloc,xrealloc,etc. override functions. * Added xstrdup to the x leap function list. Mon Aug 1 23:03:50 1994 Gray Watson () * Added $verbose checks in configure. Thanks Francois. * Added 'err' label to error printing. Thanks Francois. Fri Jul 22 11:48:26 1994 Gray Watson () * Added ability to combine adjacent free blocks into one. Thu Jul 21 14:44:25 1994 Gray Watson () * 0 or negative MALLOC_INTERVAL values act as if no interval value. * Made a 'malloc_dbg -i 0' undefine MALLOC_INTERVAL. * Fixed calloc return-address problem. Thanks Gregory. * Added KILL_PROCESS macro to configuration scripts. Replaces ERROR_SIGNAL. Thu Jul 10 00:00:00 1994 Gray Watson () * Marty Leisner compiles library on MS-DOG! Sun May 22 18:37:31 1994 Gray Watson () * Fixed some problems with malloc_errno set after call to error. Wed May 11 12:02:31 1994 Gray Watson () * Released version 2.1.0. * Fixed problem with never-reuse going on/off and check-lists. * Added -r (random-debug) option to malloc_t which causes it to constantly change the dmalloc flags while testing. * Fixed VERY nasty bug in realloc with alloc-blank and no realloc-copy token. * Fixed problem with ANSI-C configure on AIX systems. Fri Apr 8 13:51:39 1994 Gray Watson () * Fixed some race conditions with sbrk failure. Thu Apr 7 17:13:31 1994 Gray Watson () * Added some better checking for out-of-range arguments. * Changed heap-error to 0L from -1. * Added -p max-pointers argument to malloc_t. Wed Apr 6 23:02:07 1994 Gray Watson () * Added 'log-nonfree-space' token for logging unfreed memory space. Wed Mar 30 01:03:56 1994 Gray Watson () * Added iteration count label to all logfile output. Fri Mar 25 01:18:55 1994 Gray Watson () * Fixed small recursive problem messing up malloc #2 info. Mon Mar 21 09:58:21 1994 Gray Watson () * Added xmalloc,xrealloc,etc. override functions. Sun Mar 20 14:48:25 1994 Gray Watson () * Added better mechanisms for const definition. Sun Mar 20 11:57:34 1994 Gray Watson () * Renamed token 'log-perror' and 'print-perror' to '...-error'. Wed Mar 2 22:49:18 1994 Gray Watson () * Fixed some spelling and other misc problems. Sun Feb 27 17:53:35 1994 Gray Watson () * New argv files. Fixed Makefile.all.in problem. * Released version 2.0.1. Sun Feb 20 00:39:37 1994 Gray Watson () * Cleaned up a number of configure/compat functions. Fri Feb 18 02:32:53 1994 Gray Watson () * Fixed tons of __STDC__ defines. Finally I hope. * Added more commands to malloc_t to log information, etc. * Released version 2.0.0. * Last minute fixes from Sparc and MIPS boxes. Thu Feb 17 17:47:05 1994 Gray Watson () * Lots of changes to add argv files in place of argv subdir. * added initial support for external block locating. this is going to be a toughy to solve. there is a catch-22 here. Sat Jan 22 01:34:55 1994 Gray Watson () * moved BLOCK_SIZE into malloc_log because its used everywhere. Fri Jan 21 23:45:26 1994 Gray Watson () * added missing checks for ADMIN_FREE in heap_check Wed Jan 19 20:43:05 1994 Gray Watson () * Added a new texinfo.tex macro file. * Renamed CHECK_FREE to CHECK_BLANK internally. * Added 'allow-nonlinear' token to remove special checks. Mon Dec 20 14:14:08 1993 Gray Watson () * Added a -m max-amount flag to malloc_t. * Renamed dbg_tokens.h -> debug_tok.h and dbg_values.h -> debug_val.h Mon Dec 20 02:24:02 1993 Gray Watson () * Added -V option to malloc_dbg and desc field for debug-token list. Sun Dec 19 23:35:53 1993 Gray Watson () * moved the NULLs in malloc_dbg.h to 0L. * added a debugging section to the manual and moved some stuff around. Fri Dec 17 15:02:29 1993 Gray Watson () * fixed some compilation errors with non-STDC systems re Charles Campbell. Mon Dec 6 01:18:29 1993 Gray Watson () * new fence read/write code. much cleaner. new FENCE_TOP define. Tue Nov 30 05:35:39 1993 Gray Watson () * added special tests to malloc_t. cleaned up and tested alloc(0). Mon Nov 29 21:39:54 1993 Gray Watson () * turned num_bits into a macro and condensed log_heap_map. added MAX_SLOTS to chunk. Tue Nov 23 02:39:44 1993 Gray Watson () * fixed heap_check error with free blocks. * Added light and heavy makefile targets for automatic testing. * added -s flag to malloc_t and cleaned up the output. * added realloc test code to malloc_t and immediately had to fix a pretty nasty realloc bug with the new code. * phased in the version 1.3.5 branch changes into the 2.0.0 version. looks like it was reasonably painless. Mon Nov 22 22:21:56 1993 Gray Watson () * Integrated tons of new heap code with per/block allocations (not base 2) and better free list management with block splitting. * Releasing version 1.3.5. * Added more automatic and comprehensive malloc_t testing facilities with argv options. * removed library from linking with malloc_dbg. good idea dave. * integrated some fixes and remove pre-main shit. Mon Nov 15 00:39:51 1993 Gray Watson () * Added -T option to malloc_dbg: list-tokens for listing of debug tokens. * added ERROR_SIGNAL configure entry. defaults to SIGABRT. (NOTE: later removed). Sun Nov 14 23:08:03 1993 Gray Watson () * Added 'never-reuse' token to never reuse free'd memory. Mon Nov 8 05:44:58 1993 Gray Watson () * added ra_info to the contrib directory. Big wow. Wed Nov 3 00:56:19 1993 Gray Watson () * Added check for pre-main calls to malloc. HACK! * Added on_exit and atexit support to auto-call malloc_shutdown. Thanks much to Manfred, Dave, Scott, and Rich. * Added -m (minus) option to malloc_dbg. Why didn't I think of this before? Tue Nov 2 16:45:32 1993 Gray Watson () * Fixed problem with getenv processing. Wed Oct 20 19:30:34 1993 Gray Watson () * Renamed malloc_debug to malloc_flags. * Added all malloc utility functions to malloc_lp.c. Now programs can call malloc_shutdown (for instance) without fear. See malloc_lp.h. Sat Oct 16 19:18:53 1993 Gray Watson () * removed debug token log-ra, log-unknown should be enough. Thu Oct 14 19:48:42 1993 Gray Watson () * malloc_heap_map() -> malloc_log_heap_map() for consistency. Wed Oct 13 17:58:55 1993 Gray Watson () * Added malloc_log_unfreed() to dump non-free memory to logfile. Good for comparing heaps to see differences. * Added -p flag to malloc_dbg to allow adding of tokens to debug value. * added DEBUG_LOG_STAMP to add timestamps to log entries. * Added malloc_log_stats() to dump stats to log file. * Re-added cfree() call. No reason not to have it. Sun Sep 26 14:36:54 1993 Gray Watson () * For new version 2.0.0b. Major changes. Lots of procedures moved around. Rewrote a large part of get_bblocks and removed get_bblock_adm. * Releasing version 1.3.4. * Added -std1 configuration changes and bcopy fixes. * Fixed up the messages to provide more information and to just reflect reality. Some real dumb errors found. * Added malloc_debug_current() and #ifdef STDC instead of #if. Thanks Scott. Wed Sep 22 00:43:54 1993 Gray Watson () * Removed log-bad-pnt. What a dumb token! Unnecessary! Mon Sep 20 20:36:23 1993 Gray Watson () * Releasing version 1.3.3. * Added ALLOW_FREE_NULL defines because of some systems allowing free(0). Yeach! Thanks Dave. Fri Sep 10 17:10:45 1993 Gray Watson () * Fixed debug value changes in mid-stream. Repaired configuration error with memcpy/bcopy and memcmp/bcmp. Thanks Marc. Tue Sep 7 00:49:50 1993 Gray Watson () * Renamed all error codes to ERROR_*. Added ERROR_IS_FREE and changed some of the already-free errors to this. Reworded some error messages and added free's file/line into to log_bad_pnt. Mon Aug 30 17:23:47 1993 Gray Watson () * Added prototypes for _malloc_strcpy, etc. functions to malloc_dbg.h per Scott's comments. Thu Aug 26 19:06:45 1993 Gray Watson () * Released version 1.3.2. Uploaded to the ftp site. * Removed MALLOC_TRACE and malloc_dbg -t. Replaced by MALLOC_ADDRESS:0 functionality and logging of a message every time malloc_address is seen. * Fixed some dumb const problems. Have to now preprocess malloc_dbg.h from start const.h end. Yeach! * Added MALLOC_LOGFILE feature where %d in the string will be replaced with the pid of the process. Had to add getpid to configure and compat. * Fixed some problems with compat.h defines. Tue Aug 24 00:35:49 1993 Gray Watson () * Releasing version 1.3.1. * Added log-ra token to log specific information about non-freed memory with only return-address information (NOTE: later removed). * Added the beginnings of return-address handling. Thanks Dave. Need to resolve some XXX sections in chunk and get more architecture/compiler hacks in return.h. Along the way had to change the malloc_examine() arguments to add ret_attr. * Added -L or --list to malloc_dbg to list all the rc-file tags. * Fixed some problems in chunk.c. Thanks Dave. Renamed malloc_str.[ch] to be arg_check.[ch]. Tue Aug 17 16:22:20 1993 Gray Watson () * Releasing version 1.3.0. * Fixed some ansi compiler problems via patch from Manfred Hauswirth. Thu Aug 12 18:11:01 1993 Gray Watson () * Added MALLOC_TRACE variable and malloc_dbg -t functionality for tracing an address and logging messages about it. NOTE: this was later removed -- replaced by MALLOC_ADDRESS:0. Tue Aug 10 16:43:07 1993 Gray Watson () * Made some minor fixes. Thanks Marc. Mon Jul 26 05:50:27 1993 Gray Watson () * Added some C++ from Peter Miller to the manual. Fri Jul 23 01:36:09 1993 Gray Watson () * Removed LGPL copyright and put in its place fully free software notices. Thu Jul 22 17:35:23 1993 Gray Watson () * _malloc_perror renamed to _malloc_error and made some other minor changes. Tue Jul 20 01:52:02 1993 Gray Watson () * Added smallest_block runtime calculations. Mon Jul 19 12:20:58 1993 Gray Watson () * Made malloc_address exported per Dave's comments so it can be setable by debugger at runtime. * Added Dave's idea of auto-sensing of shell by malloc_dbg. Also added -C option to malloc_dbg to force cshell output. * Removed the dblock checking tokens CHECK_DBLOCK and CHECK_DB_FENCE for a couple different reasons. I never liked them anyway! I also renumbered CHECK_FREE and CHECK_FUNCS in the process. * Fixed a number of int/long problems since Dave is running malloc on a 64 bit alpha. * Made a number of changes to the configure scripts and conf.h per Dave's comments. Added BASIC_BLOCK and ALLOCATION_ALIGNMENT to the auto-config stuff. Fri Jul 16 00:01:31 1993 Gray Watson () * Changed malloc_dbg per new ARGV_MAYBE. Made some various changes from ints to longs per some useful comments from Dave Hill. Tue Jul 13 01:53:32 1993 Gray Watson () * Version 1.2.6 released. * Posting to bsdi. Last minute porting changes. Mon Jul 12 02:03:25 1993 Gray Watson () * Finished new catch-null token. Tue Jul 6 16:04:17 1993 Gray Watson () * Added 'catch-null' token for quitting as soon as we get a sbrk failure (i.e. the swap is full or something) as opposed to returning NULL. Sat Jun 19 14:49:42 1993 Gray Watson () * Minor changes to configuration and notes files. Tue Jun 15 10:29:13 1993 Gray Watson () * Released version 1.2.5. * Made some last minute changes to the manual. Wed Jun 9 15:12:21 1993 Gray Watson () * Fixed small malloc_dbg token bug from Peter Miller. Thu Jun 3 16:01:14 1993 Gray Watson () * Added index to manual, removed shar files in place of Makefile variables. Mon May 24 12:58:06 1993 Gray Watson () * Added -r and -k options for auto-unsetting of variables or keeping of variables with malloc_dbg when setting a tag. * Added const checking to configure and reordered some include files to put conf.h on top. Tue May 18 20:07:41 1993 Gray Watson () * Added log-bad-space token and added expand_buf into chunk.c. * Create log_bad_pnt in chunk. Probably broke stuff. Translated some flag to BIT_FLAG format. * Updated README and started ftp site thanks to Doug Balog. Thu May 13 00:56:39 1993 Gray Watson () * Released version 1.2.4. * Pretty stable now for a while. Trying to get access to a ftp for distribution ease. Thu May 6 11:26:03 1993 Gray Watson () * Added new fix-patch script for myself. Fixed malloc_t by removing LOCAL/EXPORT, etc. Fri Apr 30 15:26:12 1993 Gray Watson () * Removed some heap checks in malloc.c from Bali Jatinder's comments and fixed some of the error strings. * Moved around some defines and changes include ordering. * Added -v option to malloc_dbg to provide verbose output especially for dumping currently set debug tokens from MALLOC_DEBUG variable. Mon Apr 19 16:04:17 1993 Gray Watson () * Released version 1.2.3. * Made some changes to a lot of comments, notes files, and ttd file. Thu Apr 15 17:44:41 1993 Gray Watson () * Renamed malloc.h to malloc_dbg.h and libmalloc.a to libmalloc_dbg.a. Added heap-extension checking and verification to make sure no-one extends the heap using sbrk behind out back. Fixed calloc to have the number of elements be a size_t to (WHY?? It's not a size!!). Fixed malloc_t free problems. Wed Apr 14 18:11:00 1993 Gray Watson () * Released version 1.2.2. * Added some more point checking tests to malloc_str. Added MALLOC_SIZE to some more places. Completely ifdef'ed compat.h. If cannot open logfile, now it complains and continues. Removed stdarg from malloc_dbg. Fri Apr 9 01:50:17 1993 Gray Watson () * Released version 1.2.1. * Made various other changes. Backed out some printf changes. Added SIZE_T defines and fixed up STDC defines. Thu Apr 8 17:41:59 1993 Gray Watson () * Changed to void * internally from char * and put STDC defines in malloc.h for ANSI folks. Why did the ANSI idiots drop the return value from free? Dumb! * Made a number of changes per suggestions from the net. Added some size_t defines for AIX junk (that's right Scott junk). Cut down on the continuation strings, fixed some README and mallocrc goofs, etc. Thanks to all. Tue Apr 6 00:46:45 1993 Gray Watson () * Released version 1.2.0 to comp.sources.unix. * Upgraded to version 1.2.0. Ready for 2nd release to comp.sources.unix. Lots of work on the manual. Mon Apr 5 18:28:05 1993 Gray Watson () * Finished adding token "check-funcs" to check the arguments of some common string functions to see whether they are in the heap. if so it tries to verify that the pointers are good. Sun Apr 4 21:24:45 1993 Gray Watson () * Added token "log-unknown" to dump non-free unknown pointers as well as known ones. Also cleaned up the displaying of the pointers. * comp.sources.unix is almost ready to post so lots of last minute cleanups in the manual, etc. * Started integration of function argument checking. Tue Mar 30 19:36:27 1993 Gray Watson () * Changed malloc.h defines so malloc routines are handled as well as the ALLOC macros. * malloc_dbg program now reports on the token NAME and values. * Added initial string files for string support in the future. * A number of minor changes: fixed gcc compilation problems per Scott's help, combined malloc_lp.h into malloc.h, cleaned most .h and .c files. Fri Mar 26 04:00:14 1993 Gray Watson () * Fixed post 1.1.6 problem with chunk.c. Boy do I need some automated testing tools. Discovered the illusive localtime fence-post error. Had a hard time tracking it down. Maybe due to the fact that the checks were not being made on dblock fence posts before? * Released version 1.1.6 * Found some problems with malloc debug codes. Use of DB_FENCE and CHECK_LISTS and some others were improper. A MALLOC_DEBUG value of 0x403000 would crash all malloc programs. :-) * Added some better comments to all files and cleaned up most files too. Fri Mar 12 18:35:02 1993 Gray Watson () * Released version 1.1.5. Sat Feb 13 17:25:43 1993 Gray Watson () * Finished add a number of const operators to improve coding per scott's recommendations. Sat Jan 30 12:33:43 1993 Gray Watson () * Released version 1.1.4 * Took out the check_vars call inside of malloc_strerror since _malloc_perror calls malloc_strerror which would go quickly recursive. Thanks scott. Tue Jan 5 00:00:00 1993 Gray Watson () * Posted version 1.1.3 shar files to comp.sources.unix. Sat Jan 2 00:16:58 1993 Gray Watson () * Made last minute changes to solve some gcc/ansi errors and to the manual to get things ready for the post. Sun Dec 27 20:28:19 1992 Gray Watson () * Fixed problem with some external functions in malloc.c not resetting the in_alloc flag. Also removed some testing of unsigned variables < 0 in chunk.c per gcc 2.3.3 warnings. * Released version 1.1.3. Mon Dec 21 15:31:50 1992 Gray Watson () * Created the series of shar files in preparation to posting to comp.unix.sources. Looking good. Thu Dec 17 18:33:38 1992 Gray Watson () * Renamed a number of files to comply with the Sys5 12 character restrictions (14 - 2 for RCS/CVS/SCCS). Yeach. malloc_debug -> malloc_dbg. Sat Nov 14 15:59:53 1992 Gray Watson () * Added all external functions to configure and conf.h even though the library assumes that some functions will be resolved. Also upgraded the version number to 1.01gamma (oooooh). * Added print-perror debug token for logging messages to STDERR as well as log-files. Removed stdio from the malloc library to make sure it does not go recursive (alloc for stderr) at a bad time. Wed Nov 11 18:19:49 1992 Gray Watson () * Moved the heap_check calls from chunk.c over to malloc so we can be guaranteed that it gets called only once per user call. chunk's routines often cross-call each other meaning that heap-check was being run 5 times in realloc. YEACH!! Tue Nov 10 17:55:53 1992 Gray Watson () * Added two new debug-tokens: log-blocks and heap-check-map. Also made sure that heap_check was being called from everywhere. Updated the manual and corresponding files. * Added library functions that may not be defined. Updated the conf.h.in and configure.in files to improve confiurability. Upgraded the manual which still needs a lot of work (sigh). Mon Nov 9 19:21:25 1992 Gray Watson () * Added configure, configure.in, conf.h.in, and Makefile.in to try and conform with autoconf specs. What a bear. The documentation for autoconf needs a whole bunch more examples, etc. Sigh. Removed all the MEMORY and STRING defines, etc. Thu Nov 5 22:13:18 1992 Gray Watson () * Released version 1.01b. Sending it off to some folks. * Lots and lots of changes. Translated all programs into non-ansi C dependence and then went back again when I found some problems with my macros. :-) Took out all (and I mean all) Antaire dependencies and defines. Thu Oct 22 00:47:18 1992 Gray Watson () * Ran through most of the debug-flag functionality testing and tweaking. Found some bugs on dblock handling and some messed up logic with the way the LOG flags were working. * malloc_debug is looking good. It now outputs C or Bourne shell code and seems to work in both environments. What do sh folks use in the place of c-shell aliasing? I guess use bash. :-) Wed Oct 21 03:27:35 1992 Gray Watson () * Major changes. I sort of went overboard tonight. I integrated the new malloc_debug program which sets all the debug variables for you. I also added a .mallocrc which you can define with tags exactly the functionality you want to happen. No more levels!! * Did some renaming of files, cleaned up some other things, had to rework a number of items to get new debug flags working. Tue Oct 20 18:06:36 1992 Gray Watson () * Removed useful.h requirements and integrated necessary definitions into malloc.h. * Transferred malloc.txt documentation into malloc.texinfo. Boy is it nifty!! And damn easy!!! * Major changes to improve general machine independence. Added malloc_mach.h. Moved alloc.[ch] to malloc.[ch] for sanity reasons. Tue Oct 13 16:14:17 1992 Gray Watson () * Made various cosmetic changes. Fixed realloc inbound pointer checking per MALLOC_ADDRESS. Fixed problem with MALLOC_ADDRESS initialization to NULL causing free to "find" NULL pointers. :-) * Separated the PERROR debug level and the KILL_SELF level. Now (by default) all memory errors are logged at level 1 and above and malloc kills itself at level 2 and above. Mon Sep 28 23:24:36 1992 Gray Watson () * Added MALLOC_ADDRESS support for free. MALLOC_ADDRESS counts now also apply to frees also. Mon Sep 21 20:39:38 1992 Gray Watson () * Fixed some size problems with bounds checking enabled. * Made free be able to report who freed a pointer. I don't know why this wasn't caught before. free wasn't even using its file/line arguments. Thu Sep 3 03:23:39 1992 Gray Watson () * Added ability to realloc a NULL pointer with an ifdef to disable. Useful in realloc loops where the first time you don't have to alloc it. Fri Aug 14 15:54:03 1992 Gray Watson () * Added a bunch of new environmental variables features: MALLOC_ADDRESS now can have a :# argument. MALLOC_START now has two formats, the old number and new file:line. Looks nice! * Made a pass through chunk.c and fixed a number of problems where debug output pnt/size did not match user-supplied information. * Moved most of the debug variables into alloc.c from chunk.c and added a standardized check_debug_vars() checking routine. Tue Jul 21 16:06:13 1992 Gray Watson () * Fixed malloc count statistics. Removed duplicate malloc_count variable from a number of places. Mon Mar 23 10:49:25 1992 Gray Watson () * Released version 0.04 * New env variable features. Thu Mar 12 19:28:34 1992 Gray Watson () * Fixed a large problem with chunk.c not reporting the correct memory address when listing unfreed memory. This was discovered when MALLOC_ADDRESS was not working correctly. * Started ChangeLog. ------------------------------------------------------------------------------- $Id: ChangeLog,v 1.345 2007/05/14 17:23:42 gray Exp $ ------------------------------------------------------------------------------- dmalloc-5.5.2/config.help000640 001751 001751 00000010071 10622115666 015225 0ustar00graygray000000 000000 This file provides more information about the "configure" script and how you can personalize it for your local environment. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation, and creates the Makefile. It also creates a file `config.status' that you can run in the future to recreate the current configuration. Running `configure' takes a minute or two. While it is running, it prints some messages that tell what it is doing. If you don't want to see the messages, run `configure' with its standard output redirected to `/dev/null'; for example, `./configure >/dev/null'. To compile the package in a different directory from the one containing the source code, you must use a version of make that supports the VPATH variable, such as GNU make. `cd' to the directory where you want the object files and executables to go and run `configure'. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If for some reason `configure' is not in the source code directory that you are configuring, then it will report that it can't find the source code. In that case, run `configure' with the option `--srcdir=DIR', where DIR is the directory that contains the source code. By default, `make install' will install the package's files in /usr/local/bin, /usr/local/lib, /usr/local/man, etc. You can specify an installation prefix other than /usr/local by giving `configure' the option `--prefix=PATH'. Alternately, you can do so by giving a value for the `prefix' variable when you run `make', e.g., make prefix=/usr/gnu You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec_prefix=PATH' or set the `make' variable `exec_prefix' to PATH, the package will use PATH as the prefix for installing programs and libraries. Data files and documentation will still use the regular prefix. Normally, all files are installed using the regular prefix. You can tell `configure' to figure out the configuration for your system, and record it in `config.status', without actually configuring the package (creating `Makefile's and perhaps a configuration header file). To do this, give `configure' the `--no-create' option. Later, you can run `./config.status' to actually configure the package. This option is useful mainly in `Makefile' rules for updating `config.status' and `Makefile'. You can also give `config.status' the `--recheck' option, which makes it re-run `configure' with the same arguments you used before. This is useful if you change `configure'. `configure' ignores any other arguments that you give it. If your system requires unusual options for compilation or linking that `configure' doesn't know about, you can give `configure' initial values for some variables by setting them in the environment. In Bourne-compatible shells, you can do that on the command line like this: CC='gcc -traditional' DEFS=-D_POSIX_SOURCE ./configure The `make' variables that you might want to override with environment variables when running `configure' are: (For these variables, any value given in the environment overrides the value that `configure' would choose:) CC C compiler program. Default is `cc', or `gcc' if `gcc' is in your PATH. INSTALL Program to use to install files. Default is `install' if you have it, `cp' otherwise. (For these variables, any value given in the environment is added to the value that `configure' chooses:) DEFS Configuration options, in the form `-Dfoo -Dbar ...' LIBS Libraries to link with, in the form `-lfoo -lbar ...' If you need to do unusual things to compile the package, we encourage you to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the README so we can include them in the next release. The file `configure.in' is used as a template to create `configure' by a program called `autoconf'. You will only need it if you want to regenerate `configure' using a newer version of `autoconf'. dmalloc-5.5.2/configure.ac000644 001751 001751 00000057410 10622115666 015410 0ustar00graygray000000 000000 # # Process this file with autoconf to produce a configure script. # # Copyright 2003 by Gray Watson # # This file is part of the dmalloc package. # # Permission to use, copy, modify, and distribute this software for # any purpose and without fee is hereby granted, provided that the # above copyright notice and this permission notice appear in all # copies, and that the name of Gray Watson not be used in # advertising or publicity pertaining to distribution of the # document or software without specific, written prior permission. # # Gray Watson makes no representations about the suitability of the # software described herein for any purpose. It is provided "as is" # without express or implied warranty. # # The author may be contacted via http://dmalloc.com/ # # $Id: configure.ac,v 1.37 2007/05/14 17:23:37 gray Exp $ # AC_REVISION($Revision: 1.37 $) AC_INIT(dmalloc, 5.5.2, [http://dmalloc.com/]) AC_CONFIG_SRCDIR(dmalloc.c) AC_CONFIG_HEADER(conf.h) AC_MSG_NOTICE([configurations for the dmalloc library]) ############################################################################## # arguments AC_ARG_ENABLE(cxx, [ AC_HELP_STRING([--disable-cxx], [do not build in C++ support (enabled by default)] ) ], [ # enable_cxx set by default ], [ enable_cxx=yes ] ) AC_ARG_ENABLE(threads, [ AC_HELP_STRING([--enable-threads], [build in thread support (disabled by default)] ) ], [ # enable_threads set by default ], [ enable_threads=no ] ) AC_ARG_ENABLE(shlib, [ AC_HELP_STRING([--enable-shlib], [build shared libraries (disabled by default)] ) ], [ # enable_shlib set by default ], [ enable_shlib=no ] ) ############################################################################## AC_MSG_NOTICE([build utilities]) AC_PROG_CC AC_PROG_CXX # see if we actually have a CXX program if test "$ac_cv_prog_CXX" = "" -o ! -x "$ac_cv_prog_CXX"; then AC_MSG_WARN(could not find C++ compiler $ac_cv_prog_CXX) enable_cxx=no fi # hopefully we have a stdc c-compiler if test "$ac_cv_prog_cc_stdc" = "no" ; then AC_MSG_WARN() AC_MSG_WARN(no ansi compiler. this build may fail.) AC_MSG_WARN() fi AC_PROG_INSTALL AC_PROG_RANLIB AC_C_CONST # we need this for various settings AC_HEADER_STDC AC_CHECK_HEADER([stdarg.h], [AC_DEFINE(HAVE_STDARG_H,1) AC_SUBST([HAVE_STDARG_H],1)], [AC_DEFINE(HAVE_STDARG_H,0) AC_SUBST([HAVE_STDARG_H],0)]) AC_CHECK_HEADER([stdlib.h], [AC_DEFINE(HAVE_STDLIB_H,1) AC_SUBST([HAVE_STDLIB_H],1)], [AC_DEFINE(HAVE_STDLIB_H,0) AC_SUBST([HAVE_STDLIB_H],0)]) AC_CHECK_HEADER([string.h], [AC_DEFINE(HAVE_STRING_H,1) AC_SUBST([HAVE_STRING_H],1)], [AC_DEFINE(HAVE_STRING_H,0) AC_SUBST([HAVE_STRING_H],0)]) AC_CHECK_HEADER([unistd.h], [AC_DEFINE(HAVE_UNISTD_H,1) AC_SUBST([HAVE_UNISTD_H],1)], [AC_DEFINE(HAVE_UNISTD_H,0) AC_SUBST([HAVE_UNISTD_H],0)]) AC_CHECK_HEADER([sys/types.h], [AC_DEFINE(HAVE_SYS_TYPES_H,1) AC_SUBST([HAVE_SYS_TYPES_H],1)], [AC_DEFINE(HAVE_SYS_TYPES_H,0) AC_SUBST([HAVE_SYS_TYPES_H],0)]) AC_CHECK_HEADER([sys/mman.h], [AC_DEFINE(HAVE_SYS_MMAN_H,1) AC_SUBST([HAVE_SYS_MMAN_H],1)], [AC_DEFINE(HAVE_SYS_MMAN_H,0) AC_SUBST([HAVE_SYS_MMAN_H],0)]) ############################################################################### # shared library handling # # check to see where we should install our shared libraries # DONT CACHE in case the change the --prefix # # This is pretty tricky here and should be handled by autoconf # automatically. I try to see if there is a shlib directory # to install by shlibs there. If not I use the $libdir. Some # of the variables have values of '${exec_prefix}' and the like # so the quoting is very important. # # We first try and find the true directory where we are # installing. # if test "x$exec_prefix" = xNONE; then if test "x$prefix" = xNONE; then shlibprefix="$ac_default_prefix" else shlibprefix="$prefix" fi else shlibprefix="$exec_prefix" fi # # Then we see if there is a special shlib directory to use. # if test -d $shlibprefix/shlib; then shlibdir='${exec_prefix}/shlib' else shlibdir="$libdir" fi AC_SUBST(shlibdir) # see how the local system builds shared libraries AC_MSG_CHECKING([shared library link args]) AC_COMPILE_IFELSE([ int foo(int val) { return val + 1; } ],[ # so now we try to create an archive from the compiled .o file (ar cr conftest.a conftest.o) 2>&5 # see which shared-library ld commands work # # Darwin/Mac OS X - Terry Teague # username terry_teague at domain users.sourceforge.net ac_cv_shared_lib_link_objs=no if test `uname` = "Darwin"; then if (ld -dylib -o conftest.so.t -lc conftest.a) 2>&5; then # By convention on some platforms # libLLL.so, libLLL.X.so are symlinks to libLLL.X.Y.Z.so # where X.Y.Z is version # (major.minor.increment) of the library # (API) # For the moment set the Mac OS X dylib compatibility version # to # 1.0 and don't create any symlinks or versioned library names. # Perhaps this could be the version of the dmalloc library # (e.g. 5.4.0) ac_cv_shared_link_args='$(CXX) -dynamiclib -install_name $@ -compatibility_version 1 -current_version 1 -o $@.t' # linking static archives into a dynamic lib doesn't seem to work # explicitly link the object files ac_cv_shared_lib_link_objs=yes else # oh well, toss an error ac_cv_shared_link_args='# Could not configure shlib linking' enable_shlib=no fi elif (ld -shared --whole-archive -soname conftest.so -o conftest.so.t conftest.a) 2>&5; then ac_cv_shared_link_args='ld -shared --whole-archive -soname $@ -o $@.t' elif (ld -shared -o conftest.so.t -all -soname conftest.so.t -none -lc -all conftest.a) 2>&5; then ac_cv_shared_link_args='ld -shared -o $@.t -all -soname $@ -none -lc -all' elif (ld -G -o conftest.so.t conftest.a) 2>&5; then ac_cv_shared_link_args='ld -G -o $@.t' else # oh well, toss an error ac_cv_shared_link_args='# Could not configure shlib linking' enable_shlib=no fi ],[ # oh well, toss an error ac_cv_shared_link_args='# Could not configure shlib linking' enable_shlib=no ]) shlinkargs="$ac_cv_shared_link_args" AC_SUBST(shlinkargs) if test "$ac_cv_shared_lib_link_objs" = "yes"; then AC_MSG_RESULT([$ac_cv_shared_link_args objectfiles...]) else AC_MSG_RESULT([$ac_cv_shared_link_args]) fi ############################################################################### AC_MSG_CHECKING([shared library extension]) if test `uname` = "Darwin"; then # Darwin/Mac OS X - Terry Teague # username terry_teague at domain users.sourceforge.net ac_cv_shared_lib_suffix=dylib else ac_cv_shared_lib_suffix=so fi shlibext="$ac_cv_shared_lib_suffix" AC_MSG_RESULT([$ac_cv_shared_lib_suffix]) AC_SUBST(shlibext) ############################################################################### AC_MSG_CHECKING([C++ support]) if test "$enable_cxx" = "yes"; then AC_SUBST([CXX_ON],[]) AC_SUBST([CXX_OFF],[#]) AC_MSG_RESULT([enabled]) else AC_SUBST([CXX_ON],[#]) AC_SUBST([CXX_OFF],[]) AC_MSG_RESULT([disabled]) fi AC_MSG_CHECKING([thread support]) if test "$enable_threads" = "yes"; then AC_SUBST([TH_ON],[]) AC_SUBST([TH_OFF],[#]) AC_MSG_RESULT([enabled]) else AC_SUBST([TH_ON],[#]) AC_SUBST([TH_OFF],[]) AC_MSG_RESULT([disabled]) fi # shlib support AC_MSG_CHECKING(shlib support) if test "$enable_shlib" = "yes"; then AC_SUBST([SL_ON],[]) AC_SUBST([SL_OFF],[#]) AC_MSG_RESULT(enabled) else AC_SUBST([SL_ON],[#]) AC_SUBST([SL_OFF],[]) AC_MSG_RESULT(disabled) fi ############################################################################### # # check for size_t # AC_TYPE_SIZE_T if test "$ac_cv_type_size_t" = "yes"; then AC_DEFINE(DMALLOC_SIZE,size_t) else AC_DEFINE(DMALLOC_SIZE,unsigned long) fi # # check for unsigned-ness # AC_MSG_CHECKING([dmalloc size unsigned]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_STDLIB_H # include #endif main() { DMALLOC_SIZE x = -1; if (x >= 0) exit(0); else exit(1); } ]])], [AC_DEFINE(DMALLOC_SIZE_UNSIGNED,1) AC_MSG_RESULT([yes])], [AC_DEFINE(DMALLOC_SIZE_UNSIGNED,0) AC_MSG_RESULT([no])], [AC_DEFINE(DMALLOC_SIZE_UNSIGNED,0) AC_MSG_RESULT([no])] ) # # check for strdup macro (linux) # AC_MSG_CHECKING([strdup macro]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #if HAVE_STDLIB_H # include #endif #ifdef strdup main() { exit(0); } #else main() { exit(1); } #endif ]])], [ac_cv_strdup_macro=yes], [ac_cv_strdup_macro=no], [ac_cv_strdup_macro=no] ) AC_MSG_RESULT([$ac_cv_strdup_macro]) # # check for existance of mprotect and associated defines # AC_CHECK_FUNCS(mprotect) AC_MSG_CHECKING([mprotect works]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_MMAN_H # include #endif ]],[[ int prot = PROT_NONE | PROT_READ | PROT_WRITE; (void)mprotect(0, 0, prot); ]])], [ AC_DEFINE(PROTECT_ALLOWED,1) AC_MSG_RESULT([yes]) ], [ AC_DEFINE(PROTECT_ALLOWED,0) AC_MSG_RESULT([no]) ] ) ############################################################################## AC_MSG_NOTICE([important functionality]) AC_CHECK_FUNCS(mmap) AC_CHECK_FUNCS(sbrk) if test x$ac_cv_func_mmap != xyes && x$ac_cv_func_sbrk != xyes; then AC_MSG_WARN() AC_MSG_WARN(no mmap nor sbrk function. See INTERNAL_MEMORY_SPACE in settings.dist.) AC_MSG_WARN() fi AC_MSG_CHECKING([mmap usage]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_MMAN_H # include #endif main() { /* we could open /dev/zero and map to that but I did not want the library to open another file-descriptor */ char *dest, *src, *src_p, *dest_p; src = "0123456789"; dest = (char *)mmap(0L, 10, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1 /* no fd */, 0 /* no offset */); src_p = src; dest_p = dest; while (src_p < src + 10) { *dest_p++ = *src_p++; } src_p = src; dest_p = dest; while (src_p < src + 10) { if (*src_p++ != *dest_p++) { exit(1); } } exit(0); } ]])], [ AC_DEFINE(USE_MMAP, 1) ac_cv_use_mmap=yes], [ AC_DEFINE(USE_MMAP, 0) ac_cv_use_mmap=no], [ AC_DEFINE(USE_MMAP, 0) ac_cv_use_mmap=no] ) AC_MSG_RESULT([$ac_cv_use_mmap]) # # check for basic block size # AC_CHECK_FUNCS(getpagesize) AC_MSG_CHECKING([basic-block size]) ac_cv_page_size=0 if test $ac_cv_page_size = 0; then AC_RUN_IFELSE([main() { if (getpagesize()<=2048) exit(0); else exit(1); }], [ ac_cv_page_size=11 ] ) fi if test $ac_cv_page_size = 0; then AC_RUN_IFELSE([main() { if (getpagesize()<=4096) exit(0); else exit(1); }], [ ac_cv_page_size=12 ] ) fi if test $ac_cv_page_size = 0; then AC_RUN_IFELSE([main() { if (getpagesize()<=8192) exit(0); else exit(1); }], [ ac_cv_page_size=13 ] ) fi if test $ac_cv_page_size = 0; then AC_RUN_IFELSE([main() { if (getpagesize()<=16384) exit(0); else exit(1); }], [ ac_cv_page_size=14 ] ) fi if test $ac_cv_page_size = 0; then ac_cv_page_size=15 fi AC_DEFINE_UNQUOTED([BASIC_BLOCK],[$ac_cv_page_size]) AC_MSG_RESULT([$ac_cv_page_size]) # # data-alignment size... # AC_CHECK_SIZEOF(long) AC_MSG_CHECKING([data-alignment size]) if test $ac_cv_sizeof_long = 4; then # we have to make a special case for sun sparc idiocy ac_cv_data_align=8 else ac_cv_data_align=$ac_cv_sizeof_long fi AC_DEFINE_UNQUOTED([ALLOCATION_ALIGNMENT],[$ac_cv_data_align]) AC_MSG_RESULT([$ac_cv_data_align]) # # check the safety of the abort function # AC_CHECK_FUNCS(abort) AC_MSG_CHECKING([abort safe]) AC_RUN_IFELSE([[ static int main_b = 0; static char heap_mem[102400], *heap_p = heap_mem; free () { if (main_b) _exit(0); } char *malloc (int size) { char *pnt; if (main_b) _exit(0); pnt = heap_p; heap_p += size; return pnt; } char *calloc (int number, int size) { char *start, *pnt, *end; if (main_b) _exit(0); /* it should be already 0s */ start = malloc (number * size); pnt = start; end = start + size; while (pnt < end) { *pnt++ = '\0'; } return start; } char *realloc (char *old_pnt, int new_size) { char *start, *pnt, *end; if (main_b) _exit(0); start = malloc (new_size); pnt = start; end = start + new_size; while (pnt < end) { *pnt++ = *old_pnt++; } return start; } main() { main_b = 1; abort(); _exit(1); } ]], # NOTE: this is reversed because abort core dumps and doesn't exit with # 0 which means that it should fail [ AC_DEFINE(ABORT_OKAY, 0) AC_MSG_RESULT([no]) ], # if it succeeds then something called free on the way out [ AC_DEFINE(ABORT_OKAY, 1) AC_MSG_RESULT([yes]) ], [ AC_DEFINE(ABORT_OKAY, 0) AC_MSG_RESULT([no]) ] ) AC_TYPE_SIGNAL AC_MSG_CHECKING([signal works]) AC_CHECK_HEADER([signal.h], [AC_DEFINE(HAVE_SIGNAL_H,1) AC_SUBST([HAVE_SIGNAL_H],1)], [AC_DEFINE(HAVE_SIGNAL_H,0) AC_SUBST([HAVE_SIGNAL_H],0)]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if HAVE_SIGNAL_H #include #endif ]], [[ (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGTERM, SIG_IGN); ]])], [ AC_DEFINE(SIGNAL_OKAY, 1) AC_MSG_RESULT([yes]) ], [ AC_DEFINE(SIGNAL_OKAY, 0) AC_MSG_RESULT([no]) ] ) # # check the safety of the getenv function # AC_CHECK_FUNCS(getenv) AC_MSG_CHECKING([getenv safe]) AC_RUN_IFELSE([[ static char heap_mem[102400], *heap_p = heap_mem; free (char *pnt) { } char *malloc (int size) { char *pnt; getenv("PATH"); pnt = heap_p; heap_p += size; return pnt; } char *calloc (int number, int size) { char *start, *pnt, *end; getenv("PATH"); /* it should be already 0s */ start = malloc (number * size); pnt = start; end = start + size; while (pnt < end) { *pnt++ = '\0'; } return start; } char *realloc (char *old_pnt, int new_size) { char *start, *pnt, *end; getenv("PATH"); start = malloc (new_size); pnt = start; end = start + new_size; while (pnt < end) { *pnt++ = *old_pnt++; } return start; } main() { malloc(10); _exit(0); } ]], [ AC_DEFINE(GETENV_SAFE, 1) AC_MSG_RESULT([yes]) getenv_safe=yes ], # if it succeeds then something called free on the way out [ AC_DEFINE(GETENV_SAFE, 0) AC_MSG_RESULT([no]) getenv_safe=no ], [ AC_DEFINE(GETENV_SAFE, 1) AC_MSG_RESULT([yes]) getenv_safe=yes ] ) # now check to see if we can replace getenv with GetEnvironmentVariableA AC_CHECK_HEADER([sys/cygwin.h], [AC_DEFINE(HAVE_SYS_CYGWIN_H,1) AC_SUBST([HAVE_SYS_CYGWIN_H],1)], [AC_DEFINE(HAVE_SYS_CYGWIN_H,0) AC_SUBST([HAVE_SYS_CYGWIN_H],0)]) AC_CHECK_HEADER([w32api/windef.h], [AC_DEFINE(HAVE_W32API_WINDEF_H,1) AC_SUBST([HAVE_W32API_WINDEF_H],1)], [AC_DEFINE(HAVE_W32API_WINDEF_H,0) AC_SUBST([HAVE_W32API_WINDEF_H],0)]) AC_CHECK_HEADER([w32api/winbase.h], [AC_DEFINE(HAVE_W32API_WINBASE_H,1) AC_SUBST([HAVE_W32API_WINBASE_H],1)], [AC_DEFINE(HAVE_W32API_WINBASE_H,0) AC_SUBST([HAVE_W32API_WINBASE_H],0)], [[ #if HAVE_W32API_WINDEF_H # include #endif]]) AC_MSG_CHECKING([for GetEnvironmentVariableA]) AC_RUN_IFELSE([[ #if HAVE_SYS_CYGWIN_H # include #endif #if HAVE_STDARG_H # include #endif #if HAVE_W32API_WINDEF_H # include #endif #if HAVE_W32API_WINBASE_H # include #endif main() { char env_buf[256]; GetEnvironmentVariableA("PATH", env_buf, sizeof(env_buf)); } ]], [ AC_DEFINE(HAVE_GETENVIRONMENTVARIABLEA, 1) AC_MSG_RESULT([yes]) have_getenvironmentvariablea=yes ], [ AC_DEFINE(HAVE_GETENVIRONMENTVARIABLEA, 0) AC_MSG_RESULT([no]) have_getenvironmentvariablea=no ], [ AC_DEFINE(HAVE_GETENVIRONMENTVARIABLEA, 1) AC_MSG_RESULT([yes]) have_getenvironmentvariablea=yes ] ) if test x$getenv_safe != xyes && x$have_getenvironmentvariablea != xyes ; then AC_MSG_WARN([Since getenv is not safe, you MUST add the following]) AC_MSG_WARN([code to the front of main():]) AC_MSG_WARN([[ #ifdef DMALLOC]]) AC_MSG_WARN([[ dmalloc_debug_setup(getenv("DMALLOC_OPTIONS"));]]) AC_MSG_WARN([[ #endif]]) AC_MSG_WARN([You will need to compile your program with: -DDMALLOC]) fi ############ # # check for constructor attribute support # AC_MSG_CHECKING([constructor attribute]) AC_RUN_IFELSE([[ /* if we call the loc_con constructor then exit with error code 0 */ static void loc_con() __attribute__((constructor)); static void loc_con() { exit(0); } int main() { exit(1); } ]], [ AC_DEFINE(CONSTRUCTOR_WORKS, 1) AC_MSG_RESULT([yes]) ], [ AC_DEFINE(CONSTRUCTOR_WORKS, 0) AC_MSG_RESULT([no]) ], [ AC_DEFINE(CONSTRUCTOR_WORKS, 1) AC_MSG_RESULT([yes]) ] ) # # check for destructor attribute support # AC_MSG_CHECKING([destructor attribute]) AC_RUN_IFELSE([[ /* if we call the loc_decon destructor then exit with error code 0 */ static void loc_decon() __attribute__((destructor)); static void loc_decon() { exit(0); } int main() { return 1; } ]], [ AC_DEFINE(DESTRUCTOR_WORKS, 1) AC_MSG_RESULT([yes]) destructor_works=yes ], [ AC_DEFINE(DESTRUCTOR_WORKS, 0) AC_MSG_RESULT([no]) destructor_works=no ], [ AC_DEFINE(DESTRUCTOR_WORKS, 1) AC_MSG_RESULT([yes]) destructor_works=yes ], ) ############################################################################## # # check if the return.h macros work # AC_MSG_CHECKING([return.h macros work]) AC_RUN_IFELSE([ #define __CONF_H__ #define USE_RETURN_MACROS 1 #define RETURN_MACROS_WORK 1 #include "return.h" static void foo (void) { char *ret_addr; GET_RET_ADDR(ret_addr); } main() { foo(); exit(0); } ], [ AC_DEFINE(RETURN_MACROS_WORK, 1) AC_MSG_RESULT([yes]) ], [ AC_DEFINE(RETURN_MACROS_WORK, 0) AC_MSG_RESULT([no]) ], [ AC_DEFINE(RETURN_MACROS_WORK, 0) AC_MSG_RESULT([no]) ] ) ############################################################################## # # check to see if ident workds # AC_MSG_CHECKING([if ident works]) AC_COMPILE_IFELSE([ #ident "$Id: configure.ac,v 1.37 2007/05/14 17:23:37 gray Exp $" static void foo (void) { } ], [AC_DEFINE(IDENT_WORKS, 1) AC_MSG_RESULT([yes])], [AC_DEFINE(IDENT_WORKS, 0) AC_MSG_RESULT([no])] ) ############################################################################## AC_MSG_NOTICE([pthread particulars]) XX_OLD_LIBS=$LIBS AC_SEARCH_LIBS(pthread_mutex_init, pthread pthreads c_r) AC_CHECK_HEADER([pthread.h], [AC_DEFINE(HAVE_PTHREAD_H,1) AC_SUBST([HAVE_PTHREAD_H],1)], [AC_DEFINE(HAVE_PTHREAD_H,0) AC_SUBST([HAVE_PTHREAD_H],0)]) AC_CHECK_HEADER([pthreads.h], [AC_DEFINE(HAVE_PTHREADS_H,1) AC_SUBST([HAVE_PTHREADS_H],1)], [AC_DEFINE(HAVE_PTHREADS_H,0) AC_SUBST([HAVE_PTHREADS_H],0)]) AC_CHECK_FUNCS(pthread_mutex_init pthread_mutex_lock pthread_mutex_unlock) AC_MSG_CHECKING([pthread mutex type]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if HAVE_PTHREAD_H # include #endif #if HAVE_PTHREADS_H # include #endif ]],[[ pthread_mutex_t dmalloc_mutex; ]])], [AC_DEFINE(THREAD_MUTEX_T,pthread_mutex_t) AC_MSG_RESULT([pthread_mutex_t])], [AC_MSG_RESULT([unknown])] ) AC_MSG_CHECKING([pthread attribute initialization]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if HAVE_PTHREAD_H # include #endif #if HAVE_PTHREADS_H # include #endif ]], [[ THREAD_MUTEX_T dmalloc_mutex; pthread_mutex_init(&dmalloc_mutex, pthread_mutexattr_default); ]])], [AC_DEFINE(THREAD_LOCK_INIT_VAL,pthread_mutexattr_default) AC_MSG_RESULT([pthread_mutexattr_default])], [AC_DEFINE(THREAD_LOCK_INIT_VAL,0) AC_MSG_RESULT([0])] ) LIBS=$XX_OLD_LIBS ############################################################################## AC_MSG_NOTICE([functions]) # auto-shutdown functions AC_CHECK_FUNCS(atexit on_exit) if test $ac_cv_func_atexit = no \ && test $ac_cv_func_on_exit = no \ && test $destructor_works = no; then AC_MSG_WARN() AC_MSG_WARN(The library cannot automatically shut itself down without) AC_MSG_WARN(atexit, on_exit, or destructor support. You will need to) AC_MSG_WARN(call dmalloc_shutdown directly before exit to get get the) AC_MSG_WARN(final statistics and unfreed memory information.) AC_MSG_WARN() fi # other bells and whistles AC_CHECK_FUNCS(fork gethostname getpid getuid time ctime) AC_CHECK_FUNCS(vprintf snprintf vsnprintf) AC_CHECK_FUNCS(recalloc memalign valloc) # required although we have code for them in compat.c AC_CHECK_FUNCS(memcmp memcpy memmove memset) AC_CHECK_FUNCS(strchr strrchr) AC_CHECK_FUNCS(strlen strcmp strcpy strsep) ############################################################################## AC_MSG_NOTICE([various functions for argv files]) # NOTE: some duplicated from above AC_CHECK_FUNCS(atoi atol getenv) AC_CHECK_FUNCS(strchr strcmp strcpy strlen strncmp strncpy strsep) ############################################################################## AC_MSG_NOTICE([various functions for argument checking]) # NOTE: some duplicated from above AC_CHECK_FUNCS(atoi atol) AC_CHECK_FUNCS(bcmp bcopy bzero) AC_CHECK_FUNCS([[index]]) AC_CHECK_FUNCS(memccpy memchr memcmp memcpy memmove memset) AC_CHECK_FUNCS(rindex) AC_CHECK_FUNCS(strcasecmp strcat strchr strcmp strcpy strcspn strlen) AC_CHECK_FUNCS(strncasecmp strncat strncmp strncpy) AC_CHECK_FUNCS(strpbrk strrchr strspn strstr strtok) AC_CONFIG_FILES(Makefile) AC_CONFIG_COMMANDS([dmalloc.h.2], [ newfile=dmalloc.h.2 rm -f $newfile.t echo '/* this is dmalloc.h.2 */' > $newfile.t echo '/* produced by configure, inserted into dmalloc.h */' >> $newfile.t echo '' >> $newfile.t if test "$ac_cv_c_const" = "yes"; then echo '/* const is available */' >> $newfile.t else echo '/* const is not available */' >> $newfile.t echo '#ifndef const' >> $newfile.t echo '#define const' >> $newfile.t echo '#endif' >> $newfile.t fi if test "$ac_cv_strdup_macro" = "yes"; then echo '/* strdup is a macro */' >> $newfile.t echo '#define DMALLOC_STRDUP_MACRO' >> $newfile.t else echo '/* strdup is not a macro */' >> $newfile.t echo '#undef DMALLOC_STRDUP_MACRO' >> $newfile.t fi echo '' >> $newfile.t echo '/*' >> $newfile.t echo ' * the definition of DMALLOC_SIZE' >> $newfile.t echo ' *' >> $newfile.t echo ' * NOTE: some architectures have malloc, realloc, etc.' >> $newfile.t echo ' * using unsigned instead of unsigned long. You may' >> $newfile.t echo ' * have to edit this by hand to fix any compilation' >> $newfile.t echo ' * warnings or errors.' >> $newfile.t echo ' */' >> $newfile.t if test "$ac_cv_type_size_t" = "yes"; then echo "#include " >> $newfile.t echo "#define DMALLOC_SIZE size_t" >> $newfile.t else echo "/* no include file needed */" >> $newfile.t echo "#define DMALLOC_SIZE unsigned long" >> $newfile.t fi echo '' >> $newfile.t echo '/*' >> $newfile.t echo ' * We use stdarg.h for the dmalloc_message and' >> $newfile.t echo ' * dmalloc_vmessage functions.' >> $newfile.t echo ' */' >> $newfile.t if test "$ac_cv_header_stdarg_h" = "yes"; then echo "#include " >> $newfile.t echo "#define DMALLOC_STDARG 1" >> $newfile.t else echo "/* no stdarg.h available */" >> $newfile.t echo "#define DMALLOC_STDARG 0" >> $newfile.t fi echo '' >> $newfile.t if cmp -s $newfile $newfile.t 2>/dev/null; then AC_MSG_NOTICE([$newfile is unchanged]) rm -f $newfile.t else rm -f $newfile mv $newfile.t $newfile fi ], [ # initialization commands ac_cv_c_const=$ac_cv_c_const ac_cv_strdup_macro=$ac_cv_strdup_macro ac_cv_type_size_t=$ac_cv_type_size_t ac_cv_header_stdarg_h=$ac_cv_header_stdarg_h ]) AC_CONFIG_COMMANDS([settings.h], [ newfile=settings.h rm -f $newfile.t echo '/*' > $newfile.t echo ' * WARNING: this file was produced from settings.dist' >> $newfile.t echo ' * by the configure program. The configure script, when' >> $newfile.t echo ' * run again, will overwrite changed made here.' >> $newfile.t echo ' */' >> $newfile.t echo '' >> $newfile.t cat $srcdir/settings.dist >> $newfile.t if cmp -s $newfile.t $newfile 2>/dev/null; then AC_MSG_NOTICE([$newfile is unchanged]) rm -f $newfile.t else rm -f $newfile mv $newfile.t $newfile fi ]) AC_OUTPUT AC_MSG_NOTICE([]) AC_MSG_NOTICE([Please check-out Makefile and conf.h to make sure that]) AC_MSG_NOTICE([sane configuration values were a result.]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([You may want to change values in settings.h before]) AC_MSG_NOTICE([running 'make'.]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([To run the basic library tests, you can execute:]) AC_MSG_NOTICE([ make light]) AC_MSG_NOTICE([or]) AC_MSG_NOTICE([ make heavy]) AC_MSG_NOTICE([]) dmalloc-5.5.2/Makefile.in000640 001751 001751 00000034106 10622115666 015160 0ustar00graygray000000 000000 ############################################################################### # @configure_input@ # Makefile for the DMalloc library. # $Id: Makefile.all.in,v 1.133 2007/05/14 17:13:45 gray Exp $ ############################################################################### # default root installation directory prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ VPATH = @srcdir@ bindir = @bindir@ libdir = @libdir@ shlibdir = @shlibdir@ includedir = @includedir@ docdir = $(prefix)/share/doc/$(MODULE) # default c-compiler CC = @CC@ CXX = @CXX@ DEFS = -DHAVE_STDARG_H=@HAVE_STDARG_H@ \ -DHAVE_STDLIB_H=@HAVE_STDLIB_H@ \ -DHAVE_STRING_H=@HAVE_STRING_H@ \ -DHAVE_UNISTD_H=@HAVE_UNISTD_H@ \ -DHAVE_SYS_MMAN_H=@HAVE_SYS_MMAN_H@ \ -DHAVE_SYS_TYPES_H=@HAVE_SYS_TYPES_H@ \ -DHAVE_W32API_WINBASE_H=@HAVE_W32API_WINBASE_H@ \ -DHAVE_W32API_WINDEF_H=@HAVE_W32API_WINDEF_H@ \ -DHAVE_SYS_CYGWIN_H=@HAVE_SYS_CYGWIN_H@ \ -DHAVE_SIGNAL_H=@HAVE_SIGNAL_H@ \ $(DEFINES) INCS = -I. -I$(srcdir) $(INCLUDES) LIBS = -L. @LIBS@ A_OUT = aout@EXEEXT@ MODULE = dmalloc LIBRARY = lib$(MODULE).a # thread version of the library LIB_TH = lib$(MODULE)th.a LIB_TH_SL = lib$(MODULE)th.@shlibext@ @TH_ON@BUILD_ALL_1 = threads @TH_ON@INSTALL_LIB_1 = installth @SL_ON@BUILD_THREADS_1 = $(LIB_TH_SL) @SL_ON@INSTALL_THREADS_1 = installthsl @TH_ON@@SL_ON@BUILD_ALL_2 = $(LIB_TH_SL) @TH_ON@@SL_ON@INSTALL_LIB_2 = installthsl # C++ version of the library LIB_CXX = lib$(MODULE)xx.a LIB_CXX_SL = lib$(MODULE)xx.@shlibext@ @CXX_ON@BUILD_ALL_3 = $(LIB_CXX) @CXX_ON@INSTALL_LIB_3 = installcxx @SL_ON@BUILD_CXX_3 = $(LIB_CXX_SL) @SL_ON@INSTALL_CXX_3 = installcxxsl @CXX_ON@@SL_ON@BUILD_ALL_4 = $(LIB_CXX_SL) @CXX_ON@@SL_ON@INSTALL_LIB_4 = installcxxsl # threads + C++ LIB_TH_CXX = lib$(MODULE)thcxx.a LIB_TH_CXX_SL = lib$(MODULE)thcxx.@shlibext@ @TH_ON@@CXX_ON@BUILD_ALL_5 = $(LIB_TH_CXX) @TH_ON@@CXX_ON@INSTALL_LIB_5 = installthcxx @TH_ON@BUILD_CXX_5 = $(LIB_TH_CXX) @TH_ON@INSTALL_CXX_5 = installthcxx @CXX_ON@BUILD_THREADS_5 = $(LIB_TH_CXX) @CXX_ON@INSTALL_THREADS_5 = installthcxx @TH_ON@@CXX_ON@@SL_ON@BUILD_ALL_6 = $(LIB_TH_CXX_SL) @TH_ON@@CXX_ON@@SL_ON@INSTALL_LIB_6 = installthcxxsl @TH_ON@@SL_ON@BUILD_CXX_6 = $(LIB_TH_CXX_SL) @TH_ON@@SL_ON@INSTALL_CXX_6 = installthcxxsl @CXX_ON@@SL_ON@BUILD_THREADS_6 = $(LIB_TH_CXX_SL) @CXX_ON@@SL_ON@INSTALL_THREADS_6 = installthcxxsl # shared versions of the libraries LIB_SL = lib$(MODULE).@shlibext@ @SL_ON@BUILD_ALL_7 = $(LIB_SL) @SL_ON@INSTALL_LIB_7 = installsl @SL_ON@BUILD_TH_CXX_7 = $(LIB_TH_CXX_SL) @SL_ON@INSTALL_TH_CXX_7 = installthcxxsl @TH_ON@BUILD_SL_7 = $(LIB_TH_SL) @TH_ON@INSTALL_SL_7 = installthsl @CXX_ON@BUILD_SL_8 = $(LIB_CXX_SL) @CXX_ON@INSTALL_SL_8 = installcxxsl @TH_ON@@CXX_ON@BUILD_SL_9 = $(LIB_TH_CXX_SL) @TH_ON@@CXX_ON@INSTALL_SL_9 = installthcxxsl # now construct our build and install targets BUILD_ALL = dmalloc.h $(LIBRARY) $(UTIL) \ $(BUILD_ALL_1) $(BUILD_ALL_2) $(BUILD_ALL_3) $(BUILD_ALL_4) \ $(BUILD_ALL_5) $(BUILD_ALL_6) $(BUILD_ALL_7) $(BUILD_ALL_8) INSTALL_LIB = $(LIBRARY) \ $(INSTALL_LIB_1) $(INSTALL_LIB_2) $(INSTALL_LIB_3) $(INSTALL_LIB_4) \ $(INSTALL_LIB_5) $(INSTALL_LIB_6) $(INSTALL_LIB_7) $(INSTALL_LIB_8) BUILD_THREADS = $(LIB_TH) \ $(BUILD_THREADS_1) $(BUILD_THREADS_2) $(BUILD_THREADS_3) \ $(BUILD_THREADS_4) $(BUILD_THREADS_5) $(BUILD_THREADS_6) INSTALL_THREADS = $(LIB_TH) \ $(INSTALL_THREADS_1) $(INSTALL_THREADS_2) $(INSTALL_THREADS_3) \ $(INSTALL_THREADS_4) $(INSTALL_THREADS_5) $(INSTALL_THREADS_6) BUILD_CXX = $(LIB_CXX) \ $(BUILD_CXX_1) $(BUILD_CXX_2) $(BUILD_CXX_3) $(BUILD_CXX_4) \ $(BUILD_CXX_5) $(BUILD_CXX_6) $(BUILD_CXX_7) $(BUILD_CXX_8) INSTALL_CXX = $(LIB_CXX) \ $(INSTALL_CXX_1) $(INSTALL_CXX_2) $(INSTALL_CXX_3) $(INSTALL_CXX_4) \ $(INSTALL_CXX_5) $(INSTALL_CXX_6) $(INSTALL_CXX_7) $(INSTALL_CXX_8) BUILD_TH_CXX = $(LIB_TH_CXX) \ $(BUILD_TH_CXX_1) $(BUILD_TH_CXX_2) $(BUILD_TH_CXX_3) \ $(BUILD_TH_CXX_4) $(BUILD_TH_CXX_5) $(BUILD_TH_CXX_6) \ $(BUILD_TH_CXX_7) $(BUILD_TH_CXX_8) $(BUILD_TH_CXX_9) INSTALL_TH_CXX = $(LIB_TH_CXX) \ $(INSTALL_TH_CXX_1) $(INSTALL_TH_CXX_2) $(INSTALL_TH_CXX_3) \ $(INSTALL_TH_CXX_4) $(INSTALL_TH_CXX_5) $(INSTALL_TH_CXX_6) \ $(INSTALL_TH_CXX_7) $(INSTALL_TH_CXX_8) $(INSTALL_TH_CXX_9) BUILD_SL = $(LIB_SL) \ $(BUILD_SL_1) $(BUILD_SL_2) $(BUILD_SL_3) $(BUILD_SL_4) \ $(BUILD_SL_5) $(BUILD_SL_6) $(BUILD_SL_7) $(BUILD_SL_8) \ $(BUILD_SL_9) INSTALL_SL = $(LIB_SL) \ $(INSTALL_SL_1) $(INSTALL_SL_2) $(INSTALL_SL_3) $(INSTALL_SL_4) \ $(INSTALL_SL_5) $(INSTALL_SL_6) $(INSTALL_SL_7) $(INSTALL_SL_8) \ $(INSTALL_SL_9) UTIL = $(MODULE) HTMLFILE = $(MODULE).html TEXIFILE = $(MODULE).texi PDFFILE = $(MODULE).pdf DOCFILES = $(HTMLFILE) $(TEXIFILE) $(PDFFILE) CCFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ ############################################################################### # End of system configuration section. ############################################################################### SHELL = /bin/sh HFLS = dmalloc.h OBJS = arg_check.o compat.o dmalloc_rand.o dmalloc_tab.o env.o heap.o NORMAL_OBJS = chunk.o error.o malloc.o THREAD_OBJS = chunk_th.o error_th.o malloc_th.o CXX_OBJS = dmallocc.o CFLAGS = $(CCFLAGS) TEST = $(MODULE)_t TEST_FC = $(MODULE)_fc_t all : $(BUILD_ALL) @TH_OFF@ @echo "To make the thread version of the library type 'make threads'" @CXX_OFF@ @echo "To make the C++ version of the library type 'make cxx'" @SL_OFF@ @echo "To make the shared version of the library type 'make shlib'" clean : rm -f $(A_OUT) core *.o *.t rm -f $(LIBRARY) $(LIB_TH) $(LIB_CXX) $(LIB_TH_CXX) $(TEST) $(TEST_FC) rm -f $(LIB_TH_SL) $(LIB_CXX_SL) $(LIB_TH_CXX_SL) $(LIB_SL) rm -f $(UTIL) dmalloc.h realclean : clean distclean : clean rm -f confdefs.h config.status config.log config.cache conf.h rm -f configure.lineno rm -rf autom4te.cache rm -f Makefile settings.h dmalloc.h.2 # rm -f configure installdirs : $(srcdir)/mkinstalldirs $(includedir) $(libdir) $(bindir) installincs : $(HFLS) $(srcdir)/mkinstalldirs $(includedir) $(INSTALL_DATA) $(HFLS) $(includedir) installthsl : $(LIB_TH_SL) $(srcdir)/mkinstalldirs $(libdir) $(INSTALL_PROGRAM) $(LIB_TH_SL) $(libdir) installth : $(INSTALL_THREADS) $(srcdir)/mkinstalldirs $(libdir) $(INSTALL_PROGRAM) $(LIB_TH) $(libdir) @CXX_OFF@ @echo "Enter 'make installthcxx' to install the threaded C++ library" @SL_OFF@ @echo "Enter 'make installthsl' to install the threaded shared-library" installthcxxsl : $(LIB_TH_CXX_SL) $(srcdir)/mkinstalldirs $(shlibdir) $(INSTALL_PROGRAM) $(LIB_TH_CXX_SL) $(shlibdir) installthcxx : $(INSTALL_TH_CXX) $(srcdir)/mkinstalldirs $(libdir) $(INSTALL_PROGRAM) $(LIB_TH_CXX) $(libdir) @SL_OFF@ @echo "Enter 'make installthcxxsl' to install the threaded C++ shared-library" installcxxsl : $(LIB_CXX_SL) $(srcdir)/mkinstalldirs $(libdir) $(INSTALL_PROGRAM) $(LIB_CXX_SL) $(libdir) installcxx : $(INSTALL_CXX) $(srcdir)/mkinstalldirs $(libdir) $(INSTALL_PROGRAM) $(LIB_CXX) $(libdir) @TH_OFF@ @echo "Enter 'make installthcxx' to install the threaded C++ library" @SL_OFF@ @echo "Enter 'make installcxxsl' to install the C++ shared-library" installsl : $(LIB_SL) $(srcdir)/mkinstalldirs $(shlibdir) $(INSTALL_PROGRAM) $(LIB_SL) $(shlibdir) @CXX_OFF@ @echo "Enter 'make installcxxsl' to install the C++ shared-library" @TH_OFF@ @echo "Enter 'make installthsl' to install thread shared-library" installlib : $(INSTALL_LIB) $(srcdir)/mkinstalldirs $(libdir) $(INSTALL_PROGRAM) $(LIBRARY) $(libdir) @RANLIB@ $(libdir)/$(LIBRARY) @SL_OFF@ @echo "Enter 'make installsl' to install $(LIB_SL) in $(shlibdir)" @CXX_OFF@ @echo "Enter 'make installcxx' to install the C++ library" @TH_OFF@ @echo "Enter 'make installth' to install thread library" installdocs : $(srcdir)/docs/$(HTMLFILE) $(srcdir)/docs/$(TEXIFILE) \ $(srcdir)/docs/$(PDFFILE) $(srcdir)/mkinstalldirs $(docdir) $(INSTALL_DATA) $(srcdir)/docs/$(HTMLFILE) $(docdir) $(INSTALL_DATA) $(srcdir)/docs/$(TEXIFILE) $(docdir) $(INSTALL_DATA) $(srcdir)/docs/$(PDFFILE) $(docdir) install : installincs installlib $(UTIL) $(srcdir)/mkinstalldirs $(bindir) $(INSTALL_PROGRAM) $(UTIL) $(bindir) @echo "Enter 'make installdocs' to install $(DOCFILES) in $(docdir)" dmalloc.h.2 : $(srcdir)/configure $(SHELL) $(srcdir)/configure -touch $@ settings.h : $(srcdir)/settings.dist $(srcdir)/configure $(SHELL) $(srcdir)/configure -touch $@ dmalloc.h : $(srcdir)/dmalloc.h.1 dmalloc.h.2 $(srcdir)/dmalloc.h.3 rm -f $@ $@.t cat $(srcdir)/dmalloc.h.1 dmalloc.h.2 $(srcdir)/dmalloc.h.3 > $@.t mv $@.t $@ shlib : $(BUILD_SL) @TH_OFF@ @echo "To make the thread version of the library type 'make threads'" @CXX_OFF@ @echo "To make the C++ version of the library type 'make cxx'" # NOTE: you may have to edit the configure.ac script to get this to # work on your operating system. Please send feedback to the author # via: http://256.com/gray/email.html $(LIB_SL) : $(LIBRARY) rm -f $@ $@.t @shlinkargs@ $(LIBRARY) $(OBJS) $(NORMAL_OBJS) mv $@.t $@ $(LIBRARY) : $(OBJS) $(NORMAL_OBJS) ar cr $@ $? @RANLIB@ $@ $(LIB_TH) : $(OBJS) $(THREAD_OBJS) ar cr $@ $? @RANLIB@ $@ $(LIB_TH_SL) : $(LIB_TH) rm -f $@ $@.t @shlinkargs@ $(LIB_TH) $(OBJS) $(THREAD_OBJS) mv $@.t $@ $(LIB_CXX) : $(OBJS) $(NORMAL_OBJS) $(CXX_OBJS) ar cr $@ $? @RANLIB@ $@ $(LIB_CXX_SL) : $(LIB_CXX) rm -f $@ $@.t @shlinkargs@ $(LIB_CXX) $(OBJS) $(NORMAL_OBJS) $(CXX_OBJS) mv $@.t $@ $(LIB_TH_CXX) : $(OBJS) $(THREAD_OBJS) $(CXX_OBJS) ar cr $@ $? @RANLIB@ $@ $(LIB_TH_CXX_SL) : $(LIB_TH_CXX) rm -f $@ $@.t @shlinkargs@ $(LIB_TH_CXX) $(OBJS) $(THREAD_OBJS) $(CXX_OBJS) mv $@.t $@ threadssl : $(LIB_TH_SL) threadscxxsl : $(LIB_TH_CXX_SL) threadscxx : $(BUILD_TH_CXX) @SL_OFF@ @echo "Enter 'make threadscxxsl' to build the threaded C++ shared-library" threads : $(BUILD_THREADS) @CXX_OFF@ @echo "Enter 'make threadscxx' to build the threaded C++ library" @SL_OFF@ @echo "Enter 'make threadssl' to build the threaded shared library" cxxsl : $(LIB_CXX_SL) cxx : $(BUILD_CXX) @SL_OFF@ @echo "Enter 'make cxxsl' to build the cxx shared library" utils : $(UTIL) $(UTIL) : $(UTIL).o dmalloc_argv.o compat.o env.o rm -f $@ $(CC) $(LDFLAGS) -o $(A_OUT) $(UTIL).o dmalloc_argv.o compat.o env.o \ $(LIBS) mv $(A_OUT) $@ # special _th versions of objects with the LOCK_THREADS variable defined to 1 chunk_th.o : $(srcdir)/chunk.c rm -f $@ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(INCS) -DLOCK_THREADS=1 \ -c $(srcdir)/chunk.c -o ./$@ error_th.o : $(srcdir)/error.c rm -f $@ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(INCS) -DLOCK_THREADS=1 \ -c $(srcdir)/error.c -o ./$@ malloc_th.o : $(srcdir)/malloc.c rm -f $@ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(INCS) -DLOCK_THREADS=1 \ -c $(srcdir)/malloc.c -o ./$@ tests : $(TEST) $(TEST_FC) $(TEST) : $(TEST).o dmalloc_argv.o $(LIBRARY) rm -f $@ $(CC) $(LDFLAGS) -o $(A_OUT) $(TEST).o dmalloc_argv.o $(LIBRARY) mv $(A_OUT) $@ $(TEST_FC) : $(TEST_FC).o dmalloc_argv.o $(LIBRARY) rm -f $@ $(CC) $(LDFLAGS) -o $(A_OUT) $(TEST_FC).o dmalloc_argv.o $(LIBRARY) mv $(A_OUT) $@ check light : $(TEST) $(TEST_FC) ./$(TEST_FC) -s ./$(TEST) -s -t 10000 ./$(TEST) -s -t 10000 ./$(TEST) -s -t 10000 ./$(TEST) -s -t 10000 ./$(TEST) -s -t 10000 @echo tests have passed heavy : $(TEST) light ./$(TEST) -s -t 100000 ./$(TEST) -s -t 100000 ./$(TEST) -s -t 100000 @echo heavy tests have passed .c.o : rm -f $@ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(INCS) -c $< -o ./$@ # # .cc.o auto-target doesn't work on some systems. # also, $? did not work on OSF for the -c, grrr # dmallocc.o : $(srcdir)/dmallocc.cc rm -f $@ $(CXX) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(INCS) -c $(srcdir)/dmallocc.cc \ -o ./$@ # # auto configure settings - uncomment if you are doing configure # development on the library # #Makefile : $(srcdir)/Makefile.in config.status # $(SHELL) config.status #conf.h : $(srcdir)/conf.h.in config.status # $(SHELL) config.status #config.status : $(srcdir)/configure # $(SHELL) config.status --recheck # $(srcdir)/configure : $(srcdir)/configure.ac # cd $(srcdir); autoconf ############################################################################### # # These dependencies are automatically generated. Do not edit by hand. # arg_check.o: arg_check.c conf.h settings.h dmalloc.h chunk.h debug_tok.h \ dmalloc_loc.h error.h arg_check.h chunk.o: chunk.c conf.h settings.h dmalloc.h chunk.h chunk_loc.h \ dmalloc_loc.h compat.h debug_tok.h dmalloc_rand.h dmalloc_tab.h error.h \ error_val.h heap.h compat.o: compat.c conf.h settings.h dmalloc.h compat.h dmalloc_loc.h dmalloc.o: dmalloc.c conf.h settings.h dmalloc_argv.h dmalloc.h compat.h \ debug_tok.h dmalloc_loc.h env.h error_val.h version.h dmalloc_argv.o: dmalloc_argv.c conf.h settings.h dmalloc_argv.h \ dmalloc_argv_loc.h compat.h dmalloc_fc_t.o: dmalloc_fc_t.c conf.h settings.h dmalloc.h dmalloc_argv.h \ dmalloc_rand.h debug_tok.h dmalloc_loc.h error_val.h dmalloc_rand.o: dmalloc_rand.c dmalloc_rand.h dmalloc_t.o: dmalloc_t.c conf.h settings.h compat.h dmalloc.h \ dmalloc_argv.h dmalloc_rand.h arg_check.h debug_tok.h dmalloc_loc.h \ error_val.h heap.h dmalloc_tab.o: dmalloc_tab.c conf.h settings.h chunk.h compat.h dmalloc.h \ dmalloc_loc.h error.h error_val.h dmalloc_tab.h dmalloc_tab_loc.h env.o: env.c conf.h settings.h dmalloc.h compat.h dmalloc_loc.h \ debug_tok.h env.h error.h error.o: error.c conf.h settings.h dmalloc.h chunk.h compat.h debug_tok.h \ dmalloc_loc.h env.h error.h error_val.h version.h heap.o: heap.c conf.h settings.h dmalloc.h chunk.h compat.h debug_tok.h \ dmalloc_loc.h error.h error_val.h heap.h malloc.o: malloc.c conf.h settings.h dmalloc.h chunk.h compat.h \ debug_tok.h dmalloc_loc.h env.h error.h error_val.h heap.h \ malloc_funcs.h return.h protect.o: protect.c conf.h settings.h dmalloc.h dmalloc_loc.h error.h \ heap.h protect.h chunk_th.o: chunk.c conf.h settings.h dmalloc.h chunk.h chunk_loc.h \ dmalloc_loc.h compat.h debug_tok.h dmalloc_rand.h dmalloc_tab.h error.h \ error_val.h heap.h error_th.o: error.c conf.h settings.h dmalloc.h chunk.h compat.h debug_tok.h \ dmalloc_loc.h env.h error.h error_val.h version.h malloc_th.o: malloc.c conf.h settings.h dmalloc.h chunk.h compat.h \ debug_tok.h dmalloc_loc.h env.h error.h error_val.h heap.h \ malloc_funcs.h return.h dmalloc-5.5.2/docs/TODO000640 001751 001751 00000022422 10622115666 014531 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- $Id: TODO,v 1.33 2001/07/12 23:12:13 gray Exp $ ------------------------------------------------------------------------------- HEAP OPERATIONS: - realloc should look on either side (preferring above of course) for free bblocks and absorb them - find free section we can use - remove from free list(s) - rewrite admin chunks for used - rewrite admin chunks for left-overs (if there are any) - readd left-overs to free list (if there are any) - when the last element in a dblock is freed, the block should be freed. - presents problems with maintaining the dblock-admin slots - probably requires a new pointer admin tree - have the ability of limiting the size of the heap - simulate heap boundary - do number of bytes (maybe take k,K,m,M extensions) - have start do number of bytes also? ------------------------------------------------------------------------------- NEW HEAP ADMIN: - need a list of block-ids: - flag/size (bblock/free/dblock/external/unused) - 1... = bblock # bytes allocated (max alloc = 2gb) - 01... = free # bblocks till used block - 00... = where ... > 1 = dblock # bits/# used - external == 00...1 (all zeros then a 1) - unused == 00...0 (all zeros) - pointer: for info-block if used, next free if not - next pointer for free-list (is this necessary?) - pointer to [first] info block below - need to search on pnt to find allocations: file, line, size - key: pnt - data: - (char *)file/ret-addr (or next->) - (short)line-number (0 if ret-addr) - (short)size: # dblock-bytes/bblocks - [pointer to bblock to go faster, ifdef] - [iteration # when allocated] - [iteration # when last touched] - [time when allocated] - [time when last touched] - [memory crc to track changes, need ~MD5 (token?)] - [some sort of use counter] - idea is to keep the info struct around even the section was freed. That way we can track how many times a pointer was returned - time could be global or elapsed - always save start-time and dump it on shutdown if LOG_STAMP - ifdef the global or elapsed - ifdef the last-touched information - time info when LOG_STAMP - iteration information need a token: LOG_ITERATION - need to separate the allocations of the trees, different data sizes - either ignore the external bblocks and the ones for the tree allocations or account for them via careful recursion - still need free lists of bblocks/dblocks - maybe maintain the bblock free list (sorted by # blocks) in a skip-list for easy location, or walk free-list - with fence overruns, dump the pointer info on either side - easy with allocation tree - maybe have a #ifdef to define how many pnts on either side ------------------------------------------------------------------------------- CHECKING: - maybe have a type as the first argument to message - can be error,trans,admin,debug,etc. - this spits out a starting label to all messages: trans: checking heap admin: need 1 bblocks - check in heap_check the cleared space above each allocation instead of only the fence posts - maybe add another debug level which stores crc information about internal heap structures and verifies it during run time. slow, slow!! - maybe add crc information about each memory block into the admin structure and then be able to dump which blocks have changed - maybe add 'use-mprotect' token to allow the user to access only user-allocated pages - a _big_ project could involve hacking gcc to allow some sort of heap checking of every memory reference. - watch for non-contiguous memory and mark those blocks as external - have some sort of EXTERNAL flag - make sure checked/freed/realloced/etc. pointers are not in that area - we may need to round sbrk() calls if someone else did not do a page-size call (see get_bblocks in chunk, need non-alloc flag) - think of ways we can reorganize the heap and move allocations around since problems sometimes pop-up with different heap organizations: - pick a random slot from the free-list not just the first entry - add new list of dblocks in reverse order to the free-lists or randomly disperse - maybe when allocating for a block of X bits, get 2 blocks or some allocation factor - maybe some sort of compact heap orientation like ndt organization. - need a different dblock admin maintenance or - need to allocate max dblock-admin for every block - maybe generate some magical value which corresponds to the orientation because you want to be able to reproduce the error (bsd random?) - probably need an internal randomizer with log-able seed value and the ability to set the seed ------------------------------------------------------------------------------- DOCUMENTATION: - add more to the debugging section: - use of MALLOC_START because a failure is found at some point to find the last malloc call - use of MALLOC_FUNC_CHECK by inserting dmalloc.h and FUNC_CHECK on - need to make sure the manual works for the brand new user - need an overview early on about its purpose (at a very high level) - need a section to explain all the error codes - put in a section about other malloc libraries and commercial versions ------------------------------------------------------------------------------- TESTING / STATISTICS: - maybe use the new gnu testing code (GCT) - general tons of small blocks and watch for dblock_admin entry leak like with large ndb_shell scripts - maybe a program that would try a standard set of tests on a number of different combinations of debug-values to look for dependencies. ------------------------------------------------------------------------------- GENERAL: - add display_pnt calls mostly everywhere display_where calls in chunk. - maybe show the upper-end of a pointer if it is over fence post - need to pass size into log_error_info - maybe with no 'log-unknown' token, don't print ANY info about non-file-line pnts - maybe have some sort etext support for systems that don't have it? - etext (heap-start?) - end (heap-end?) - maybe have some sort of memory-stack support: - malloc_push_location("foo"); - malloc_pop_location("foo"); - have a maximum ~100 entry stack - count how deep we are and if we go over don't store but track so when we drop below 100 it will be correct info - if we are at an unknown spot, display the top of the stack - maybe some sort of cheap crc on memory in non-freed memory sections so you can see what portions of memory changed (check tripwire) - maybe provide support for reference counts on allocations: - have a call which along with malloc/realloc, increments the reference count of the node (maybe duplicate_pointer) - free will decrement the reference count and free if 0 - have a call which reports on the reference count of the node - may need additional admin space - debug token? - maybe have bit in allocation struct somewhere that it is a string and maybe have a checking level/value that runs though the strings and makes sure they have a NULL in them. - token 'check-string' or something - should only happen if alloc-blank used - could be dangerous if folks are changing 'type' of allocation from string to ... - maybe some special strdup flag or something - write perl script to summarize the memory usage per file. - for fence underflow, print out the pointer below's info and for fence overflow the pointer above's info - handle memalign, valloc, maybe some form of mallopt - maybe mallopt could be mapped into dmalloc_debug() - maybe an environment variable to designate which program(s) you want to debug. found with strstr. - or could use .mallocrc entry - could have program:tag entries for default behavior in program - requires knowing the argv[0] argument - add a recalloc function. I guess it is available under SGI. ------------------------------------------------------------------------------- - should the free and alloc-blank tokens write the address % 256 into bytes instead of a constant '\305' - it would slow it down a bit - maybe some token/option? - \305 is recognizable however - I've considered adding the mprotect features which would signal if code READ into certain areas (writing is easy with magic values). This causes problems since most (all?) mprotect implementations work with page-size resolutions which means that every allocation (8 byte string) would require 8+pagesize (often > 4096 bytes). Anyone have a easier way of accomplishing this? ------------------------------------------------------------------------------- I would like to blacklist a list of 'ra=0x4013195c'. I would be *very* usefull to shut-up numerous leaks from standard C library. Is there a way to do that ? ------------------------------------------------------------------------------- but I'd like the extra feature of being able to SIGUSR1 a running program and get a memory footprint during the main cycle (I'll add this feature myself to dmalloc if I can get it working). ------------------------------------------------------------------------------- It would be nice to have dmalloc_examine return good information from random pointers: - whether in heap or not - in use or not - free, realloc'd, calloc'd, etc. - more than 1 file/line/ra for alloc, realloc, free locations ------------------------------------------------------------------------------- dmalloc-5.5.2/docs/NOTES000640 001751 001751 00000001431 10622115666 014651 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- $Id: NOTES,v 1.31 2000/07/21 22:41:21 gray Exp $ ------------------------------------------------------------------------------- WARNINGS: - I have not been able to test the library on a system whose heap grows towards low memory. If you are trying to run the library on such a system I would be interested in talking with you. Please send me mail. - do not be surprised if the library catches problems with your system's library routines. It took me hours to finally come to the conclusion that the localtime call, included in SunOS release 4.1 (and maybe before/after), was overwriting one of its fence-post markers. ------------------------------------------------------------------------------- dmalloc-5.5.2/docs/Manifest000640 001751 001751 00000006431 10622115666 015534 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- $Id: Manifest,v 1.37 2003/05/15 02:43:55 gray Exp $ ------------------------------------------------------------------------------- Description of the files in the debug-malloc package. Changelog Log entries detailing major module changes. INSTALL Installation guide. Makefile.in Used by configure to create the Makefile. Manifest This file. NEWS File with a condensed view of the module's ChangeLog entries per version. NOTES General Notes of the debug-malloc routines and associated algorithms. README Quick startup notes. TODO Things to do list. It gets longer and longer. arg_check.[ch] Malloc routines used for testing of arguments. chunk.[ch] Lower level allocation routines. This is the meat of the allocation algorithms. Manages and debugs the administration structures of the heap. Too large! chunk_loc.h Local defines specific to the chunk routines only. compat.[ch] System compatibility routines if missing functionality. conf.h File of defines for the library produced by configure. conf.h.in Used by configure to create the conf.h file. config.help Help file about the GNU configure scripts. configure Configure shell script. configure.in Used by autoconf to create configure script. contrib/ directory of contributions from other sources debug_tok.h Tokens that correspond to debugging functionality. dmalloc.c Program that assists in the setting of the DMALLOC_DEBUG and other debug environmental variables. dmalloc.cc C++ routines to help using library with C++ code. dmalloc.h Installed dmalloc .h file to be included in those .c files where file and line debugging information is required. dmalloc.h.[123] Used to create dmalloc.h. dmalloc.info User-level gnu info manual file for the dmalloc routines. Suitable as a text manual also. dmalloc.ps Postscript file for TeX-less folks. dmalloc.texi Texinfo user manual for generating Info or dvi formats. dmalloc_argv.[ch] Argument processing library files. dmalloc_argv_loc.h Local defines for the argv files. dmalloc_loc.h Local defines for all of the dmalloc routines. dmalloc_lp.[ch] Leap-frog routines to provide file/line info to lib. dmalloc_t.c Meager test program for testing the dmalloc routines. dmallocrc Sample RC file that is used to set the debug flags. env.[ch] Environmental variable processing routines. error.[ch] Debugging routines and others that provide user output. error_val.h General error codes and associated strings for the dmalloc module. heap.[ch] Possibly machine specific routines for allocating space on and manipulating the heap. install-sh Shell script for systems without a sane install. malloc.c Higher level alloc routines including malloc, free, realloc, etc. These are the routines to be called from user space. mkinstalldirs Script that makes the directories to install into. return.h Defines to get the return-address for non-malloc calls. settings.h File included by conf.h which contains manual defines. texinfo.tex File included to allow TeX output from the malloc.texi file. version.h Version number for the library. ------------------------------------------------------------------------------- dmalloc-5.5.2/docs/dmalloc.pdf000644 001751 001751 00001505625 10622115666 016167 0ustar00graygray000000 000000 %PDF-1.4 3 0 obj << /Length 297 /Filter /FlateDecode >> stream xÚ…=O1 †÷û“áBlǹxE|Hˆn'õ´¨¢Pé Cÿ=NSJùª,‰óÆ~ò€ ºÀH0‘—ØuföÚ„}ù¥ý®ÕD{9+ÁK0ýÂ0$Ï‘ãw«þéÁ‚{ìošËþЊO ‹„¦…Ó<( >qæ‚¢·œÀw9ÓâbîZ°Óg×RÇv2¬VìZOhgµv»ÔÊt,¹aÜþ†. £ø€¾€ ¤"f•0ÎÍâ'ÚqøU1)«$1LÙS‚ªêÎe²óq³\¿)‘eÏ^©°Ðˆ^H¢ŠA/ q÷d28Ìv[ãBW¢;§˜°Lk)³O”HͪUF©ó®ëoJØV ÷N¢ÞKy£%@ @|,¼r•ð Üb}hendstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 612 792] /Parent 10 0 R >> endobj 1 0 obj << /Font << /F51 6 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 13 0 obj << /Length 966 /Filter /FlateDecode >> stream xÚVMã6 ½Ï¯z²&µ,ÇŽ¯ûU §ì¡»%ö$Â8v`ËÓÝ_>RRœA]ÌÁÅGò‘µÊèO­êlUi½©‹ªZ/O™¿<)Z“Æz©òaÿôÇ—­Z©lSgµZíŸïœì›’<]kU*•|º˜®Òu¾KŽ$Ó:Ù§;ÌnS•XÓ¥ß÷=}ÞÇhÛ<ÿ?×” üä §3ÎN਺X]@%ƒó,«äùÀfrþÖ&Í« øšîŠÄ¸)]“eOdC תÜ(ícÿ=ÓË¡CdÖ<Ó©Å¡‰!ê[³ø¥"ÿäû‘_h¶ãÅNìÖ’ÖZoubÉÿ„c‘œFÓs®m#onïæ…=ˆª~¯Õx*q\°2p^ñUÂŒƒÖE„G.ÁÊ­=<ûç ‰Û#ã™zÏ ×‘ Oe}…}±žÛ˜¶Þ¨m&Ô:†VÂí]+ûÁÙc+ŒéhF0ÉéÊD|[3ߛޭ×Û‰5JÎÞØPcºN„ȆžNo(P¼ÛªBí˜Ežù>Õ\c†Gô !aHë˜Î—!6ú7nâ·L­×~õݦ|B{-³Öƒ@à‡9àŠá¶K=ƒxfíè-ÞëTÏ …»ªLžÑêQÎ7"¡í"qÂ$îO¿§ë--pk µÍb‚ŠjK¨¦AÌÝ™¼± ˜¼GbfÎ\]ëC·2‘»¥§oJaWXäxúM,@Š)²cîf®8RÕIûÃ]÷S.f’¯qª@ƒ`í êMGYê:»Ñ–^ßËX\ Oh9¿Nô.‹iÁЋÆH̹ãVô'±‹yÂo§§qÆzz”ø»+ÂO]NY„9±üQ+.“yQ`žn3Zy»80©Šc‡Q E÷Î,—Þ'4~,_æ\!‚õÔ/ª.µ˜—X¨i‡[²¥Eß;ú²Äô^¥‰?o—*ùu£éCAÑ'ãgo\Ĉy”)@ ®A4Øá@\åµ3ýúQ'O³9µD¿"+c 2 OÁÊoábøÍ¨80¹¸G 3K†9pG‹e´äñîn'MщJ<œö‡tùê .Ít2àæ 8Šo>ß&ÂuÄïù?ù¼%ö­„à˜‰‹íݼ˼à𣑶L·STÌu1×1{oXD ƒ´àfžT•ccgL’¬ñ¦`‰à’;—^2½ìîéæ”;;7á_±ÿY¥‡ôendstream endobj 12 0 obj << /Type /Page /Contents 13 0 R /Resources 11 0 R /MediaBox [0 0 612 792] /Parent 10 0 R >> endobj 11 0 obj << /Font << /F51 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 16 0 obj << /Length 2071 /Filter /FlateDecode >> stream xÚX[oÛÆ~ׯÐ[) ¢È½ðÒ·6nRNœs$£rò@K”D„U^ìêߟ¹ñ"‰FŠÑrwvvvö›ofìO=øçOcojíÆ& §ëÃÄ“éï_Fs˜E~]M¬?õ=7öbºÚ^(Ym¾:wés3óÝl®µq>Á0Éób6W‘³æ¹‡ &ŸË¤„Ÿ3,ÄÆóömõÇä·Uw¶UêGÖ¡È­y¡šú¡«|kļ 2®¯ófs8½AûB°Œ3À>í“}¡míC¹¤<£]×w¯¨ÈõàXÒ¹ÚƒRe}gY? ðe=ç€é¡(ÏüÝ»#©³âÈ“E)çØá9¾µ®ÕQâ9›Cg-ysÄ2ã¹AhÙghHïi0qRñø~B68;6i…ŸÙîØ^e#VWòÛß´,N<—Éæ²Ýs‚Až¬ùâ4sœÅ5Z<ûqà*ÏÄ0Ò®o=vâ\0×çÔèMøYržÉ N?Ure5¼rÃж>B£®ÑÆÕn]ónT•ë‹D™¾© ¼ìÁ™?ReD`ý›Ô¿U´-ÓtL ܰÈBÉqÃŽ,À“%»ò M¾ñ™“=Ñ!•G¢å²À(®³?žÒz¾m/ 3_÷Y΂ÆÓôüeÊ^2JvÜáâK+¯ø)F›¶MÎaìQÎ-$(aXæY!Dq…& 4ðžov Aýy`GR³Ò²›ÅpÆ¢;›€ÖÕ¾»šÈ¿}TvœÓõ½KÌ®óFBÞ„‘S5ëÄÓ¿€1ùnWñb"¿/1ÇaÞš‘|G‘ЩK¶t}gïfsëƒ}éqM’óEnÁÁ»^ˬîmÙ¤uJ7!ŠñÑ€ŽêÎ[äxÍ£ì 5‚öÏO‹ß›r#[ÿÒé¸/ñ5þ‘…‡Œè£á© ä0G|ÂЂdæ<.A•àÇçô¯AŸÖ>Àââî©]_¾”¥e‘Ó»gNıó”×ôžËþ!fIÊ´ÕGΧ%«ø3;nØÑH@øv²•xpÃ'²&—j,ðeM`0šÀ:ïËõyr¥syt_óz’W®yQx•ÖªW… ñš²q…™Ç`Œ_eÀ±…¿õ¾…Í ‹ã[°+FXéÈY¶RéuÕ“…Ä­¡¾‚¤C WâPd¼Bì$ÐËtÍ…2øÕãÑ×§ŠÃÆ—íùƒðáyS}Â9QÚÂ‘Š®ÍV1TgYÆÜ®p«/â¶õŒv½(°#œe þNHå‘ó}fNµFQÉ$$‚‘ß\ öÔíæK‹4"ÚÏYGärD@#,@°„-ÕºÌðëJ"åo*S”ä OGÔÈ=abçDõ[Æõ)*Ð`›W¿ML'´ƒ°…/dAe³”­B¡©;±æàLP]æ’Çc—šhsAÜôÖN‚’Õ”bQüï’æùpv@¸ ±E-,œ^4åZ2QAý2ƒm •”6F¨€È®úô߇k úÚs-ô &V®²Ægr ؊͇rŒÀ‹2ðF¿¯ëÓϋņ‹^w]7¡ cW‡þ•·‘ b#f\µ:ŽhÅ> endobj 25 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 531.9676 298.0305 542.8767] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 26 0 obj << /Type /Annot /Border [0 0 0] /Rect [130.554 489.8298 239.371 499.8298] /Subtype /Link /A << /S /URI /URI (http://dmalloc.com/) >> >> endobj 27 0 obj << /Type /Annot /Border [0 0 0] /Rect [260.7597 460.5397 369.5767 470.5397] /Subtype /Link /A << /S /URI /URI (http://dmalloc.com/) >> >> endobj 28 0 obj << /Type /Annot /Border [0 0 0] /Rect [152.6478 434.2383 267.192 444.2383] /Subtype /Link /A << /S /URI /URI (http://256.com/gray/) >> >> endobj 17 0 obj << /D [15 0 R /XYZ 90 720 null] >> endobj 18 0 obj << /D [15 0 R /XYZ 90 720 null] >> endobj 14 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F55 21 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 32 0 obj << /Length 123 /Filter /FlateDecode >> stream xÚ3T0BCKscc=Kss…ä\.¨p6—!”¥ T¡‹¬Ä)„KßÍÔPÁÐ@ÏÒÀÒP!$ Å”h #M]cC3CC —ÜÄœœ|M]# d ˜±±Fˆ¦…±FiI~‘¦¡FfbŽflˆ—kÜ6S##îžé%ƒendstream endobj 31 0 obj << /Type /Page /Contents 32 0 R /Resources 30 0 R /MediaBox [0 0 612 792] /Parent 10 0 R >> endobj 33 0 obj << /D [31 0 R /XYZ 90 720 null] >> endobj 30 0 obj << /Font << /F51 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 36 0 obj << /Length 888 /Filter /FlateDecode >> stream xÚ…UÉnÛ0½û+„ž( rE‘ÚzlÐ-rèÁ@M´-ÛDlK è¦ùûÎBªJê 0` ‡Ãá¼7 e’ÃO&mžÔJ-[]×Éæ´Èƒúq!ƒ”E67ù¸Z¼ÿ\ÊDæË6oe²Ú½p²Úþ·3¤Rø.ͤpi¦”òCši­Å½]Ö3î™õ·ýx¥=ïYgÎ[î-¨7è¥;Óömû`îm†ïû¥*[¡ÒŸ«¯‹O«)ö²(þ‡Mþ…W‰¬—…,u€W5z)•. žL³²*8¸µÃèM]Bh R%Å3îRĵ€`ÿÞnÉ´'@<¨ò–äa¼¦’P4Ë¢d†kyØPöç¶-PÒ o,y^óöšÉ&ùO›´¨£â{Ú@¬ DíCI¤vt’É 8h5ð ýtîdG²ÆLd…n…‡‹2—‘’«ª›˜dðT'4l%r7ß0xñ–½-t'¤ëK(«¢„ïU#/Æ~çñŠ'ü3.˜ìǾÀ/CÇ–çÅ °¨E?kÊ‚x²þÐÓU„?›PKYæœ]§TÉà÷йnbÖ{b—.õÝö•%ÝëzÔý²HÂÚ€˜ñ|Ú‚{³æ é ‘Îzꊿ½ãfU¾Î½‡J Îó b¸Ñÿ*ƒt9ƒÓÔu„?‰Ü Ì[g€Y]•зü5Ç# nÁ€\· G¡+(ËbD3ЧC¹gs R¿c»;g›h ¥©œP}¸’ƒey͈xê/Ü9E¸e Ÿ Ë¢‹=oC©\Á;`%¬È‘B­»¦U"°A³Îêí躅:¿Té£w4ÿ.žù†ãˆ¿œq4ìÉ!Ý…WŸxþÅì‚–4a*vÕ>´cRU[R#A?³Ÿ…»±¹ÔqÄb¢r(~ê4ïáÆkdÐn†úzŒê °½=9^N¦º–ZTŸÌc(wÚPM UÍ[®\7Îh1Óè$»Ø3„Öè›ØyŒ´Zo0öh}ìÚ†«ïê‘·h†ý-DzÁÔN|lß8)°"‘Á8¡øÙ› gªºiBÖ%¿ _h²u3ZÇ¡‚³³ ¯ç¼XfäÀŽïX€š@hÌ u¿7õj0ŽÙÓ@e?M)UDô³á&»â×ßß?mC¢endstream endobj 35 0 obj << /Type /Page /Contents 36 0 R /Resources 34 0 R /MediaBox [0 0 612 792] /Parent 10 0 R >> endobj 37 0 obj << /D [35 0 R /XYZ 90 720 null] >> endobj 38 0 obj << /D [35 0 R /XYZ 90 720 null] >> endobj 34 0 obj << /Font << /F51 6 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 41 0 obj << /Length 123 /Filter /FlateDecode >> stream xÚ3T0BCKscc=Kss…ä\.¨p6—!”¥ T¡‹¬Ä)„KßÍÔPÁÐ@ÏÒÀÒP!$ Å”h M]cC3CC —ÜÄœœ|M]# d ˜±±Fˆ¦…±FiI~‘¦¡FfbŽflˆ—kÜ6S##%…endstream endobj 40 0 obj << /Type /Page /Contents 41 0 R /Resources 39 0 R /MediaBox [0 0 612 792] /Parent 10 0 R >> endobj 42 0 obj << /D [40 0 R /XYZ 90 720 null] >> endobj 39 0 obj << /Font << /F51 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 45 0 obj << /Length 3854 /Filter /FlateDecode >> stream xÚ­Zë“Û¶ÿî¿â¾Y7©hâÅG¾¹Ž“ºc;ßy2išI)‰'±–ÄŠÊùü×w_€@в]OçfN »‹}üvAu•Ÿº*ӫܘ¤´y~µÜ=I¥ûÃ%­9̘ÇSþzûäÙN]©4)ÓR]ÝÞ ¹]ý6{±©î¯Õ¬¯¯çjÖ]Ï13ýýõÜZ;û¡>`ï²khJÓîy¼½ã߯ ;««þØáDcì¬ÚÃÄþ­½ÖÅìú–;ª{î¸Á«®¯a¶ÒEžÍÜõï·òò6°ã´þÃ8åœã\_©<ÑÊYá8+l¢Œuı¾ž»LsÈÛáùÃV­ûÿ›¹›µÐ¾ãæ×%pŠÓªzô1 ƒÕ9Î-rl4q ½8¯å&3 ì¬èelïÀ2Ókc3ôš,QÊfLn‚ÓM25ê´Ã'z ÚÍ¢#]yäaÙÞ¶¡Šn«Åö´ÉNmwü »#ÿÀwV80‰r)ü¦Ý‰8Ѩ«µHÇŠv¾ Ö÷÷ß?{¶Úº´ËÔêÙ˜fRfzLÉ™[ó&(¨üù‚H kÏ\ƒ5¤6/† ¤EnɪêË–=©©Ód"xFäà¤BMñêƒoUüóo1Ä|84›;d‡Èéן¦ìUkh¥ÌzÊ †Íyïúc_ïYÛpôaƒÚ³Db6ܳcÚQ‡…\R Rë{‚»!å༟¢»tä¡E}zºbÙ)›&YYäCÝ[5d_d¸}‹ZKê­Ä Òèœøv7û•Ñ‘g<4èL°µ¯ÙàR .¸ Zï~ý ¡nòA4N¶µç‡ãO¡G/LcÁXù$+ÚY:"aâc¯–a7ï0l"Ïé×C{ì–(2Е8ñû;Ðy4#A“À°ÓæÄ°qålG¦ÿÈï«RÆìãÌ®ÞW;ß·‘² ®"Ì…ßI½Ó(|Yš wU—L«œnZ¦.V½2¬½¦pú¤°u»Ý0¢LQCyѱ¡º'o¶îªÝaˆ6Œ.¶â±¼ÇÄv¬õ’:/\ìÙ²bŸÙ´›þc ^ǂ׮à¬Xu¸©Âi5)uÏp”4XÉs‹ÕAzB¸ú³ñ­ñü`û@=Á‘ýúÀ ~´øôÙåàÉÀ‘ñ‰jx^LV lõ4ç¢g,rÀKL÷²Ýß5k€ŸS,:•8k#÷ˆT -oô@àeËËöÞŸ:ÑÜ\FÈ’„8’L¸@¤MÒ\•ã³ØLR @5×jHå¡6ôâªYèy–äY¦†BoÄJ6^ŸºÈ íçàWmÛL_ðñ l[­XåÄy¬›WÝWÚ4}½D¸-HÜÁ;kqÙ—­ÌúÈIƵó™?¹bà]\’šÌzùmx·äÙg»ÐIQÂ:ü9i›žW‘µŠ]$6†p‹ÐãäÅXhGn÷‘ƒà °‡÷ £ ˜ÆêÕÎgû°y@is¥t¢mVÏuRµ &5íO6õö~J Àƒ“3: °Ã3· OÞŸèLïÚnWqÞg!òU :³öØó @ÖÃC¡hm‡Ñ:øP ÝC©…ÀRà>D›ãÑLèhO’ê2ó‚âi>'x¸ž/?~œôue¢SçÑÞ££üífÍÝÚlßòï¾í¹1tÿ ³‰Öl˜HŒ C&ºÙâH°}5zùŤ+Ï `ÓzUþî»)¦TLe2Åg^ËeÁiXR­$pET…w°%¡]Ö"Š´Aßpl‹B^0h7$“’Hmb\^|&(PÄ›Ï/ùC¥¡]h–·€Œ„à &Ðtí2H´‘Z·‡­.16¥4AÄ#°:Y1³ÖÍ^œ¥Pâ-z]ïë®ê=êJ(Ó@Ðéà¶Ô›êC}×l'C&ÄÙBåŒ*7ÓT§"`äèðäÙ¤Ê"Qyᆺ:öRŸÀ¼’PR†í þ]F nŒÍá"+Kó3$^7ÍYI?â)pš‹r¦— øhæ_-Ä, ³@§žÐ˜Žâ,¬ŒAì46 žÛ —fz`â—ÞCáÖ²í"Ï J{XH}’ N™L~¢ZPL¯ÅØ!Y6)›­iz©$@ÿÚ…¨äcžÈe—è¦Ï<;ËÇòtŽp½ñiX®F‡ó›Ãïqï³ eê¶b'%Wù¥Ä85`úߊçI83M¡4FÕ¿Kñœ(lƒ_僴˜f£Ìz Þ±Êr¥d‹²‡" É ¶Aa¸DÒøªP)Ù¶fïèEŽoHºJ—”®bgCµó2ÊAà«H0z<4”e@ß½„fâdå·L ˜â/¥ý-ð>Yg¾<·™™ôÀ¡ÏC}VâT,*k¯ÈÉçe‰õB.pKœ~Þ<ž8QX<_i½àh T)·~{àÊ»~i€/jÝž GÍ~¿¦J»-³Ù=•pmfgº³eu‘Xeó[õÒ0ïKl/ÈõR/(”]BÏ´ï+ ¤ê[xRqðhàË1C4«ödã‡ýÓž_ôÑH^8} SÄ·^qQFB®ÉÙär“Up<‰ø­=õ”Wýò-æû›—¼{yûþÝÛ?Þ<ñîç›Éë̳t6Luβ *Kz”}2ii ReÿÏLkìÉç²ßBeÙ·zô2 ŸD˜5CŽUÍC„!áwUG®oŠs0L¸¼0…0x~þë`¯pòüw”0a«EÃÑ Ê2½t­C£O+°kÝp~rð7(Ìàyý®æE§ĉ2P~yþîí«·?]x6>%}Í}²E‚áp_Ÿõa÷8¯R,8øÁ½"‰’—&&ºkùøUÇÛ¤ãÄ ³o8ïKão/䦉in¥gµò®ò¿^n&âendstream endobj 44 0 obj << /Type /Page /Contents 45 0 R /Resources 43 0 R /MediaBox [0 0 612 792] /Parent 58 0 R /Annots [ 49 0 R 53 0 R 57 0 R ] >> endobj 49 0 obj << /Type /Annot /Border [0 0 0] /Rect [206.1457 597.7999 314.9627 607.7999] /Subtype /Link /A << /S /URI /URI (http://dmalloc.com/) >> >> endobj 53 0 obj << /Type /Annot /Border [0 0 0] /Rect [211.5144 322.6526 428.4147 333.5617] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 57 0 obj << /Type /Annot /Border [0 0 0] /Rect [133.4406 131.4447 300.0806 142.3538] /Subtype /Link /A << /S /GoTo /D (Portability) >> >> endobj 46 0 obj << /D [44 0 R /XYZ 90 720 null] >> endobj 47 0 obj << /D [44 0 R /XYZ 90 720 null] >> endobj 48 0 obj << /D [44 0 R /XYZ 90 660.6127 null] >> endobj 43 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F52 24 0 R /F58 52 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 62 0 obj << /Length 3943 /Filter /FlateDecode >> stream xÚÙŽãÆñ}¿bsà‡}‘My°ØÞÀ‚ì±^8‰3"–e’òì ?Ÿºš‡DÍzzP³ªê꺻ÕU?u•'W™1qn³ìj½{•H÷ûWJZ+˜±šNùæîÕíwN]©$Γ\]Ý=Ì€ÜmÞFéõʨT©èo»¢®›ë•öÑúŒ‰î®½‰Ž}Ó^«¨*êëwwÿxõ÷»›Óúcôà”¤”ŠÓ$ÑW©·±2ÖY]³»^©¨Dz²¨Ã6ÑÑsGó€ÿiÔúªÙs»oxìù¶Ð[î]ÓÒÝ÷P—-O SwÅ{œ,X*þõ?ß¼ŽyõëY°½&bTÔ’ŽëkE[žWuÜ[ì…>ÄG¤©èºò4:ÔeÑñž€‘ÀŸ•2±r CGÀqú†™Äà?’jŒ…«h[r»8"ô-0„¦t2¥bþ`s„àØ= Ï¢°n³ Û ,z„.û£µÍþ×DYèx<¶¥ À5ë¶¢mÅ´•rqêF'©ö´—¦ 3.ÏÃaà‡Ž¸K“$Œ®-‹MdzŠý†H_%mdFÓ˄͆Aô[b‘Ÿ ‘N íòØŠT¬V徸¯ËU¿e,¼d®6ö¹×²¢h‘©,t{$Z0“¨Àÿœ+7¸9œøŒLY1O´Ob•/f‡[áV—èV>Ö™±Bˆ£ðûº³$6©IeI·m޵HÕ“ã†A¤šã㻟7ÍSÑ奖…ÿTzFQqû\uu¿!#±î·q±DîÞ+™þC~³®‚² ¨,825,Þ¸çrÜ1‰õ霓º¶$ŽH>ê¾Í Ù›iê¨qô¾-Ðf<£¹ô©›+‰¢Ž'î ¤ì™—£F…NÏfCl?ád2Dï¹cP¨Cà¼h±œ9S·?¡N„‰D®-zÙÉ’Y óÕâ„ClÓ&*îÉ–U½Ðh´è±žÓ‡Æºç‘ ˆ—[†& :ÉÃGÜÀ:ÀSVÔl`+sÔÂi~wímT®Z–¶y) `ó· ;Ý•ðT‘,1¢Újƒüg!Ø ¯IUÃŽ‡¥“ô‰³F ò†m&eÍÞÚ„%È$³Id À’ê<:"›hÞ~2¯%Š ãÇ%$B0¾kÚ’[Õþ)owň­`EmŽý9Öæ@S¾(D®ÊÇ…:‰ÐT÷Ȧ¢}æaàè[~â‡e¢nÔÁÜ}l‹k–èèÍx†'~߸$Öü¹Ë€ Ä’c3@Ãç?Ì[M'.DçùØÂéyØÏ­·@×ϬÿAà÷?Ã>'úîFì²ñqª37gâ¡x{«ýé.•Íâ<5ù•s9¸{!¦­&󖢜Spˆ_©Ëb—7—ZX;zR7Q`úÀ £.pg6úvÑ”'`òË/—Ì·Êb•Úàׂ‘â¨ö]. Ü€tYÂ& ±žÎíÂQ€‹ÚÌèöº1œéT0Eµ,eÿT“½!åyœäÖÌÏoÑiÁ>MbÎ\Ö‡/¸¬$}–®>m+2~ì³°‡Ü…ÎÄ„Cc‘ËY¡læ_fr+eÂE‡¦9Àe|A¿ý ‹ÙgÚ‘„½P0‹Ž Þ 6 4à:Ià¢2çFçs§6c›rhlˆ3¡!¶aoNÁ+õŠ‹²v+UûåX¸—˜ô<‚³[b¤5q¦ÓÀlôFYý‚”êfÁˆ(YŒ÷BN ã8‰h¼bÏÒð×Ô{²AÑ:ÎR£çüZŠØgþ#2áb›˜L挶ÉK è]p6ЧH@Lz)pKtœ@¸|¦Ë:zä¤ :¬tà“Èo"ú!õ¸„ÎÌ6AµŽ×ëEd:ÎóÜL‚D»l³ BwÞ~ç0¨ª%¨ÂçjŒx ð7€ŒáeJëû‚D„’9–iNÙ |…#É$¹g‰´pg“ƒ“`ØÚºÁƒÂ^Ñà¥ý9[åBx½/Ÿ.e¯Â¤›%@)¸Ï\`Þ¾[¤Áš?gSÖe_.23=@‚üÈP ·R§eY;ƒ¹Lž”d!yølM²5 Öµ™Dåd7û¦íb¶?=AЃ¾‚6uóX•¨…IN¦Ù$£IƾÉKµ£ :ñ䨀q'Ü+Ô¢;„‚µI6iôš‘;þ'Ѥ±ôä!þöTBtÁŸ»†¡ŸÅîo¹{Lkê árÑ×û`»a|¨~ ‚ƒx kã ¸Sn.‡¸>V‰ @n]{ ‹ú}´*U›à1æ'IÃ⥶«M¬½?±×ñöO¾M=;ÉupßÇMÉÝ“`Q£M°ivã&¶.ÕçÛ¯öë!.E4XrðCòV ÅN ñµ¸¸oª‹¸C¼:&q’ú*»&ã9)“'è”E@Y3ð³ŸXQ˜ìý¾ÚüèÑNfé$/Ͳ±æl`¼šd8Ĺ{¸€Àž^FF#ê—­–˜Ò|à÷™Nö‹ã!úMlX…4XÈj „RéÃd~¬Õ '‘ÊDЃ‚‰G‘û©1«Âu±3ƒÛ¦]Ü„`ÐÖ—v¶œhz5Õû€sbiæîa9ã€,ßgùÇRP¾I®ýg÷êÕ?ÚB<=7Æ¿`‰E&Kì(2ø±•вÄñQM’uˆ’Ãe.+xîrPÂãÙY­mùP}øë¿¾¾ûaÑ–[°Æ‡€ÇKOB‡»ÅîÙe‡Ð[ÉÈÐ׸­LÞRôß¾Š.šÈ Ò=­æþ‘c/Š8f¼Åã“;5¹n IíxëFU2—M…¥è‹ž\Ù<y´^b0ld*­ÈPÆÎ½GUCëåÆû މ)¶UÆ~_ö}H°Kú}ÑBfóìH%&—2;vP%þ%X§ã5‹4ùžœpPî;AÀ['@bÛ±wé*Îê—n,„ i’»+“83 s^¾aæ­¦ªïçg7 H1˜A1g>JÝÛ)3ñpß 'GSÑ»Qn¹T°Qzº/x¬†@#×qŠNbùRa˜·šN\Ø×9ÀáZáö»LcQÒ@M³RÐ,άæ¹ð©Hƒ“JMô={Ï™õ#›}ÞhðÌInÞsqŸzÄ3¸èÇ {é¬)A[l¼ÇB €xñßm©&à‡¹¡¦Ñì'ýã-v=âø ¢mŒ5é1©ù*Òd]Þó@µ)e,ÀÞr© ÔOù§†Ï=¹Ï£oŠ®â샧š$>7s2†l©ªðM3¿ÐKgQ ¤Ru(¢¥äÌÔ ó(™}ÏNn05¨tb3? LÒ —‰¦¹\L†ËCS4ÓÜ\)àÔ¥‹ûaÖjœ¶ä|N€Í\*]ªÇŠo_ ùX‡áwü*îL³ÜY üçl'ô.Èð0ëezOMä×€ü§N®àÈ%úĬ'bÖ=‘-üšÙHì cC¦#™¼|‚v=±_oI~å刡ôYä5Ñ“[r¡åÐ6$` O NfÁmbÆ»bžT¿lq¯øDex;Ô“]ÕÑp±Œíá%Íò­W¢0M … fÿ[ù¡Z¬dYgyÈêûõð¦r2¤0Ð €¶ p «t¸8>¼².å‡`†„bÃí³÷ع)»¾ûÔ„{a˜;©ðœßæxãùÚ>ÉÚSÄ1ãR;ylÚÉÈœÆN¦·<}µ ¨dâe˜Rì¶h¥kBr„3T”qlÌ/½X›ö&W,åKÊz=Wª±ÉY™·EÏo'Ñ-”PKUGJv=‡Œõo&ÁÜPÌ{x¹?/.ŽíüCW `÷gqp]9_ê^ ß?õw i4ؾ¾êzÞWÇ}|u :Ù‡áæ©”nrEt%'œü£–šüÜÅ×ÇÝĽœÀhíg$ÖÍ#OŠ€âªtôƒpAͯnŸæÑS45{aû|fGZb°¥4„…7èA ‰¼[¡”ÈžšÚ©ð¶é&<Þ#9ñðü'2µ€.ù9ò8WD©^¬(¬aÛÓ¢z·=ö›æi¿|ëÖÌ80ì> endobj 64 0 obj << /Type /Annot /Border [0 0 0] /Rect [350.2277 570.3775 522 581.2865] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 65 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 557.8328 147.9639 566.9843] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 66 0 obj << /Type /Annot /Border [0 0 0] /Rect [470.6095 303.6476 522 313.3446] /Subtype /Link /A << /S /GoTo /D (Getting Started) >> >> endobj 67 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 289.8909 208.8941 300.7999] /Subtype /Link /A << /S /GoTo /D (Getting Started) >> >> endobj 69 0 obj << /Type /Annot /Border [0 0 0] /Rect [206.1457 200.9593 314.9627 210.9593] /Subtype /Link /A << /S /URI /URI (http://dmalloc.com/) >> >> endobj 70 0 obj << /Type /Annot /Border [0 0 0] /Rect [261.5693 171.4428 415.2664 182.3519] /Subtype /Link /A << /S /GoTo /D (Installation) >> >> endobj 63 0 obj << /D [61 0 R /XYZ 90 720 null] >> endobj 68 0 obj << /D [61 0 R /XYZ 90 278.089 null] >> endobj 60 0 obj << /Font << /F51 6 0 R /F58 52 0 R /F52 24 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 73 0 obj << /Length 3141 /Filter /FlateDecode >> stream xÚµZm“Û¶þ~¿âšdÆ»Xœ¼ ៼LÃK«µHµ—ùî"tÃï/¤k-€b1$ùüöâúe$/e(Ò0•—·ëÑ"·«7ÁÍ6;\É -®2h®Zë@}vµ0ÆÏ‹#ŽæMI$e½çïõš_^%&(²öÔ ¡Ö&Èö@¸â¯_ÔW* îøC[óà_Š–^ãŠYÓ@-UbãÀ^½½ýêâÅm'N¤Ô¯ Œ$¿*q$RiÒË81Bj‘ØF\-â8 n¯XRq°!Þ Ñn¹‚Û«]VU@¢äøé÷8³-wÀ”Òi×ûïBiàÃæ„d|æJ'¯e¹Æ_àJ‡qV㉂nTÁíÖ£QYß9rùǵQݪí²Sð`»u ÚÂ0PñhžPé`zòÑ¡ôáXî Vošl÷Ä-i®=Ðÿçfœ­þû[îÒ>HSî> 8M½ßq·Ý–±­¦Ÿ­[Ï=œŠdo* ùðqÔ›ŠÚöHQ :cvǶáÞð¤€n´Wo~ØóËVµ›ZƒmS#Û;’îÓ2Ëq¡÷Ü+÷Ž!·Âôgô^âÒ :ý{Ê‰Ó p¬‹[í§0œJôúÜ3Ÿ„Q ‡`‡&þèõšŸZ· Û4²ÃŽ†Î»ÌüwZ¤ÞíXBX’Ý•G+•¨ v›t‹Mf^Êý¬”+²'Lu Þé­ @÷ŒÍbÍæ]´§wÙ¾€ˆ Ô¡­$o;›H‚ƒÕ¥x?~Éü”E¨µ>‰=rŽœM¹9íÉõyÚ3+l’¸I$tϪçoïñ/ž¸ªe¡¥‰’j¬ž»L˜6þ Ð>ûúëW7SØ—©VœÇ¡:LÖÿsñæmx¹‚ðÕE(LœÚË;ŒBi@öÝ…ʪÄ÷«‹×ïƒD·àb°âL )HÕmŒ¿úðy‹‚ù Zß¾föK ˼)îÇ'ÍaxU:XA„©ýäÎ%XÐHÓlE )‹$26X$1÷yÖ#XЉÀ?[×òf`ƒŸê¸åÎwaNu®à’Ì$‚m”Ž8Ü‚vàë Üvd‹kR¬nº2»mÛÃg××wwwâ§ãVÔÍæzʆVJÄ*œ°qõ;²s6Fz¶²âKVÄéX4GlÐ Ypåô•­zÝùƒD²u°ÜA…¤`¶ß8ÂÚO(ʆÏLI)‰ ¼sþ6R˜' µó7±ÌŽÛ&ŸóKÞœ†‘#|‚G qtvI<‚$Lýš‡¦^—Õ¬³›H$ÒÆ“E‚´ó‹«ŒÑ¿øOñ«àð‚=ÁG©vr›#çŒæmÉqÔ͈Bv˜2§Y©?–È“F “v›.–sŒ¡Iíe®)— \·[_I'~âÂCMéƒ|°?#’(NÇë2%ȧƒÏ©EcûìÚ4Æî¼>ísθ¢.ß˹ó3ÿ 1 Ö»Ü‡£3Z˜~?yúîÏÜúeN‹ Ä—.µw‘Æ]¢­8Óe¸¢LŽÐÌCÙL>8ÂÃ9CÁRmâ-ÕË5g¨ˆã±'\S›÷×’ CÚÔÜÏ*!møëÿAýßÁUâÓzÝüläútl®á{V]/Ëýõj%è]>‚¬q@ ÞylK4>q¾?ÀJ™p>E :ÞÕÐ݇A£õ‡ÛyŒÆ™Û~ë‡1 ëãnãyHŽŒˆÀ}=Æå¿ã108¸€Žckðû+Æ ®EÌ”²7³°a|HÎa ×å›$4òÅùŠa«ÏâD.OÉÖÈ,]Šsf“Ou™þÅzúîÉ#öŸ£T4° í-•»áÁ&ç_‚2L«ãh<½SI}B£W®Ñ%sqÈÁ¡röUî7Ž¢qÔðè¼a…pVvÁ³Éçí u,{»Âõ±“»`A`>ÞsÜð„‡ ¸g£±.þñûM©ñ;OM ™ü­Á˜±a2±¨õ,Ä ÌéçÇÐí“§¿ÌÙ1Â$&™SäŠAÏ*`fƒÈdckÔà\œëaǬ¡‹XQ$lcm°ËÜ­;wØæ{RË#„?ðK˜”W§•Ã-ûPžeÁÙ¬IÆ×7±-’"2&à߈›£*ÜðOgR˜ ÛîâÀ¸Zw’ n¹ûm½;P%¬õ¸·xú%­kP°†Kã·®¡]•KäUJÔ¬!{ ú°-¸üVÅuEÞíV!£h;,B,ûT²a,@¬Zâ|°—ê8`$kç.ò›b_4T5ÐR\JXVÞ¼wdXçÒ–J™{ßôZ¥ÀÕUAŒˆEB†¾UïUžn1$œ¹Ñœ/ˆ¼¾.|æ2pãͳA¹°«åi)ƒo²Üë¦&AÞòîì$i¶qbËh*‘XH2#‰f®hݯIt¾ "köË–ù„~”¬;_üFfÀ• ª&;»… lÔäê•ári4€G3f¸7Ø.À.¯° Ö¢=¢YÍþX¤>ìSI<&¥X(ÑÍ©þ‰ýxämØÏÜ/4êëÐf/Ø•¹î²ª¥Ðn RíéÍ4Öað/Ä,Šv@²#“`¬"ÙP˜PÆ“rÍÀ´»äb‘·_¯Šõ¸ ’¹ŠêÝ•¿ â—‘0ý¨iwnFIÐ;{ŸKc,ßøx™»êÕâùóo¸~D !(d™H[7w>¡QYéDŽSŒë§HœZ±Ij%b/[Ö n~ÿý÷Üxzí¡DÅBÃIÓR—¬)¤ð<Ï ÎÇn}&ü¨Ãúf‰‹ýª\?á’‘4±pl^l)€õu÷°#§i¬ÍŽørÁãèFjþ=;8Œ”<1y@fî¡•;RWüÃ0¸uCó (/ ­ú]AOSÜ:ˆÛoîäu¬„ãd¬[wF?¼üç·7?Ü|ñâæ¯³ùQˆê5º¿¶öºñï&V“ç¤"¤Á¹vA,š‚ä8<*é°Q¡ ˆ.V÷î›»~cÃP×%\]už"nÅ›ã™ào÷n1V[°Ów2ŒCßÉ¿f›‰[Æw9ØîðÿQ¤%¦%[Ù9ø¢ñcÛøt\Q’±âñékŽ55î;üBͽ.Šóh‹H\¨0Ê$öøÚÑ-†„³Ñhºà(¾"sZháͳ†ÊvƒB|}Ru`»—Ö‚Žì=_Hß~Ê8Ö\@1Ÿ¥¡*7F ÓD>p;ºÅp.…8[îœÄ¡HR;©@äþöÖð¨;ôú‚uG‘ÿ–lœ7°¬¾&ƒyïßEüLOßda„^Ë–ôdÙÜóPÙ=oÖ<0ͱOêð%žh—ùßgì‘ô(2ÈMb MD6–Õ=xyð!ö€ÌsFVø7GOý-k_dÍÙó㊋\þ1¾û2Õ…F¶þ¡g¡‰Sø TY¶ô÷K›Üx¬^Kt³áK¯å:iÁ¹%©µpñbé_†0vP›`¦Í½P#Rvu–Ñ Õ¢r"Õ›µK`°ä_†þëÝü66êÊ…xUö…]d¬ø1#€rPW{!“ØÎœ{£„PÃïÚ]"¥t<-àOáè}Ü] ¨“HÜsgç/“_HÅQ²ÉrðªçÖô*Åv‡æ@?6QüzjK²€Pµ%Ù…›òí«Û~QªãºàÃÎä·ÛÒ•y»ÀZU.•ŠÃQ¶©|¤F¶ñÏΞŽqä2^ã_^(c:{ÃöX2CV0|Û†‘}¶s-zˆ†ßù§£E¤ŒßÍ[Óƒï+¦O'”é̦–›Búß=°,\–ûÈâXÀK¤êí‘ ÊàßѰ¯ãnýß'Y¤;oa¥‹øDFñ~›í7®ÂÁ ³äG^£éoRJ6¶OGU~îìèÿÞŸô|æï*üÃÇšríÀP÷ç‡m>ùÒ"E9ÿöë—?2 Wø0ø_˜¶ö#endstream endobj 72 0 obj << /Type /Page /Contents 73 0 R /Resources 71 0 R /MediaBox [0 0 612 792] /Parent 58 0 R /Annots [ 75 0 R 76 0 R 77 0 R 78 0 R ] >> endobj 75 0 obj << /Type /Annot /Border [0 0 0] /Rect [213.8032 583.5077 322.6202 594.4168] /Subtype /Link /A << /S /URI /URI (http://www.zsh.org/) >> >> endobj 76 0 obj << /Type /Annot /Border [0 0 0] /Rect [225.1285 343.873 415.9424 354.7821] /Subtype /Link /A << /S /GoTo /D (Allocation Macros) >> >> endobj 77 0 obj << /Type /Annot /Border [0 0 0] /Rect [416.5158 206.5215 522 217.4306] /Subtype /Link /A << /S /GoTo /D (Argument Checking) >> >> endobj 78 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 193.3708 201.2973 204.2799] /Subtype /Link /A << /S /GoTo /D (Argument Checking) >> >> endobj 74 0 obj << /D [72 0 R /XYZ 90 720 null] >> endobj 71 0 obj << /Font << /F51 6 0 R /F58 52 0 R /F52 24 0 R /F54 56 0 R /F60 81 0 R >> /ProcSet [ /PDF /Text ] >> endobj 86 0 obj << /Length 3040 /Filter /FlateDecode >> stream xÚ•YYÛ8~ϯè·ÈƒXI‰’fž&×î,’É`Ò/‹L0+K²­m†$§,ö¿o]”%·z’EmE²X¬úêº àOݤÁMlŒŸ†q|“7O¾{¢¤µŠíœäÅí“ço"u£? Rus»_lr[|ô’ÍÖ(«”÷ªÉêºÛluâå0fŒw»IŒw»~£¼*«7ŸnÿñäõítZ¤õ·øA’‡ Ù`ÎÒ…Qxc“ÐW&Œˆ­?ã×ì+íÛ(‚Ý‘èïÙ¸ýŒÿJ`Y§Þx”F<ïó¬ÿŠCx+{Ç’~îx¨ WD½ç!êó–n¡ Þ´Žú ›U×<óGÂn2gW›Äá ¿ÛŠ‹®ÜÍh_Ç:bØRù›mÂCñ09*ïZänì»ZFp¶Ã±{îï³aÄýo¶:ü$1áÍV_E?ùW¤íÎ=ny§¾;œìÇÞ}…Ò¨±c½þ í؈í½ÍúßžWçÿïHoÊ~àe,j'¬)îx†Ç2;q«.¤’¥Y[ðî4Øñ ž~Wx£‹Ë ¢Êž„zoE4ÀQÙ³ü×Ç™{<´Â3jyî4ÄRÏ÷2&ôêêŽ4¥þÊcÇ¿9f#]ü8[[6]/¤'ܦÛÕeCõY!–¦±mß* –¡Í÷[Æë_tW «‘ö2þ«§tõ˜®&2‰€•=ÿååz`ò½{ÃlÄÑŸ ÇÓw[ß*6êî~•ÕØW‰²WŠž&Þ?qº3s’g-7²zèøØ…öuíà4òc$²enǪ)×ÎŒ´qgï;¹~S¡Äª†aîŸÈW*N—е¦×´ðÀú»­ðÅ ã@ )‹ `Íþc?MSÇÚú^À±ûÇêp\ÛI[„T½¸$ê`׋&ÿ_&8Ã+V˜›(¶Ü(š> †y6ümÕÜ0ök'Ý ¿_w_€…h‹š¸ÏΨÁã3ÔTÄæW[ šEV-3$S˜$#£±ˆ÷!ð9Qçó&Œ©ÏîæOR›‘P8G§Bz)]ë‡V»G(û¾ë·Ù®ëǵ»ÙÈOÜÕÆŽñ¢åSï•@„èœö‚}:˜‡XD‚*g÷VøJÁE*Ø®«Z)»ñ1-w™Ë²jîÔ%XÛ‹øH¶‰ÖÞ‡²¼4T’úAë›(]RÖ`$Ã4=‹6&ºíœp%z¸!2ò¡ÌI¥·a”zƹññ)ÖÉ™yh賂ò>=Cä ¼S†®({Í¿‰•o´Mü¯DKÝ·ø¸!ò/œ04ŒQ™–;E5°z#›ã±â·Ç íKÀw¾Ç ¶€"FË—Ú¡®’ûŠP…1){‘Ë#°Z§ú…—YnÆËo˜ŽÒ‘ÆÑÅO¼Ð’_bT‹Øè+vl:&)*¢æôZM· Ç#+&®Bí§q’|Ÿ‰CÔFfi¹3kÇK³ÑAC⯠R—XàÐg"1y˜ù7Lœ‡‘;uw˜ÄF÷¸›á³È£#aŒÇ9îòþÚ#mµòm€Í¨T)\y«íy@å^¹wÃóh'$Ç5„”x5uU¸hɺ¨Z°hÂ0XÀ'je»ïx|þÌÎ1ÈïëÒ+§¢)òK× $L5s…ê$™È¶3ºC|°Êáå1CV¶ê Øj\£ EC~ÂLÀÈX)Â],ô~›.†hC ƒh} ÔD×·ÔˆIø¦c?Š‚Çg¢ÛÎ WîùpCº¡ŠRMeáé'²qÊš zØ$ˆ[—g &<"vkÄÛaÄ·æ)QœûתÙ"°.1§Ï×”‚δDHŸò ÙÔ—CÀ‚è—Œ ‰(ßjD}q ¨&„ÉGŠðé’ƒ€)èFÛ+pXåß÷ \fÉÿköcL]PùS4òÛ ÕMêQ>Q’ôî@'¡Ð€ˆ 9gx@ÔáëÜ·ÜÉ;NèU2q•H´çßÂÉcó·¤×¼›ÂÇ)Ð~?¸5¾` “}œ}Ìé;ºíœpÍé?ØpáôÉýˆGŽ_²}½¡|½ý†ÂK2ÁÉþÂðýEƇ·‰¼¯ÙŸ£ûï7œìHëÈ[ƒïVfi¿¾¿}ýHÍ!MA%Y~„…1×ðv¡¨Ãx¢ÿ<»'8j¸Ãh.ü¾Ff˜;”·C/Œ GÚ¹F¿Éü%φ¹<;Iº‰Nn±Ù#öH¡¦¬Œð=@y¿ìô‚Èrå…9¢…à8̕ѣÆJÚGs¤íÈ?Ò—€†ÜSª1§&[Éës1Ë7p\Ê ‰lCYU{XM6Là›)y|õîç·oß¿üóýo·¿¼ÿõÃÚ‹¦à‰Rëœòx¼äx|2§5Ä/ùš*¸w%$Z'WR‚G«/t â¢þ¦ÓÐË{ˆ$K™ÎøQ»%‘¡J£h»‘ÇÈtý‚×·³£d­\…vÒžRPÆbv"p'"äD¯¯$§“#³^öiÝÁRqu~„ë‚kÇ(¥wÙÝ,KžÒ§^ðà‚¢O/‘fˆÑÛ¡”(­;.&¼„n»l*MB˜™W•BRñeÅÙq«š^’Æ 﨤â &·íÛ$2ËâR W´€Ë¿sm <š— 1¶›bUÌ|0uþ’5“ôP±Ì%'Å6ܽª`(Ïf#o6ì.õ Ig¯S ;y/)§Ø²XðaÍ«&¯m|ü)Šnõ­®ý<Ý}»ZA‚X_Å2Ÿ]÷‹ôßq”G¡DiO™#ãäˆëÚeåðXÖRs™âJõ g7é¬ 1ãÒä,ÄæT¿‚ˆ-I‡¦ÚÇ“­"k¼ .ølTÉ‚ä3ò^•CÞÓ[žFúé8p’ „ð{»;âZP#ˆ†Ã>Áí70¬s ž•³‘áÂ!D8 GäLL[?Iõ‚5ú¯˜Á¿±±—=Ú´‰­÷®tØ­"W‡ÈŽ¡"&ˆÕ±âøxÉüç%_gX{M´ôØ·Æ$ÄÆÏ­¸ªE^¦SÍIœ˜¼Ž"¶WS¢#ˆå2R|W$Ò<ÆPå Qš£ø~À놬¶ü22—® Q–gˆ;Fñ÷˜‰ˆQT3`#ËG®â\vç¬a Ñrvл tu‘z6•8I_éB[õ"Û‰#ùBy%ó ”C6f²ïÀ¿ÎëÈYdĸˆæÝV££‰ÀPw’:=xÙÒ-½?–«ð›»ðw‰?¿”¹ƒë‘+óO,òíHnðL>ú´¼G$­D€ø!ÆÕVÌ¥˜ÎG ˆë÷Z¢òNþ¡@ Bò>Ú蔡hGa:£¹¼ë qN4êJÛ˾t³VÅ ð3@bR?Š D @Kæiä[c•?RU¦ÀÒßÊVÖ·ÖÆ—Ä£­mú—3g º²)"Ø¥CUéµ µV4%Oâä ÷ “ \z¹dUxKͤ±ÓŒß ×Zµ\ˆpK_ŠŽÝP^D;eÃ)Ë¥Y óšLsªêD\|¼Ó ôGY:¯e¬å¹ÆO¢èª¸þü€My‡ºÛ¡6aû3D@þ`—Âj äHº2/oOí‚D‚­ž¯*V;òt{nve?|TÁ§Ÿ¡¦Ï@,í&«Z¬ÝQine£ÿРóª‹)ß—w\ýïj-Žec×^ÜÅWYðõ°UQzÏFäCxì¾ã•…ŒLÙsb –X¹RN‰ib“ʵ,½V!;å4;T…ìÀé4—8%ûÀØ“ƒ…aÒk?…ôz)HþEã Qg3™“µÙ~^ ¹fVVÝýÊéHÙ\l¡½ÒÌ™~ƒ#«Ý–¼p.äiôÄ£(£UeÖ $,é•2î*ÑÍ}×ýßÚc1’\°…JeÜ«&@”ä6>//'ëÈïþÊ$öu—‰QŒd"?­‰Nc½àB­3âendstream endobj 85 0 obj << /Type /Page /Contents 86 0 R /Resources 84 0 R /MediaBox [0 0 612 792] /Parent 58 0 R /Annots [ 88 0 R 89 0 R 90 0 R 91 0 R ] >> endobj 88 0 obj << /Type /Annot /Border [0 0 0] /Rect [189.0872 583.3891 371.3269 594.2982] /Subtype /Link /A << /S /GoTo /D (Dumping Core) >> >> endobj 89 0 obj << /Type /Annot /Border [0 0 0] /Rect [492.9091 538.2767 522 548.2767] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 90 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 524.823 271.3882 535.7321] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 91 0 obj << /Type /Annot /Border [0 0 0] /Rect [111.6002 482.3893 253.7215 493.2984] /Subtype /Link /A << /S /GoTo /D (RC File) >> >> endobj 87 0 obj << /D [85 0 R /XYZ 90 720 null] >> endobj 92 0 obj << /D [85 0 R /XYZ 90 386.187 null] >> endobj 93 0 obj << /D [85 0 R /XYZ 90 357.6304 null] >> endobj 84 0 obj << /Font << /F51 6 0 R /F60 81 0 R /F58 52 0 R /F52 24 0 R /F54 56 0 R /F72 9 0 R /F55 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 99 0 obj << /Length 2212 /Filter /FlateDecode >> stream xÚ¥XI“Ü4¾çWÌ-îÔ´cYòÅ!ìPP2(à n»»M¼LyaÒPüwÞ&/'PE¥2-KOOoýÞ“Ô]ÿÔ]Ü%Zû™I’»cý"éw/”Œö@±_’|úðâõ—‘ºSŸ™º{8­˜<ä?{Ÿ]ìãNyC±Û+¯ÛíµÖ^øÑnoŒñ>/zœ=v%‘”mÃë퉿ܥÆ+ì0vH¨µñl„9¯~ÝîÂÔ{â…¡åɯŠ'Þ"GÛ P«0Mb/Ûýúðí‹/&u¢0ü7…‘dCãp©±R©ŸdYt§ÆWÚD¤÷_x0Ù‡±¯eh²¶eóKð_¹u¥}l¬?iÒD~ªà¸ÕÒ©mÝΉjCÏÇÞú)Ò(Ša{2ðë³MêåvcYüȼ†=mÕ·La« G‰wDY2*ÍüÛÁ¦±Aw ¸¿FªBH¢M¼ÇŽüõ;ä…;‚‰Ðý]{îl]»8Áé§»ˆ”W7¶.¼µ.è˜Ͼ²E”?élm¸£}´<´*‡²è}1ÐÊ…¡xíc²ÿë¬×¯v:‘7\ Ø<‡îù£”ß~h;´$Ž1ôW;úÁßñðÕë­ãÛɺÛÑ•Íùã5-G…ïû[ábâlä'a®¹ Ï7àø£œ˃Dîÿª€סèŸQéçƒÏÀ¦Þ[Ô}^ßÐïÕ–åšJðt)—µa·éožÂ¶Ý¯mÀV[žò ÿ`<, ¡QcrqA-²óæ˜ç@ŒòboW–^ÙŒGïmwåqÓ>9:LA2CñÒ4oA9Ó Š%”þ÷¶ÌQþSWøÍÚoh´©ýfü’4ûf`ä.âAb³ö¸:aÔDboöÕ¶±çBjáæÊãá"˜†TUy@¬±`I¨-sH̸ø¦"öíxFàÉÂI 0Óž=Àoê1’á™G!h½á=„bïQJ)Ä·JH1cäâÊNbùÂɱ'*POvÔ¿)¯œBUÇ'T§J‚ç¶Säý=((Âóa-$în‡dšµk-ÛíÜŠ®øWìZ¼·õcU¬ËôžzÙ…™³øØSÞ°ñ…xvå©•6à™ªnBho®=<²è„ʽ7i0»ð³¶é˼è°ËˆØe=G§ÞO»$yé©+¥71&F½qr.Fn?†Ž:ðj΢,vý9]ñ:Ζ¬Zš'Öå dÿ˜DËiì]âÝ÷ü#|P>!ÅRºá4θ¼tÖ¡`³”ÈD¡™ãˆò D0ƒ ?a1º½=V9~†)ï$Àq)óš\âÙ(CŠÓgÏߌ9ÈÁv˜kåÙFJƒ¾üCüŒ_4ÁmÍXGð—x(úõñÊ·Àˆ»†³•´wíæÔ4JôΠeÄ6ŸÍüC#]Ê´!Ú{!r#´?d¢Â%>ˆ-ÀDKl2.ú SÏ¡ÞL<ÙŽ?k${Ù| ŽK–Êf¡Â*”XÅa Ö©è [ëÚZþÍ92iê"kG[€PrYjÇ%¤0\T<çÎÄ¡yÉð‚Oh!€&Àa}™Wå–‹£Òá@ @ŽQ^Ȭ³óîàÜ×˱—¢ÙRþÊá D*`hyuÊK˜Eññè+ÌæVè ›—¸zæo2?ð±ü‰QŠŸ.JyvéMaÚrËGz¶Þe.—g©˜‹®Fyru†k𠠫Ǧo4Ú7¡ é”5^ópÅøŠýìØ:¡¥±UÉÑ¥ÙšIä½±Ad“ºÔÍyí0Ѽ’â ö¾·8â2F>CÊïˆï[> endobj 100 0 obj << /D [98 0 R /XYZ 90 720 null] >> endobj 101 0 obj << /D [98 0 R /XYZ 90 170.4952 null] >> endobj 97 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F72 9 0 R /F55 21 0 R /F56 104 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 107 0 obj << /Length 3019 /Filter /FlateDecode >> stream xÚµZ[œF~÷¯˜·¥£4[7(ˆ´ÞK"¯œDJfµŽÑÝL m`<™üú=·¢¡=ÞMÖ– ]×SçòïÖ7 þê›\ÝxkãÜy³?½RÒüË+-o[±ùëí«?è­â\åúæön¶Èíá]¤Õfk5ü‰þ~*êºÝlMí¡ÍÚèv“Ùèah»Žª¢Þ¼¿ýç«ÜŽÛ%Ƽ$yI"­³Øçyr“f.ÖÖ%$×í}¹Ù:í¢Óf«#Ø\Gá°½k”«‘qUÏÏ!LÜ}Ec“èTÒ*t'z\Öª¶Á‹ë¨Ö7Û4K£7ÃlP eÏ 2©èÊ‚Gµw¨&8£™žì¢m¬ÅJï«ßJ6S…IãÄÁLE£vØì Y¢Œ=Èã\Bò u«ºæ·. Pô®áÖ‚g’¹­ §Á‡²ãŽ¡Å'*Œ§ã{.öòÚ•Ê~ u0"Fo¬ÉâÔ¸üfk\œz0/JúîëM梇†‘:Ü­mÞ_T¡ã<'œqk3p‡4Oå”Ûê°GI¢/ö¨â½LJ§ŠÉTì½v2å'•(•LGù8óY&ƒHš¥AaŽMyàcW¬™ŸMEKM¬3ËÍÃiºZÙÇú8M² Í—¼îÿ²_m‚¹'N1;»U±6‰¿œ]¯¹ÎÖ$I¬L–Ï=í_}q$~µæ–6…¥µ•¥ÏxÖ_ØPÍÃÓ¹äÆ/pg¶v°väì(úUÁÂ&[íc§ý%ºMj£ýs°}"»jØ)±iª|Ô.KÐùpÞPÀ´•cjŸÆ*O³5Ãê…aña„2l`¢j`øè¿D)|Tû HsϽëï!LœÕÏM;÷ÜÚº+ñ.Û¨ŠÃE;³HG—ø ÷±wZÏÍOà <`À|„;µòz_ò‹†ûÖ%lRBWì/Îg²Ð™s ÓYç\ô2°jdšvLbc“ë©ç·wÁÝ®9’7±SA£7I Žñ ûýò¢qP (9Í1ÍÓQƒd×’Õ§f~úºî[ñqv¾ºf¥…$éTq­ºîPáÇýs@%œ-þ!¯«6…Ÿ²/iTÓEÅñÙr6œÛ-3]ØJ$+BÆøc¦íÕ;´åþ?PRãUX÷±rc¼}¬ÜP6pýb VMÑ®Œ·õágD¶•…ˆl]þûq<‹3—%^ÊÇŸ¯a9èÙØp¯cy ñaÿï±ÜL„ø <Û`èI´ñª›ç¨n³‰K/ãúîГ›=.ðš¨üõÌ×ó€¶ãöþ¾#Òò‹´a•¡›ãê§¶{â±ÏØy*÷­çk Ù[ïV½dvTçbãmð?@ºµ cã,Sn¢| .tégÓ?›ùѰœ0Ûìèx’êí3JOVç˜6rHŽhó赩V¬QѾ=WcváÉ…w„,§…–¡÷ñ©=­ªZ›²œÿ UÛ8¬–A¶jÊ4€äÀgÊÜdgEšs&‚_(öŠ,@ñœUv%W¬nG«ÏôˆÜ°GW¨ŽSµÍ Yë,û“߯¹ h#q#<-Ðb.CªõõrHhôíästÓbÐYqgì.:™Y Ë3Ū(âwµôПCv.˜œ#g¡wÈÍŽ<ò4ËŽ¡#xèá*ÎM+”Ø %”¥=Çíb“›:rŠs-À#߂ВûšÓx_ý¤´ Ô‹S¸$‹¯Ââ‘•s©ÐíêË—á–ÓÈ>\³ŸðßCs7ÞQñ|âpý¢B©Wÿ~dRSøIýïMµ/C+Wh=ÿ,x?ŽiÂX}üÌôÅ!Ælë%/{¼ï¾¬ ­5ø~`’`¡s/v|¬A>;“•4V®Š”—{*ª ñGvEy0ŠÈGð7¬l´¤}¹…!çª$år‘K=Ëþw oz€¨·\ÐÂ’€‚Š/Lq›Ôyt`x+bÇ‹ó¤H£T‚¡5!ôØÜ6EÍ… kǯN§µ°<—æ£mp·¿ñãÜ „öõoÝã¸ítàÊáž/ÈÕ=Fça£b§@ÌÁ%íl‹º|7ÒÀpÃßàܧð…=•>éS«8°1ÝöÓW“`ÖH)p_lè ÷}ÔYþ:”]ÃyME}K²î/Å’¦ò³Š1ü€Å1Õmû2ô!N„½ÇÏ(SûP_£§ÂÆ¡~îËg.®›'pq„æÇª/! ³·Ÿd…»bO¸³Ê ß&Ù8#0•æŒÅÙwÒÎàÈ%‚#­âøþáL©éIšïW!ÍQv¢+P`m3«Ó%¯ŸSćKF?!i'hcU.sUt_"Ì`ßóòe!<üÈßxaVdÓ.ÓŸ6œuhò3µ—Wë«ð}lÎÿ±)T áÿ/t-ŠRsÕFÿÂ}ŠL†u~–Üø<6Êê+H4ÛNÆ­Æêb¹¡|66üòî‡ÉÅÏëÃÒï7ã'½O¡KaC—OÅ_Áš0êé—‹8ƒ;þ úäÚendstream endobj 106 0 obj << /Type /Page /Contents 107 0 R /Resources 105 0 R /MediaBox [0 0 612 792] /Parent 58 0 R /Annots [ 110 0 R 111 0 R 112 0 R ] >> endobj 110 0 obj << /Type /Annot /Border [0 0 0] /Rect [468.6959 163.2411 522 172.9381] /Subtype /Link /A << /S /GoTo /D (Allocation Macros) >> >> endobj 111 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 149.4844 283.7519 160.3935] /Subtype /Link /A << /S /GoTo /D (Allocation Macros) >> >> endobj 112 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.4185 76.4758 467.449 87.3849] /Subtype /Link /A << /S /GoTo /D (Return Address) >> >> endobj 108 0 obj << /D [106 0 R /XYZ 90 720 null] >> endobj 109 0 obj << /D [106 0 R /XYZ 90 271.957 null] >> endobj 105 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F56 104 0 R /F55 21 0 R /F58 52 0 R /F54 56 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 116 0 obj << /Length 2932 /Filter /FlateDecode >> stream xÚYKãÆ¾ï¯˜[(À¢ù™›ØÉI6ÀÎmíCÔ’ˆI…¤v<ðŸO}UÕdSñ`€Q¿»ëõÕƒñCDñC=ìÒ4¬²Ýîaß|ˆtøùC¬­-­ØúK¾üðíyüGaUñÃãqqÈãáKð—³¹nâ`´›mô›mš¦AòçÍ6˲à¯vÀ辯yIݵ2ßå÷ÇM™ÖŒ· Ó4 LK 2û÷n“”Á‹LŒ þÍŽ2ð'š~´´:NÒ]ÄñæçÇ|øáq¢'O’ߣKþÉE™…qšåLòѶ{»e×Í6ÙS9ÊŠò¨¦·…ÌPñ$ënLÝ@Kb!b Ï–~vÁ3vµ'Ð@Èýä»°ˆ"zhœ†q ã…y¸§îÑX>jÔ£´äi¸«ˆtœÐðî¦ë_iGõ€_¢äl¥az:™]Ñð{¨Íh/ºÍ€º2`i}Å?ÝÝõ2/Äó1'RÌß_o.4¥L‹Á®BA‚â‡/8ð‘Xž¥ ¿¿t€4 ,ü"îYÃòyE/æ9Œ¾ˆ¾ÆA ÕÍHr{Ùuš12ž7xˆžÎÏÚó£‡A~tf…ð+Óv"ž÷´ó›ã@n^Ð-Ó¿2ñÑ’n±ªëÌÖ}-Ç€Ä8 ^ζ•Öa’ßEµKÔDÙ6‹*’0X` ¯!(ÉaVôš™ÔžHÛb—МÂG>õ¬$zóÞèÅ/}=*é¼á*À;×úºÉ zâQ *è6üæÂ+c¦g9JS-IV1Âw¨†T•ˆ¥FQ‡‡NO¥ÿRC_Ðj;fºØ,Ê#ì0¿™9,‰(˜ˆ³ñåëVÅWä›×ôàÑèz,rF6+O¹Ã³¤ŒÂ¨$ƒ.â2LË8`‘yó´jÓº­¿pÙÞJ>ÛýŒÕ„Œa*Í/«óP³€ÀOJ ƒÅ“?#³pæ¤,Jv÷4fUB/)Ó+À=­û=ßCÇÌ_ºM³,Ü•%ïBò ‚÷ÿþôøÃ–¦IXU¤Â‚¦ðyQBæ¡z¥l²~b ƒfbš,éFéJ»vš‡!µÞHqCWÑzÓ¬½:Iª0K£\ßÑorœ•'m¸›µ§Ó–´JÝÓ|~#—Aß½ç¨ÝÅÁ7‚ÃI‡eœÝAq×*þ¤Yål'+ÅÔ02-+†œÍ;e¼dU|wáÛ:h Ñpô dÕÉñiìAÏn-»Õç[Nú±u<©Ý;ЬÌM(CmîëZ2®Á• _|–:w¡Ší‰Lðg%G²¸6çÞÒÔ¸HN¬¹n÷äÿFÓîõ.ê¸~ŠâLç¬F ‚Ö=àÐ0Cêaì¡¢ ¿£[w©ŸhU¯ ›Šs¥qÇ´‡˜§‹N³Hºæzq¼ÿn"σG½—øX± Î›Û˜Ê57¦ØÖ´6gy°+;vàA#.t1E¹>˜Ví»¾‡¯"’2eå, LûB_4Xò޶—öÞ1[ˆ?Ëh§³§Z%²Bßu  à‰ÅÌGáŸêÉ´`¸…ã Q£;Q(㿇ÄÕl tˆsê…™DÄÕ®AlÜëþuS9ÁÞÅ,»xÀ…¾ZµÖ¹ÍíÙ^NgªA¬q«ÂUÜij»$S§Á›“ôˆ–d¹Äløm̳¿þ¦ÌCGìK–պà ,»~Šƒzu³ÕŽ,C¹ƒíDݼ_ìÚèîñŒ-Q]#8¶B™r‰luŠz9Î77bã OÍ0ZM–L«ù«ˆ9µÝ C£Sð8Òú;µÈgOJѰÞhˆI„'‰æ#¶=üŽgŽóKð‰„Nx>Mí'ðëå :?ÅÁØåŒm,äŽÐÏ×L²b&cõoÎ  gôŽvOz64SìsÏ]Ö kµ j д>º„"WVDž·šóD±7¬×}+xº ËÅgÙÁ™½Ê1æÅäHpµAøÒ!–iÔ UºªY¢~ø«n§ÓœáÝS¦ù„íl¿«QJôÿF'ž¯ËH'  ž'ײQžëÖ²Õbhþtã$À(bëùsöÄ[m¥£ž¤°KŽ™‚pq‡îá ‘I^AqÒªT–+·ŠO‹Ž5TY\Ãe“Ñ ¼U%£¥´ÌÁù&yÆ&ÉÊ÷p /qDí+¡—”aŽôh%S@‰@rC¹³‘€f}¿¬‚ßL#r£ˆµo2Ȭ‹©&` ƒàæäÔ~r±Kwb$­œÖ©ŸÃY|0ã¤{$\¥†¬YbB–š»š[z]}äðoÍff©ÏL¶Ïíð˜<ì3‡‡Xù*[Ÿn*Mj7š°2ZCox”šÂœ2dÔ¾9Òwi9Gq9|t'HиèTη"?§^ÐÛ7ö«1 […Hï·b»KGXà'äÞŠÖI»ÞïÇtŸZ§v¥PA©éœ*—sLaŠEñ_ÎŽ—° •öÁ2gOÒ“xÊUeÜzN!£gK\9Ö²OOÄ}ñUû°<ä=¤/R)>Ln #b'ˆÛ˜SÂh"ï¶Šž´%Ó¤‘_åÇ/°<9Švæ=S€»õ ˪”]+Ð%»"̳"^)¬ñ “@žW³±]&»©,÷r®‰³",“lÉ®D ²v\T3¢ôËÍÞ—ÔP,ͲtÁ.ôkÝÚZ?Åà©“uA+áÿIÆŽ½µÊ.>Û7eЬˆÂ¸"°K(õ¦p¿x§L1­Ûú ×Rø7.Êxʉ2,N¼Šî8öå_NsÂöO  6±aÈãÄmQž(Þ”`Š"¬RÊœ“]˜'Õ;å‰iÝÖ_¸V‚ysàTž bÊÓáèWB¾,[ÄèèŸa‘hùaÏxkð_ÃÈ^&8àÃÝ”p¯á’ ŽˆÉª-Ÿ™{A u¸Ð‡KÅ'>[¨ˆšz2+Ç—ý{®Bsz—øõ\ŽÎfdh¸ÄÂñ gtV³ì˜|©•%o/åáÛ`NSt»‹ÈZß,¡`ŠÁ kÙ ‹½hÁ˦ßOçÝ‹X_A§5š- @ÿaÊÿÖ}‡ýÅxÁÊäD2Žyf¦K}âžá«îä;xP8ŽH¶]ÓhIýL÷i±F–±:\=TWŽaNkX)k"fÔ–a§ºÞȨ›róR!Öì₤̂“ø¬9çȘüÊ'ŸÓœKS0'T¸ù¤.톤áe0H1¨ÍÅ=IŸœ ÐÚ‹`;T½Lõ¦<`³{ƹ^ÓÝÜÎÞ \eCG?y½WB¢ j Ã2·*Ý»¸eµfð¸)Sù ‚Ï èiú¤ø¨^|å`vQ ÂòÍ"õªyYºô¨îc„̼)ñɰŠS¿Ã|šâ Ô#dŒ«EiòÇÀÃÇ9Éçòi=ÊïYË7¨f* º «sdEÙÖºh°ýW?wåZ¬$ÖPG¸r&à”™­œÒ_w¹FÊ‘_¼à;n죹Êkƹ޻‹~)1ßùµŠbrÏÒ1ýÓä¾håÁŒFf8ÿÉEëÑû×9ò.´ÀBÁØ^#‰Aú’.åó—í±ÍˆË,E5ïôP—Õ8™£÷iW‹@°»r9Ïu«•ÏãJÅ…êù³ø lìz/ØÆãN­~tvõÜû3⌳$,ò`L¡F £ÈÉ¥.WäD§;zµ1<.Ño¤»å'BŒ¿S!àýG|gPw‰ ìh÷När3ýz¼é»~¥”7ïq¹¼ÔÍHu„~¹ÃgY*Éda•Ý…Y÷©M­12òN] ·9<”šìeõNFà›Ö;ù‚ºMhÌüË­v¦,ú!кðïãÐ?6endstream endobj 115 0 obj << /Type /Page /Contents 116 0 R /Resources 114 0 R /MediaBox [0 0 612 792] /Parent 121 0 R /Annots [ 118 0 R 119 0 R 120 0 R ] >> endobj 118 0 obj << /Type /Annot /Border [0 0 0] /Rect [280.0851 615.6538 492.3883 626.5629] /Subtype /Link /A << /S /GoTo /D (Fence-Post Overruns) >> >> endobj 119 0 obj << /Type /Annot /Border [0 0 0] /Rect [460.1906 290.2824 522 299.9793] /Subtype /Link /A << /S /GoTo /D (Memory Leaks) >> >> endobj 120 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 276.5256 266.9337 287.4347] /Subtype /Link /A << /S /GoTo /D (Memory Leaks) >> >> endobj 117 0 obj << /D [115 0 R /XYZ 90 720 null] >> endobj 114 0 obj << /Font << /F51 6 0 R /F55 21 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 126 0 obj << /Length 3850 /Filter /FlateDecode >> stream xÚZm“Û¶þž_qߎš±¾¿ä[ã8­;;Ó\ÚÉ8™”'Q{©T®×_ß}v (ñìÚ3G`±‹}‡‚;Ÿþw…—EѦˆ³ìn{úÊWðÓW¶Ö„±vQ¾}øêëï“à.ð7…_wûÙ"»O^®ÖQ@ÿ¼ïNeÓt«u˜{[‚E‘÷°Ê#ï2vý*ðê²YýúðׯÞ=Øí’0üA@ùEÓp|—æñ&ˆâ„Éz8VDC’xô <Ð 91hð·ùÞ©“‰²fS?1åÍ‹ þûbWVŠûfÇAÆi?°ÃŸ3‚1võ¶A{Ëò…’$–;Ô+¬ÛËWBcUžµU2á‘Vñ[Ûv=Ž~9†`Ɇi²7”lò")&IŒqNhÁcÏ$¼”AO¨×JG÷äm×þâ1N}é!AÀ§ñýýfŽ‚‰&ËÎÉSÝâ™/-³ÏüÞÁ5c){·cµu53Õ¶•ý‹Ò¸ÃÕ yYžãCüª¤…5ÚÆÖa– åÕ©ë_Öõ‰å¼\ÇaJŒS‘ sßÛ‚zL´\B‡ÑÿSžøò ÁXö¹¦ëç–R±«AÛá §ç1‘\ ŽUO‹èªˆ ºK¿…¨¡ÈNà«ìñ;ƒ¡ÝcS@}”©"Ô«k2ª6–†ih¡¹h•{\r¥pa-!Äu{Ð¥˜»hu½´P§±æÏE ÂR Fµ¢M›¥CþXU×f:ð‹MTDÅ]ꇛ8'ãKv˜À<ìØj‹·v öõ‚²ó–M+Y´‰¥ñé»…sü-û×7Ò>‹½¢V^’SˆCx‡¦Gcñ¾Düí‚ žyI¨±‹º²‚Püdn>||x§è³•£pSt >c}ƒKK½]'_±ÀÔx³.¶’`PÏòWsŸý Ö{ùZgddk­’˜’$Ž[8±#»AB8³]xlŒTž. …)/+R¥àE-µÁ¿× }ºÆI3‘·uœmŠ(Nçb÷žN¦¾õ%OÒ…IÃ÷È‹õƒƒD_5-…â›ÜvbRÔDTZ‡ÛmsXÐd@½c+§ÂT}¨ f¥áÓ‚àPœ°ÆÒ;×ѵnô#NÐ~¤??.é]_5U9(åð<ñ†P•ðw$þ½îÙø O·S&s[½Z=®ìø¾j·Œ¿> {­w%ÄSÙ‹ÿí1¾,šYgF÷B4‰Ø0ÛÄ~1±á˜Éj¤‘÷—nÞ3-F\1À–:«Ñ{Ti#À[Ýb“’GàŸWE¬•¥Þ+¶…Äý›Åò´¤,`_± B¥ˆ|Å Á‚ Yº¶@w÷X‰|¶“ÆPCÅ÷ÊfH¨ÃBv¾2™`35¦'èM3Slü„« (.$`áýºÓ¹!Äqšoã4Õ3éM´©AÞ‚•lï_äR¿XµsNñèU<k;\Iš¢`ÂQ îaO¢ÐÆiŠÙ ÒP9BËdrˆØÀÌcÕsרkŸI»µ7F(þÔvØóÙ ¯à`nã«P"Ÿ“ÕÕ)ÁØUPo¶drÊ­aÆÌ]£-Qaú³[GK@'€ÃÖ›FÇöl±Úô`ð5wÊóàe«“¡síDW|TçŠ5Ѝa¬ã$‡ÒI’Û ·y°ð„qØ8±bã†íV,8àÊÉdÿSBÅ$›d‹žJsïè•ò™Œb#ŽM[’@nAÇ/~âïWŸ¡¢xílï›Faäâ¼p7Í8•Zr°Ü(™#o7Û.ðà}ÿñh` Ì=àPæØÏÄ A3âOéÏdGr/ž°¿Xu…Žœ˜–¦91ÍE1§cPgʈ9/á%âeÅq\8§Æ¯ÅdvÖ´°(ˆv5£sP,J[µ›eãX©q¢PôŸ¬LTçA7ëKž¤ ná[ÊGÊþÚ(\bi÷\z­F¹ÃˆÃv–ÔízÎÔ&¶FŸ•ã8$õdïî2J¦SHâÛñ W:PÃ?s–Èô TN•èèfµ°=~(6ÛW7Á !¯äæ\|,ÜÛ‘Y_eÏý,ýÚ#„\úÿ§8X²x2\®‘¯8ñÎ#Ê÷yŒ²Pý^±îHk¶Ü©ÜU:··›xuu¨„|U‰à5%É"G:ud OiTµ°Ö@ͺÂã´tá¤ÖËr¶¾t‘ì¼4®±¬à˜’bôÕÜ.ÐM)Ü“¤ý+Th¡)ñ-±[£ëË1 w:ušN³H³g+^næ€Ý${øŒ÷r͇6”k؉|çTFö€Ñ)&ll_Ub Jf‚Å r·cD©ô¼1i¬ûDÜ謒G³fQR6"CnŒæJxYõŽòŸñg¥èÅ•]1‡$ôò­¾»Ä'ÕGc¦„¯ŽYaòhè N¡y‘RuÞè~­Ûü±By¯©wjƒ´ÂZ.¦!Ðz«¾æ ¦pdÃ÷©pt¥?£pÊ>[$âjŠ[‚ãœn/Îo\r |o.@HµËÆìwÅíÌëØ`¸0ÿ:}/*(â¹VE½+סê××;˰Èf%B;pj>EÝ„MÚd;×"¢{µáŠæŒ%N1Rièl¹ i€É¤O”L¼n_1t¡§a1S £"½Ý¯ØL2ny¯^¡H< ~w?m8Þ”:¦õqj cÙŽ†]"uX…}kqS Á¦â/š'›"ë® ê wèdÜ‘M[Zôîñ¢éd¶ýqx• ÕûW¥ ÊâÐ"9ˆRsÁ„ýqLCmeã B?jݶ™{õF æ„3qÕ x)(íij ^Ø(MH&Y£qû]ÒE#÷¶S·£žÔ«¨®0Öó±6vö:ijn×}N§¨C’+[ý&µžqV¨ûÑਗ਼ ³'[ ó5%\ˆü‘a1(²Ìƒøç©¼'v2,Ò×J‡³´€ŸrŒ=øUuBÆ9Áæ>×ÐLkݨ’÷Ò=«¶|ÔÚƒåàëï“pVÇõóMr·t¿OkÖ…:Vl²&ôÒA,ÂeoS ø¶.Ǿ9v†Ì“Eêzsއ°Ù‚•dÚݪ=×;§ÏØü¦£ŒWs·y-åõGÜ„_b´Nò …ðÉlanL`³KŽ–âiÜ£J~‰}JHtUúfïê²Ö#Çz™V¥ éí? @|o¦Ñ œJ“޿ހñnb®3§ä°æW_wÅ…k€à8ÕÈ<-²O«ulP_ÌQ&æ!Òd ØÚC)âÈ!’:%K›ÚÔÃQܼã–åe‹t—³šftw¨9DnE‡‚ÂÎ~J¤TLåx­½îM•-˼ûu}VêY·«©¢@Ëþp9U†e˜abY4…® —‘ïƒØÉ×HžßÅïGëž®me¥›ÌO“» ψÞ(Åî[¼µ‹¸`+oÞË)‡íå ±|>ÍÐ=…¾É_õÅ,ÏõÙ(QróÓ  ßi‘ÍN²ôû ƒ÷¥“Ü.hŸmïP4«8÷¬…“™Gg[^8ðŽLi-ºŠãtLîÍI®©Ó³žDt{s«ô"ÃÖüΙÇFù5Éç÷ûô2V[/:–S~ýF–¸¿­àt]Ë7º—%$ÜAëÆo}®,—d& H¬,£91ÉÔâvà”;ù”VF¤¡ÈWþhQ¯ø³WÞ±Ó_ZI÷º¾E =›¢É¢“ˆÄÞ?À¼²™½v.QZ-ð}iÈOÄ2s7íRxJȾ:Smäàpœž®lâLý‹þœJ~ÔsЭƲŸªÓI@b¶¿4æ7J+ÉZùÉítåˆ{[ˆœ¿µÏom@’æ-†Ðn5+L o=È‚q/ˆÝYëºÄTHsý)S gä–ü> endobj 128 0 obj << /Type /Annot /Border [0 0 0] /Rect [109.3939 599.7579 284.4244 610.6669] /Subtype /Link /A << /S /GoTo /D (Dumping Core) >> >> endobj 130 0 obj << /Type /Annot /Border [0 0 0] /Rect [110.1245 252.9252 286.2935 263.8343] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 131 0 obj << /Type /Annot /Border [0 0 0] /Rect [336.7065 184.4266 518.9697 195.3356] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 127 0 obj << /D [125 0 R /XYZ 90 720 null] >> endobj 129 0 obj << /D [125 0 R /XYZ 90 546.6985 null] >> endobj 124 0 obj << /Font << /F51 6 0 R /F54 56 0 R /F72 9 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 135 0 obj << /Length 688 /Filter /FlateDecode >> stream xÚ¥TÉnÛ0½û+t Ô*7-̱Kº\ë[[´¬BÅBd)åýûÎB¥6 "@ &53œyoæ‘:SðÓ™WYemî]UeÍa£’ù~£Ón ÛóW»ÍË›BgZå^yíÚ‹$»ÛÏâõ>Mh­a€À[ö¾¥©Å#;æ‘ïâ̆O˜1Ls„hmlU må×ÝÇÍÛݟ˜çcÈs”µràvYY»\[WïÝ»R ¢H[ƦêJ%ô†¡—)~dÃ> ÅŸø—²ÍKÚvœ!%üŽÄ•9Get+6ExÚ®×}7Ä{Á ÐyáœO¡W¹ÜÖP’Ú?N\£l³DÄ ô8½]Ëlº¨;âjÄ1&ŒÊf[-rÞAcµÍu¡X#«øm®¬² Òí!ôýØ|›óæZ›rC]À¶^è^2S– -è,|ÖØmã> endobj 136 0 obj << /D [134 0 R /XYZ 90 720 null] >> endobj 133 0 obj << /Font << /F51 6 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 139 0 obj << /Length 122 /Filter /FlateDecode >> stream xÚ3T0BCKscc=Kss…ä\.¨p6—!”¥ T¡‹¬Ä)„KßÍÔPÁÐ@ÏÒÀÒP!$ Å”h CM]cC ÐpÉMÌÉÉ×Ô5²ÐHŠk„hZk”–äijd&æhƆxq¹†À­352Âá À³%±endstream endobj 138 0 obj << /Type /Page /Contents 139 0 R /Resources 137 0 R /MediaBox [0 0 612 792] /Parent 121 0 R >> endobj 140 0 obj << /D [138 0 R /XYZ 90 720 null] >> endobj 137 0 obj << /Font << /F51 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 143 0 obj << /Length 3723 /Filter /FlateDecode >> stream xÚ­ZmsÜ6þî_áoÑÎtU‘¢Þò­í´½tÒL®ñ½MšÉÉ»²­‹´ÚJÚ8ί?¼‘¢´rÝëe2ñŠ$<¥.#ø§.‹è2‹ã°0Yv¹k/"éþp¡äi [ŸäÛ«‹¯HÔ¥ŠÂ"*ÔåÕÍŒÉÕþmðÝ]yܨ`¬6[ô›mÇAü|³5Æé6:î±ÓcÇ/_ußÝöeËí{X#‹;îï*~xY_÷Ð_ö@’'y¨dóî꧋ﯜȉÖO)…$çZeúRe¡V‰­ÒÜ„*6 io¶IªQX“™(¿¯Aú é ²µÜwïÈ’`„gÒžQ‡’HPtž×„±I5Î ëmT¨rè¥iC¤T8yü\îúÛ³zm'¡Tð±Þר8ÜòÛ¨ÕдiPíaoE :èÅá¦#.m9ÒÊÓn¾Õ œ*B¥ó˜„û¶AÃÌõaל€ÿ¾>Àß[ìÔÁ¿…ö¤I¨Š7ÇïÛ²iº]x·6W¢ÂĘBHŸÙ™ø÷ͨ;±þØñÿü)ÓT*ðô$+”;Ú¥¦ÙÐ2¢¤¸ø†¤Ç<ØÑ`ì¤'ãQ²¯ÎÑ*ÉÞ×G´ø\µå…5Ti˜0D‡*‰øØ4õ-®ÞW¼)7I*RÊLÂm‹ôqÎ=*v”1%ŽÇ-NÓàÆI„»œfpf*~ÓS/žÐ¦Üѳ ¹¯É\á •x¬Íâ|ÅIÇ—)lVš‚)Àúíâí»èr‡í§‹(4i‘]ÞãÉ u [Ø^Ä¡ÎtnÛÍÅ›‹¿NÇÑqÜú,WÉ.‘¨,ý¿r·>Ë…DU@hrt`€s¨uþ%嵟”7)B& ygŽÇn£7Ø­!IÝîŸ`P¿%·ñ.Kóà›ýžhÝJT¿y@bÅPGa'GRôñôîÜ³É âÏð}=Ò~jWí$•ffòi7ó÷D>Û™ô/7¦­8Êzž»­«_Pc¿ªÓQ:œwÇ—7«nõf*i5aZ—c%cçñ5Rz§à±Ÿ¥«;ޤª™ƒà4´ïnŸyA{‚ô~{tkp$`Çð~?@+Ð@e&L³<—€ÿþý/^~ÿþý40y˜'‘J9ÅK~¼B”'ŽÝ˯þ;«&ž9Ò´îïpewØì;Öô¶ù¡¯Ž¸’<¦Ú‹·‰²°ˆõ"À#ºŠsY¥®=Öd¨háÜ?Öh q^ØHŒ}w¼–ØKãÈôÕQðcÌÃÏ%A¢¾UÏŠvƒ;%&ð,“ÞõãÀ‡‚YǨu˜``›l¹»n*z1„«†–‡YQ¤öìRõÐÁî$:XUûçüü,úçFEϸùk”DZóóõÃX С쨮•1’ßáîy¡Ÿ­0.rž$éòøÒ"&h ûÐ ܱQ AwËhKI IkwGчÓ6N=±²hhˆcãUK2 „Å-…7°½¹+9*DÊŠ®L½š>ÄqÖóü—fmYREO©ŠÆkAÕDyKXPè³Õ7Uuoa·U®òKS$aœNàÝôÚK1ÝÖ'\‹¢g Q„7ÕÎÚ;$Ï!D%~|û³]ÀÉF_VåÚ¨wSP9–·bò:=ÄJ…Y’ÍUXÉ’ÝS*œ3DØlu”†¹Šóùñø×&ѽ°ù”h/b.ÝÈÎVNmb}Q+­-‹5ΑÃ"Á€=Ì­1÷B«õ!h‰è±;ñV”ìDìÎÏB_)n;îoÄI)JîC<¬*ø…®dy6¤z¦å¡ÌÙ4û9øÅƒ˜¡;;b ÔM'÷ƒ:8è3$š1š$QÍÑ D™g ÎkrÂ"+’ÀçYŽ.3©f+ m®{8¡Õ=· B>Óî­Æ€lT4­±² Ôb" êÏBBë¤0`¢·.|YNåáœm×ìñ8(ðû•‡z¦eSŠãK=Öe3É-S­J8 ZÒûާD®ôÀ£-O=wl¢x²wl`éòDŽ<%î´¼°~Ÿ¯I䊃ÅGÅЛÚ1`äÖNYéƒå1ñžEHŠ#ÏЗ”o½©,R«ìrÄàçJP,QÕL`"ö*ƺ²óíÌöã(¸FF~ž"Í©±87âÝqúR#Æ=.Gû$[«)¶Dëà²ÒEÀ vÀSm 5äPR•LÎ0#"+‡Ÿ]Õ%yêſ²7=S–Òâ³xØöêíÚš`Уù´– +›aYkùxGÁ{¢i>pK zq‚v_`ºp:X·J[ÜÉ+Ù¼X›)RëGl’“ɦÙÍȤ>›ÖA/„徺)‘cC  wkKÒWã ™l1}úÑÃrC}-fmúÜíb)´’n8jªtrPÂvÂÑðNò°h7.eÁÝÁÃLEpíŒþ|زïû\Q$ÐÁßq<ƒ_Q´–ì™ÉÁ¹ÄæÁž8Î|!Í}ô3$r¨TR‡WËø©„ÝI„²‡)€ÑØ _@gÅFÜùÊâÕó•yƒì¤VÀy* ,½;KÐäš1qp`]>A?5ã.HÉÈïi”l¬2 ¹ÄLÙÉ\²IQ1›î¤ ^sŒ¢3*²ñì+ÚŸ[i¬#ÉqáÁy ò'‚tœa¡çöèÜ—õÖ‘\0iå‰CMª\Q°"Wb!Í´ ³dFKÄ€“mBãXÈ&".áQS¢zk wdûʇ±Õïm0'7Á?ñ'&,ÐÛXÊî`2Nþ=Ož›²Þ3ÁÒ›ÝjX¾˜Ü~jWo0Š$øäe‚Ô•Î[](¹0Ð:¯„l)ç— . 0Šxr£UOn z‚\:[µ9.tM#ËŠïÖ’ ì¯znØñlø‰G¡ÁV}ÿ\³„ÁM}ó»š%t&„_ZÆòºÊQÄ8åÔ{xÔa”û=Z ‹%úòb dÿ`CÑÇž‘†ÂQaèìrÍ„]÷’³*.ú¤”+çìƒhŇ¿Üó`´5üeoRQA탻3„ÕÜZî諭²Ìx¬ï®×\ bï’ÙD;¹„^úWPê—µ¨s ¯þöò¥d× ¿äêBf–Ù¯œÎl R~ƒÓÿòêÅ«Wï=¦¥hñ•V”4á¯Už¥!]höª;‹øO{ëÄÎa‚â‘KY¥u˜éôÏ]Êré:“~#+lÏD<í¦›Ùp÷ÈoØðü;Ô®eƒ%ô ¾“‹ &­N‹• I^sxù|p:½œ{æN@Ž<`-€@ù‹J·Û’ù»z+Vêa9–þ¹–™*ªK¶k;Œ8 Æa‹©vT]§ºƒoP ëÓè-•jŒˆ¶ äVrÇ4Y¿-~ÞÌ>³0ÁÒmÓA:+˜Äìáx¤e/5©]×z—å ox¬Çð‘¯tš4÷¿zÐüÕÃøÛ†)iðeÝŠó.hƒ´ï9øš?l WÒZ˜³¥¼çé¾g?D5Õd·ˆTáÕŠ•ÚÐ϶ˆv\œ(lÁ+IõÞ&NÑTùüÚUí±›ÎðMçSI•¡Nx9ÇÏÇ, Q¹wö°µ“"yõÕïaLN°u®ù[|F m:¤újü$Ÿ!DlVµÇ“‡Ož+Çû¸Ã3Ný±å¾‘IW}”·˜¥ÖIåšðÈpò¥,ExÊ¿¦›DìêTLw(\šw—;ð?™/"Ç=鉯þôÅä ÁÑÁy6Úû:K—RxžÊ£À’£•„ªÁ!-B¡0Ž®¢èhÉUÉd/.ÏÇ3(uLNUôôMÕ¹®öL—£/€a¨ ¬þv-‡ó\žžÁC¾èJùRÙˆXŽ<¥˜K…›-c˜^п}L9,HE:¸Â|¨cR¾‹tlj‹eîxæñÎõê,¼ý‚×TÏá ËS/‚äÙ„ŠÏV¦{«|™¬A—æà_AÚâzseWA?Zw¡Sé.!k—AîÆ© ð5ê\7„G9+Ê å’xùÝFd´0饊!¢fiòÈ5†£Ûú„«Ÿº,ί1@þ$qbÖû-<¾¦¥ïÇAqÝ@ধ‚wö£ 5Mî!<¹Úˆ“ßΤaœÆAšH']m8º­O¸z;³dè_m¨Ð¨"[É¿ð›/ö¸]ŽcÕ±ö…-ÂÓ‰> endobj 146 0 obj << /Type /Annot /Border [0 0 0] /Rect [128.1818 492.6235 311.7578 503.5326] /Subtype /Link /A << /S /GoTo /D (Memory Leaks) >> >> endobj 147 0 obj << /Type /Annot /Border [0 0 0] /Rect [404.6946 132.4493 522 143.3583] /Subtype /Link /A << /S /GoTo /D (Portability) >> >> endobj 148 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 119.9046 126.3637 129.0561] /Subtype /Link /A << /S /GoTo /D (Portability) >> >> endobj 144 0 obj << /D [142 0 R /XYZ 90 720 null] >> endobj 145 0 obj << /D [142 0 R /XYZ 90 720 null] >> endobj 82 0 obj << /D [142 0 R /XYZ 90 655.5401 null] >> endobj 113 0 obj << /D [142 0 R /XYZ 90 220.7265 null] >> endobj 141 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F52 24 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 151 0 obj << /Length 3829 /Filter /FlateDecode >> stream xÚµZmsܶþ®_¡o:Íø/Ù™~pì8M›ÚÓØ™LÇñ¤Ô‘:±â‘*Eÿ¾û¼ãYN'µgt °\,°Øg_Àä2†ÿÉe_:­£Ü8w¹Ù]ÄÒ}‘Hk ë)É×.¾zc“Ë$Žò8O.?ÜΘ|(?®’ôz­ø·z½+š¦»^«lµ>­W®3½: ]¬ê¢¹þôá¯ß|ÓY¥žI$RS‰’$‹\žÛË43Q¢%¹Ún¸†×í궯ªòOܾŠÓ™Iâ+~ü9¶±Rܾyª=t$þ­n'ïôÅŸãßÊRm®p ×:ÑQbc÷Ìœw¦Itlƒ „x½‘0ŒŒÃ¨Ô6¥†FB˜Ýæ…ðÐÀÞBŸvEHÞ;é*PhäËPâ'Áp²÷펉(\¾£ðd[ñPɦÛPH^}È|m¾æO¾!Á&7i®\ oqÛÚÍÈm¢¾e¿>±1 ëv“ð®¸* þêŽó%ÕRÌÑéÆÙ*Å(J]•¦«Is1NÃÊY8®R+ ‰cÝ3a'©bRVLVðäC9¤W¸ræ{ ”šÓ]@q|,óqj!iûÈD}ÇÑ};--}¦Ü:»o}¡éÑ'ÿÐ{ç{𠤞«”†(ÛóðÈ¡b–¢ßü™•œPHCp¯Ò£r¼&©L#Ã>+„×BY¨A̪&‰êR*j,;Ê¡ð¦]8‚|ØCÅ åÄÕåfÄ$!N½‰í™ºØ/‚¸˜= #Íͦ{xZ$•AXžzìz±ÄÊEµÉu[V¿ýŒöC¿á÷$V4‘NµœÖ&Î HXªh³lÊs_m e{¶üêJA•oÈYô¼Çäh¾¾M½D1•‡<$EjǑ֙™W¹®#:A•ål5âÞøý®ƒgí §I“ôsГÛI`ÏröE-%ÈhÜѦj¿HKl¬¸ÜÀsŽp1c /„çœ ¾H¶L_ÃLxïý0ô̽6t°—ô#¡!V¢°k®îr°åªÝTkÁ-‘t†75³š8sç½$¾TŒ l޲•Ü­à„>„$u8P?öõ0T­l›rⲑ/¹T\WS·co(ßÃ=0ðÛ;qŸÄˆ7/]my|¬Xˆ|{±A`Ó*Ü™,™#d{l&† lO*é&ÑâçL¢Žt=3Ý#ñp‡±…@zK.·8·¼r~}è%–¦Ç;T ÒW-9±íÝdŠ˜}‚JSu“Q¾ Bø ‹×8¿íZRk}7è°ñ¢‹ã‘¨IŠ…‹}ÐMÎÞ`Nö¨Ø­aƒ<®‚{S€zt˜·¡ "ðÉÓ ÁÔ˜æÁ ‰)b"vwþ$jo.5[š—VñaеlÜמò¹«Š‡y¯%”÷Ñ›{ùݶ]?ŸsAžzRa8éuz™›_v£šDÞ¢QU÷mU¸¢†‘-W5[©¿¬èî0Ì‚ÅãJ{ì+ìnRa7\aÿ–W]õÅÀË¡âzJ%[gW¯¨ÈŽv€Oo¨ºNY2ø*û7®™Ÿ+¯sMé;ºõtç :ŽâØ;ݪï»~]Ütýp¦îçòÄÇ!åXV3ÙXäÙȱÿ.qLÔöxÓL-àß_=ú4o,l»1#6”ë#dt­g0¯¤( sŠ y”¯Ao¼Ž£s“ã*r5wñ\ˆ0q2 f/îªì>&n ò%\½0±ƒl|¨w»°¶º*¬ìc?݃ |‰ñ0Ȭ!ía'³Ü·é¡5qT›OM¾zïŸOk) ¢`¥KGgjžn=%\ªuœ0œÕ:Pd¬ºr$å<Óé6Ok±f±kRf– ±*N±°Ž8²™9Wˆ të)áR%ù„¡D” ïí]à«Icgµÿ$ñëå%yʉŸÂÃz¹_éG%—Oް ?‰à'ö•‚fa±—K©ïp6½OLø(·^ôPïù¥m7zk·êÚ ©7u”€â? ÁT߉!OpèûS÷y½,Ô}©KâL¤2uÎ(ÝzJ¸T;a87 §ð–zõñÇ=¹±-?þÄ ãè³ ìx}òI Ú¬Fli”=)|Àp›ëÙ’l"Ð=·¤S†bYªV_K1Å.«ÛOS3ˆ˜¬;²a—*ݯ—5ÅMÔ—ÍN¯²A²‰ö¨Æ‚Aä¢g"¡ÚB*Õ5lßü¦cu0-v˜Æ nH§!@YÊOµŠ2€À/ö•ùøËôŽÌBª:~ЂŒtÀCY{ë Õx^\í¿@ÉóÈeÉQXz[ƒ¤5$Þ¤±-‰RÕËÙci³£Ïmâ8wóÜ•CõŽ#¦gÖ›(XU(RàgPô&ÌÏ™@¶ºóhÁA´|†$¤C èÙ+Î*-9áReĤQ–º/ _`#sXf|TFD.F%¾ÌûD»çn#¶="4>Ï2[ìøw€Õ;šnË Ë—:Õ8¿Ôð_:ð®TpDØG8"È‚¥£ï}°%EÝÏX;L`Ül{Ä=û¡™{.ËåЭs¡6? õ¬™ün­¯)é±¢Uè*CÎŽ_âY«Ng•xV| $¾® ¾Ö6øûì¡xbúÞP‡ªÌ¹=æÁžêp-›EÄPµà2røg‘…DýŒ³ÀOT§$ËŸ¨Šÿï]5Þ™ ½"yºçD?e.à]ë"åö3U+c©Œ?3+²©w÷<º ±5½Š±u&õ $Þ?íÿé’?†Ï )ÍF¡µ³€ |¹˜d!“µ\;Ç_*Ï Õ<¼?[ÿæ`c¥ØrT^qÇÁvã÷ÜqØ83}bÂV„“( z–/¤låY2~ÙW‹ª j§W˜€ÓÀÔ9Ïn—P˜ÙîÄü±þ†ºù˜#ù²d&‰Ò$øŒÛ®[t .JÐY…K2ä7Á/H6Ó±ëÿnßÿ?endstream endobj 150 0 obj << /Type /Page /Contents 151 0 R /Resources 149 0 R /MediaBox [0 0 612 792] /Parent 121 0 R /Annots [ 153 0 R 154 0 R 155 0 R 156 0 R 157 0 R 158 0 R 159 0 R 160 0 R ] >> endobj 153 0 obj << /Type /Annot /Border [0 0 0] /Rect [227.485 599.4781 473.4246 610.3872] /Subtype /Link /A << /S /GoTo /D (Translate Return Addresses) >> >> endobj 154 0 obj << /Type /Annot /Border [0 0 0] /Rect [262.6964 512.9481 435.0298 523.8571] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 155 0 obj << /Type /Annot /Border [0 0 0] /Rect [417.9054 467.446 522 478.355] /Subtype /Link /A << /S /GoTo /D (Disabling the Library) >> >> endobj 156 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 454.2953 190.5153 465.2044] /Subtype /Link /A << /S /GoTo /D (Disabling the Library) >> >> endobj 157 0 obj << /Type /Annot /Border [0 0 0] /Rect [469.1339 211.6137 522 221.3107] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 158 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 197.857 206.9481 208.7661] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 159 0 obj << /Type /Annot /Border [0 0 0] /Rect [110.9144 171.5556 340.0593 182.4647] /Subtype /Link /A << /S /GoTo /D (Using With a Debugger) >> >> endobj 160 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 105.8022 262.3335 116.7113] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 152 0 obj << /D [150 0 R /XYZ 90 720 null] >> endobj 83 0 obj << /D [150 0 R /XYZ 90 587.4686 null] >> endobj 94 0 obj << /D [150 0 R /XYZ 90 259.8329 null] >> endobj 149 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F72 9 0 R /F54 56 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 166 0 obj << /Length 2715 /Filter /FlateDecode >> stream xÚ­kܶñ»Åý`màUERÔ#A?¸®Ýº½ÄA|-P8ÁU·ÒÞ ÖŠ Iëë%èHÇZ7@mØ"‡Cr8ï™UWüUWyt•æqš^íŽÏ"|¦d´Œíå7Ï~ÿƪ+…y”««›ýâ›òCðêPœ6*ªÍVÝfkŒ Ì×›mÇÁ_ÜFgÁã`p¼ø=`wî¾+Ž<À5q`Àp¨xp]ßu/ºG@Él–*Ýütó×g¯oF’­Ö_z¢ü¯J²8T&¶ôªc±Ñi÷ÆÊ%q>žx²Cr]Wñ¬èñ›ÿBºàP½84 •xâÞ¹p‡ûqq{lÃL¥óy¸Ù&¹ ÞîùŽGd¢;Ë…|s´@”xOÌäb{Ïë/­¦Lª\¹ð)²´†a–y²øÀ#7Õ ˜˜Øô‰’z¤âŒâHÄ7ðÄ?µ.»ÚšÈ„ÖÄÙÕV™PÙˆõé„"õˆ• Ìb5{°!€tèðö¾*‘~áZ1¡[xŽB¬»ŠÄ78¼ä‘ŽUÑÖˆ}ÏóáÀGA-·¡2dnÅù§ñå:xèHÙZ¡çÀ0½¢4øðhù`b¨ ZÔ¸Ýò3àSÖ°nª®jñºq^ :è…·¹ô&ͳàeÓ»ñ,u!€"6¿Ñ*/•Žg§™m"*=¶ç1¼q¨žû©n*Ö¼žÁ¥Âl‘óДWž\ÖDÎ…,¢ÄóFµÿò â(eÎD”àPuu_ X0jdKÃ“Ö ôØ”‚ZÜ!†LH_c²îˆ­>;6pÀBéÐ&4Êįdö!Oø„ÓDc±.c·¼:¶(·4èi²;³âˆ~é,Ü5ÿØ3¼÷n²ÝUÉYŽ•lÛ9V¢– ЦáÁÜ óÈǺîQ(q³ ½Â •¿h¯Zû¼âÁì5éë– Hˆ£T0ÚZ¢…6:ØIQ•ÀëÌDÁ?7™aǨ ÞFFxu1Ú@H”ðÝ3WHÄ•™šÃìì_Y  @šJƇç([½( ”¬/ˆ\ÿ\ñ*žÙÔGÐÆù÷ ݇„£bˆH&Ì4´6Î óƒ_ Ä65r»+¼uhd¿¸!xeYí ºràµéI=Äô>sý6 ³4UâÔ‹;× k¾Â¥‰tìƒ×™o'Ã×ÇQj£ñp1ìêÍè©iŒ¥˜=ÂuŒ:9XøˆŸ§¡£$TÚÄKe"pˆÖä8q"ªZrñ¢]&$1摇NvtÅ2ü™äñƒv¯c ƈãuÏß»† ‚“1O9lnvˆ\Žšî]&b‘Ÿ¢W̼ ô¯†ŒÉàZŸ2áÓ{N´FnâÊ¿’R0ò<þÌÏ„œ³½¯Öõ&ÉÃ8³¢{{}}ûýï^½~ÿ~M{RšDç‚]VèEQ05k1çÀÕ%‰Ck[_å Ù”u¿ª¬iÆÖÌò§•#·Æª0ãdioGp˜?F6‚jÍqý¦ªàH R Ûñ{¿a…]EüÏ͈‘Y{A¨Ùó#ÈUüE›Õ¡JcŸ¯•nò¹¨ÚÎ Tz©EMœLZ“´âÑåÒf'ßîqyÞó´a"{)”¨X*l eÐO(ƒÎ!O„?¿M²…6\k±a†¸ïͭƈ½q(’— Å ×#ÑÔ¯ÜW-ú)U ²Ÿ¿?J¶Vxu7Á3©3zk¶ÊÉBK/…ÎöŸAZG¦Áeų€‹!œšÈë¿ûûõõjjŸ„ ¦Z°N¤)®fª«î Ò*ŒÒÜ,5öw‰ê¨´ Ç…_ØjE`@´R·¾º…áí‰'àOtýÍÓ‹JÖÄŠRÓ@ð%¢t¦yn±š#•ÅD“ ‘WöA`~Y–˜"b†L¬,8K4i|Ç>€Û~(Ú²èJ\°Á¤ gÞÖBH]a!:Š¢Sf¦À­s N½7‚|ã‚?ÄjöùÀúYzÔá:Ä®=?m,d¥]-©+’L)<(jBǺ÷É5ô,ª¡K†Ÿ[vúKŽŽ#žÌ(L7‹"ƒ&IíÕ²ÿšlËd M ¸³Õ˜Ò¤1äÃ?6Y<#7ü4)– skY†ã~ÖÆQUÊ#Páv·U×µnU‹½ðçÞVLš*´ï˜G ¨ö<ž|VÎ.Šõß›^[4|PécsÑÌ3`Ú‡YŸÂP^Ñafc@¤,æã†²·­TF†Ò;Øá‹g<ɧ%UBÑ#8ÙùDMÕ?NYKyÀ»žŠ–$x;pu²+Z̪"®8 ÚÌî«”ZÌ­çI˜ÄÚ{/¢~èèÕóPz)-Û0ÊûqDå «‰(x²„ :eV¨¥¾Ë!…DoA^â9m„ RH’Êt,¤È5gЬÀdSÁn2Ò –-ÔHÈ@DkLœH' ;,øÃª×œý‰þü<ª—c@=^/˜™?]…òÁo‚ฬ)¡±B—ƒºå°gE=8½k¨¬Ã¬– ŠTaò1ÜÝ¡è¾ZšnãîO0ö·/V·Þx‘Éw”¼¤À\‰JZ‹Ð©ö)§ÊØñP² ‹„qÌ’‹¸«rÏ«³¦ 3½ ûÇ.@ ,¾ÁÉì0A#ŸCô]ºžµH ÌUóyÊŸ¾}y}ýîÕ­ôÆüâ"[¹~÷ç7o¯_¯¶M˜êÄgÜnÞ bmëê1ÑègÕ€/„`tfÈnIš€ ›A¾Ð¨c*OâqV„HÞt©ÃcÁA„]2¦O¤¾çyD”†2Ár ¯ÜÒÎydõ…<ñ´ŽJ¾ã·Ä)¨a"mSÿN`>¼Au?)ÖÀ¾á)7ažä>½úäà) …ïç¡t­ìN.Û®ÚæjæÍ.òW(Ð3_Ìñ–•ó ÕKLOÇ©' <ÌÓ8]³4H”/Š{+uðd1ÎT9âø"ÁÁ%ûlÙ‚¡XÿÊ~i©Qt¥ë0Oy½;г“È»ï©UÈX¤´V²U½”Ñ>¥Ú՜ͱS» Ç3…ÚSOrŒ€6]tÊpÎ]7Ë:q¦ÛL¥ÀÑéÜf–àVîb[ìÓq‰!xÛl:5iO’‹w/çÁmWãýR‹û ¾ÐB÷hŠ)Ú¤ËÎ KàüæÈs¢ ”Վ”•qæµÖµ·Õ¿ëá×½ÅR"Ÿ"`"òbµ®ƒs³|¬j‡/ga™Å©[ ^ËÉÛvîxª›Jf“‹º±µˆÍfɰ²èÂ&úóœýèC(I!ÏOŽí‰z 5Wž?§´ûp5ä(\ãŸðJ]—œÛKfö[^^:ŽAƇÅoH›ùbj×ó7š4²—ùÛÒm-³!„G/ÿþàÎ wK‘ŸINQ+1¿è ¨*qÒ]}ð]éN¥SÑ;ýµü J»$òñKjN6ÏGí$‚>è̓TÑ û™ûçßR^¯ó aH«}ä¾l!­KÝ›Ãzm­-19óµuö…æT:kNù_Ka®þòr!ïeûêÙszÞຸ,™\ø«ì§endstream endobj 165 0 obj << /Type /Page /Contents 166 0 R /Resources 164 0 R /MediaBox [0 0 612 792] /Parent 169 0 R >> endobj 167 0 obj << /D [165 0 R /XYZ 90 720 null] >> endobj 168 0 obj << /D [165 0 R /XYZ 90 439.6044 null] >> endobj 164 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F72 9 0 R /F56 104 0 R /F55 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 172 0 obj << /Length 3101 /Filter /FlateDecode >> stream xÚ½ZmoÛÈþî_!P„ ,†ûÊå÷áÚ$@¹ä»Ú\àÒ"%–H•¤ìóýúÎììòE¢í\’öˆÈåpfvvç™g–f³þg³$šÅB„‰ŒãÙrw¹á›3æ® ±ŠüåòìÅkÅf, “(a³ËÕHÉeö1`f¾ þ ^îÒí¶š/¸ –0&Dp97"8´U=gA‘nçŸ.:{uÙ™Sœ?åŠ<呌á±NôL2!•õëã빑Á¡Óà Ú®ªò:øŒ±0Qð Â8‘}·(Û9˜VAf§´¼ºÍëbuï^ÕC㌙Pò$qoþ©È‰©¡XšØÄNh9çq°wÒšâôܽb†NÁ¤#ùwöàÒ„y.B#Ñ[gNj¡S2”, 2ÑÊ]nŠìk¬àL¹l‹ªÄ(¸Ã"æ6»t¿FLæV–Æ2Ão‹ þ=ÀºZ%;+¿«ê{Ò±·;¡*Ê9O‚¶SæÔ´vþ-½šÖ9]4(u˜» Ô9- T+R¾Ã±ÜCQÐ^]/pöŒÑ<·¹•nÂùBë„6%lSá>7¹]²Žåxy‰ÏÛ¢î‡6yº'A4™Z?€™Úß”~Þýýí[º‚ýo#ÿ"NË”çµõË€_ j`V‡¶(ÇC6-ƨ.›©é¾üùÇ·oßÃó¿ç‹uÅFÍ´”¡6\bBýçìã§h–Aòýt…R'ñì31äB&³Ý™y̿ߞ]œý­OÏNãb¨r"G™‰BÆ–ÑÓ¼úðæõ?½ä°§cC/;OyÉyƉ{ùêÃ\¨÷(W+—³æ“ ÉB@ªoæ»Ó÷”ç€z¡‰´üœ “„,};Â'LD(:ròÝûW°Y1È19tø%GøÅc|A!€©PÆÌ¿yùj CÎï1wxðïøÛæ*…t’c´G(Pj¡ü{ÏÈÂ2µ€Uf{OWÒÛ¬µhsCÂ=̈^€ …w<¶Wí&'ùBí ˜UåÜêB EñMŠ&z#62((#‰cÄ5!«QpšKA7¨4½Þæ`’d2xm±²v¿¥»ý6?‡;WVø@Zߺ׭ù¡Ó’Èh-¤­é– üÅ¡Ê çez ·[«kŒ39¹„"2¡Ò|õÚpÉp*ޏ—¦‚–%:‡yT2pÈ.^¬òriN@ÃR!„´U‚^¢¨á»ñgB)´ …€ )÷µ\æP6ź̳Š©ÉòëÃz’ÓhjÉØçp÷eUÒd¥­ßÎ(MÕQ€)’“DaÌcÏ_VÛtÝLy$t=Es&€™)ž#†€¾õ%•‰ ¡z꺬„'™ßÕ¸!PV€Òpéò/Ý-n‡{z4Iáèº! )ÊdÎôQévÙËÄȦ¥1ùmQúçVRt;W òpªø¿Á5H„M+‘àÎÚ¢ÎÕaëÆq÷%œøU^RÔ$k+È,×ÅâšGÕÝOwŽì ð]Z–»%€XüÎXÛíÄ ÓI4ƒº$yã,[Ä÷(Ý`èÚ&R>5×Ccq*æ:¸ÈóS²ÃÛM2SR„®°(Á°}|3¤0Nn1œ¢0' щ‹ÜÑf xÎqºúø’ Qn]”kú‘~.|Ô=!þè&QØtžŠè´jcs#FÓ™h˜¼ØS³9Q‡“qÑìPý-JOÇÛ´Çwç³+(— 'l±”kBú•žfSÁf´y`”~õ[F»ú„7ãÊDc˜‡•NéÇïÔtwN=‚_ÚÑU[M2áñQý°àˆÈ÷pýP¡êH†Ew4±qNcËTw‘xbC#ì%à£È@¤§( "ä.-ÊÇŠšˆútØWØ© ³ÂúÒeBu꟫Ѩ‘'@¸öåeW6è;¯$uõnÜâ8â\Ns;…%@wÔNü1j'€?Ý£€L{sŒ!0”f]Ø¿5u„Õ€,Á8°JÊ÷šÀˆà×": 4ÇèH¯…Zg«ÝÚζÌ:pó]/Jâ}ѧ¢½M~O7)U Ú&n¶ãêËÈÞ±‹Ö×Ù¢¥“–â÷Ô5ó¸,EÄ´h™¢§˜\’è i6ë×¹Rê\H· ÜÞu ~>µá™JÅ«&oû)7€%…Ru$~@m·vï¨P2ÎpŸý߈ÕÕòP×ù§6Ì„FqñG–ݧU‘=p ¤…–OÒ#Ò“ìHH}|à`‡h¯aÞ{ʂÄrpsìÉ¿Ëu©ºb@RÃã¥i‡žÏôFaDa2ÑûÃÑIo=¦Gnm=y€×ú'=Ô3†&Åìí27&eIJÚ{—©V§ 8˜ÞùŒò¾t‡žÒç'M ¨ª¢‡}a¾)J˵'Êž0º¦Â%OS©ºP;‘­=Bë0æÕAÜâ®›ØàÃŒ÷J‡‘1â û–ÇÎF5ôn‘öý@µÇ­Õ\5m=å4‘ŽÔÓÍC!ùdóÅ]zà^ÎihÐ<À]ßÒÇÁz[]c=‘~°~¢Üd[?l+àýÔé§ãm§kWÏ9ÑÖÖ§µ=G”Á;»O»ó~*¬³6óUidSgkÉUÜqn¸1Á>m«3º·uQÅî·?/E=/†ëéc1àðNØ•œé¯?tòC•SL—#ØÝ›Æù¿ÿ\µG®oð¬ôÝÍÆ#YÜúfn¶Â+ã;[k“BàK`«PH‰ü‚‘JÆçoà¹mšàÊâ(«z`²ˆZd^  ¯q}Ô­{£&ž ÇÁ²¨—‡]D}ÙµU0|×ÛÛTe¾vß1¹iC…%wå.ï ×}òЙ¸–ògö‹×TÜ9I:•ßaÎGÖ+H÷{Ú´ö®û Ðñ.ÅÙfGMl36Ów±Š zü “$¸ðIyÒ8J-CÎãTÀ‹Äc'· N}Ÿ:Q8jÑ?Û8å“À¼¸9j ŽÚIÄÅé§k'kì#‰{»>±ô´äœÐà„Q¨å§ÉNn1œ:4?QH­$?JE_±FŒò¢Ú9ÿÜ™bóýdgfÂ8±G—ƒw_Ø‚0SØaõsW¥ì¹–½l«›¼lèzS¬7çnxSçi–»ªíf+7©ãr<:ŸÚçÏý+Qe ÿ´§{¬yû"óÅæDÍ Ïxú!Ú‹Ú¾³÷?D¿É•ÔY$ÎÑíªüo~èøþÙ[å:Ñg‡®Ešg¯|<»T„5+jØÉ˜¯6|eö@„3>ÐU±ufžÁ›x÷ìÅÈ?´ÛJ%Õw`i`Ù6ÁEY•‹UççËMžåÚÐ:‡ú¸žT&ÄéoH¹NZ Ì“¢Ì'ÙÂ8Ò_ʶ©Ù‘ eùÇ$ÌOiõõ5Ûk\ U¦¨qD¡§“º·ŒNÿòîrŠ ò«:?ùN®Æßy/t>ü„7õ¥Tr"üf3÷ Ÿš¸Ä|Ū£™_¼ù×+G+Œ†N‰ã$š:Z#Ðê›Õ&¯¯šâ÷üj? ²£ÈO†‡š$‚ø¸ˆ”ùúO´^ãb¨r"@ÜàiŽ{Ó]€ùS füê·¹G‚«P0Œƒqú7“– Ü10å¿glLÛq¨•‘c£ã²Iõös0´VG=ü áØydaA½d±°Ö¢ÑèW/¬×¸ªœZX$>JĽiŸó®+d¾_×:o¯Ò,«Øâ<ŒõQ ÝÙ6bsÿÁj[y–5iÖHÔʇ©µKë›ÇR«7L,OHc}”Æ_èNlB.¹OÞ&Ï˫ɶ\òP#´<õ·B°b‰ñä1‘ЦZVØ–SœbÅû¾"rsûÝÝÙcEçôð¾ÿ{¡¹ï¶ºƒgNUÿçeio6uï0As{ž=uçñ%=={±.ˆ?—S|£?ªµT5Úð¢þÏe xjÏ]»ƒ%3nèúïûîc¶€?øîµ!qFÙC¬ô¤¥¦Á.ˆ&žú’¸è”gÝSìÚQÅŠŽçAÉÝàŒ˜Wƒ"Eëqà¿;mž¦endstream endobj 171 0 obj << /Type /Page /Contents 172 0 R /Resources 170 0 R /MediaBox [0 0 612 792] /Parent 169 0 R /Annots [ 174 0 R 175 0 R 176 0 R ] >> endobj 174 0 obj << /Type /Annot /Border [0 0 0] /Rect [171.4489 540.6176 384.133 551.5266] /Subtype /Link /A << /S /GoTo /D (Debugging A Server) >> >> endobj 175 0 obj << /Type /Annot /Border [0 0 0] /Rect [464.2279 351.6991 522 361.396] /Subtype /Link /A << /S /GoTo /D (Debugging A Server) >> >> endobj 176 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 337.9423 263.8603 348.8514] /Subtype /Link /A << /S /GoTo /D (Debugging A Server) >> >> endobj 173 0 obj << /D [171 0 R /XYZ 90 720 null] >> endobj 170 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F56 104 0 R /F55 21 0 R /F58 52 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 180 0 obj << /Length 3308 /Filter /FlateDecode >> stream xÚ½ksܶñ»~ÅM¿ônÆÇ`3ùà&NëŒc§¶ú!ãxTêŽÒ±:U’g5ýõÝ>Ž’œ8õxÆÅbw±oœX¤ðO,òta•Jrmíbs{–úé›3áGk€XAþr~ö§ï2±i’§¹Xœ_œoß/¿Ùw+±ìÊÕZ,›ÕZ)µT^­µÖË¿Õ+é–÷8©—]Í‹?tS_7Å-ßãÆ Qìx¢Û•ô®@$yñ”ƒxb¢P>ÖÀ8Äl¹%26]SlnüV3 5Zæ¹ßùsš¥,‚*Z$¸©mÇ:ƒr#ù(ýÈðÄœ¤“‰ËÁW‘áHóÙæ1®‡(ÙœF„Kg’\ZÑM¾Ä7|3¥T¡TÊ~?J#Ƨ(UÂLˆôá†W=ººÕ‹«ãa3wµÆ‚#Ñ¢¿Y1g`Á J£ôØ)¾% ½F¥kIýP¯•6býߨÞ[,Nv”!mÐßPâpÍóW=F‡àïwÝÃÎcNøhŠÚïË-/uÅp/†k†›PhC~ÄD&—Ž™õŒ:¡¦¥`‰Ù!¥:è Óý,„|ùú¯^ñLÇ9É“¨ ´ó}éQœ¯0ÓèÁ‹”Nɘ ž÷tÖ7üYt¼z¿ #òðWusëeMs|5¸á®!:ÅG¤b[nŸá‚ ùÃÏ!,ßd5 …6ƒœEå‹Ìš$éç[Dĸ¢œ …6OŒIuô£¶+Sð‚¿¥ãS”JH` §WJ9vŽâ•\8‘Œ; ®@’¢Q˜¿ëp‚wÆACš H6êóƒFÈ ‡¶º>”Ûõ¾F³FÛ¢™î-į WTUlçðI•eôSKXU†±s MìØ`-#,yô—jáØ…4ÓIJ{›ÒçDsy»I0ñtY£<Ä@`ãœ]'™Í-k`ÁÍC ü#’ÌŽÌ3wôy8¶!{Á%ŒÅE¬‡’Ø××¼!H0—4!W†¢HÂ…\6XfÙˆ2øDl¥R+vØ8Iq`WPvÉËô²­Òí¼ÃN$ð2nü!U·ã-žÜY‘ZÈîdÐâ ²ÀèÅξŽõå¤Â†JÀš°kh¢ÁÂÖÊ@Yhs9–Àºïª;ròì?ñº[6ÙxEø¯Ú‘|DȰI<~o1ÐŽkΕµ0KþkèÊ~iÑ£¹BSØó”¯ïi±:\óÐ[ëË »AXô0*¦-›áa+näkæ™mlJp†Ë{C®Œ4ÿê°@„4P£ý„>«>Ω ){:,bh"HS§’è„…±ÁV =Kžð€GmáÝ2N`­ƒëeÏ'µ:ž&¿xíƒ×\DI}‡”.K¥ä\È/Ö ýHTæ¯TÊ(ÿ–lf¬É´‚7 >ñˆe±HÅnÃ'[†„‚@Í~Ùó¿IÇ=¦:Z-ß•åI¯Àèì7ƒDg(€Ây´<èŠE¸õp®p‚É|WHqJoÁ2lRî¿ÿ¶¼D®®¯ÉÐîžóŸwAÅ›ÏúR¹¸ö¬Ò“ŒÃ(HSµŠ þgù=¿·Îå'¹sCÜà&5©û„—˜3¸ lãêqN î)„èõêÍ_/^ž¿xûüüå›×s`g] ^ŠËý :Ƴ(?œÉ­g–ÿœ;J5HËUliu¾…\f.ŠZÌÇ‚Êþ‘ù9š\­3cG€‹1u&Ú¬£4 ©°‡óU„õ€9Êep¶êUÄøÌôh_HÅ-~ÈO7¬ͨÅd„÷¡¸ É¡³aLôa;Ò…ò¦á…úŠ·ÝŽÛ]1~UëÑ‘/ê‡G¼G§zÙ>àÔŽÛ´S/Ã1y;¼VéÀ§’ç†ÀA(Шӟ¨~92ùcûÜëÇœ ²)¶6ô@õ~|}þ¸ú‰4ER ÊŸ8«ZP. 'ÜoS-ÄÚy.ÚŽÂ{‡ŠDA:ïÌX|£ Â|ž"'ÞçÜ숺ilÎUáu¡,Bôdw3î-³áƒz& HñeRýùº H!çÓtJžÙü §ýR›ÄXeMû¥å·i³hu8ÞôMªÁhXïê®Øó_5¶¤<¿íÿr°£GÄÀÕºI†¥5Op]ˆ`Ú Àß#XýÓŒ÷}ŽWŸÌY6gˆ –Ãß{áØû?KžaŽC›ÈQúD=&¶2ŽOÆÝ^V87¯âŽ…„ž—ð$牊o ”Ó8b9'§åNÅRÍ7mÆ9;u^þïöRº±¹ÜAvpÑVÿ-gËc|n€<åK—ǹÁ&¢zÔNÐ?…7Ða+(TÈ´ž>)§.{‡Ó"±\óœÍŽ+îã…ën¨Ü8ß“ãÇ1 ô'á·Ûóo¯Q%µ£œc¿e2C“p¤#æ¤É޹[ÿõq•a‡ðدûpO}ð|5#é‰Q7æe¾HM5¶ÂÕ]—*ê *ÅC7 ‰XšÇü}¬ï>A­®|Éîjæ‚ú§ƒœÂB–áË׈!›úxè&5ÆX‘%X¨tö7>: øtæ~_sA4Ó/Ïmbr+Nû2ãW 'ÍL|LöÏÂY’ç“.Ó€Œþe|î`HÖ¥ˆéÆ¡î.®š²Ü^\Îoò$ÕiÖ?fÇVBïÜÂk÷×3Gfb(0<.ž6¿†zÀºìÉx+óÄÉi¼ý.×?JÝ[‹Ô§Oã-OÇláwãÀ¨C—ˆ2(*qªdS$%/ê{\7!$þP—G¡W}Dš«“ ET.þê ¨³×†°8N{…r†.<½ ‹¥ÚlŽœ!ÔƒŠ2Âk²Äf*ÓËi¦|C%œ±WÇ¿R5®¤~…š8Ú .1óŽá7¬c±¯äñN&§·˜©þ94S'©l¸ŠéF¹ ålj !W“êüùáŒf_˜-XltQ1^”ÝøG?DìaŽ>—”PØðŽ“gr õDÍããzÀ ¿a,$Ü9 =`&m¿µv¨>v®û§\Îeúb>ú°rΧrnàEþ5êå87ù­“ËCÂü@ËÌ&¦êÿXsJ9©g›I@Ýœ/`Ç ÌIèÆ´¾Vw9X Î§³¾Õu9îRÂwÑI`'ªöòÐ’K(ù“o !±Òî6ÜRT£Ö ß>hvI#ýÄá¹Ö(nèG×<7H¦8¿q rï‚N:hñ·`ÛÑ2³tÐ"ÜzøØË"ܤƒ¦¸ƒF£_Õ,ó25Ó)SaS+Ç\ÌtÊ"ÜS\œ"Œ²©î‚ÙD[zá˜Ó1¦˜»ôY ¹t}}ú •V¾š«K’d¶2+Ú¶l:Ü?›&áðŒ1 ÿwpØ×_ŸL}5ÿ+“(›þŽ©ÞéÏI°‡ÜvE×Ζ=Z%öÔ¾pÙ£!ždBÌĘÂ×GúíÁ!äö¨×Ýý?“úC‰Üôq¡üâ… ˆ¤j»jÓŽãM Ô2÷¿ÔÂ&£ÿ¡€7–ÿú|aíendstream endobj 179 0 obj << /Type /Page /Contents 180 0 R /Resources 178 0 R /MediaBox [0 0 612 792] /Parent 169 0 R /Annots [ 182 0 R 183 0 R 184 0 R ] >> endobj 182 0 obj << /Type /Annot /Border [0 0 0] /Rect [464.4545 465.4624 522 475.4624] /Subtype /Link /A << /S /GoTo /D (Debugging A Server) >> >> endobj 183 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 452.0087 263.8603 462.9178] /Subtype /Link /A << /S /GoTo /D (Debugging A Server) >> >> endobj 184 0 obj << /Type /Annot /Border [0 0 0] /Rect [118.7995 158.2984 325.0725 169.2075] /Subtype /Link /A << /S /GoTo /D (Debugging A Server) >> >> endobj 181 0 obj << /D [179 0 R /XYZ 90 720 null] >> endobj 178 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R /F56 104 0 R /F55 21 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 187 0 obj << /Length 3501 /Filter /FlateDecode >> stream xÚÍksãÆí»…gú!r'böÅÝåÇ<;ɤ½4ñL§s¹qi‰–˜“D—¢Ï¹_ûà’ZÙ—œÓönî´Àb,€]~Éà/¿¬Ø¥‘²¨”1—«ýóÃo/¸o-b™‚|q}ñÙ7%¿ä¬¨XÅ/¯ï&H®×¯‚]-%‡?‹¯öõn×]-…]¬`LÊÅõ••‹‡¡ë¯ø¢­wWo®¿»øú:’+…xŽ!yŽ#e`ZWúR[Up©Jâëõ7WV-@¸á‹¡…VwxƒLqÉyQ•ð –ÒzŒ¾}×µë+ ].Ö´¦ÕÍ®ÛÜ<îú¦Y{:e—º`ÖJÿýϬd¬LÁLaµÈ eð Yh©ÕˆŽ{¨É—¼´…e²‚–,xÉÜŽ\oÛ#îI¹¸K–[ÐÜ8¬† ôbØÂxãÚLK\îñ“fßõïÝíá¥×ïë!":ÿ»õßïdãÚ?3® »kQqµTÒ"_0ä ·þ·Þ;OÞMÝ;l’¶€&K#šÖâ\÷Õbõ€JֽÕ¨Ã²`÷hìž:äç€Û0–€?¢k‚v²¦ö–p5®C²îö÷uïäÊžb½©ÛCXáàÇp Z}n­k”ÂþÞYÒxï]³;.Ë²à†‘^¦ÌïV{ó¤Ú¯¶õaórj¿êG\¿T´ã‡c»9жà*;ä{ãqØ”×ÊÀ(÷Höuÿ6GI€HXÌøS‡ÕíÉDø0Ú:-ÉÑZ ©¡£õtCÝpCæqs›£­«‚)V~$í’§Âz‚œ‚­“ªzQrëf¨ÛÝ1œl¶æHÂ<ç“DU¢T2ÈNø÷dDÂŒÚh…¬Ð™`ÓHŒ ½ØÖ8CŽÒ²º‚ÿ…ÓI‚¢¥¶Qã›SB¤.ÔzÄÑÖc¡¯{íI;ÿ1 bö‡Ô‚ðßv4®Y–¦VD)zã!+]ÆÉ‰.% <ŸÐŒûŽS©Å·w9ªÜFG‹8UÎ ^­ -˜ðÀä|¥ðîvpògðKNé°d~tÄ€n_rïz“Ô°ÜNÚãŸm&RêüÔ-}NTO×â„çI’3[ˆJó©$Ï”†Čòr‘¶ÐZV©\*•È:$—ªLå‚£[âZN 4äÀ9À0žÂN»~&˜örˆâ ;:ÕQ,5€ä-/îxnÍS;•`úºŸ2‘æ±ñ~CT†¸í\ó@Ne‰“ G´Î…3’>Áƒt´®ñÿw-2þáM$’ŸDäzç¯DeGAPj£©áà ÛþH"Fè}l~þ—‡ãç+sÆöêÐqÝ3Ç"–…•¥Lc* 4êƒkD¥ÅÎÃ1=ìÛC  ä~¡³nå£'˜z$§ƒÃÖ‡¨Mn[ál‡SZ”3÷‚.OÜsž‚a%Dˆ!ïæ ¸ð¥ZDûÞÝ» ·’ÞÉ—lOØ ¼˜šEšÛÖmø)]-ÿÈu ϯ(ØÁ `…ÂX»îÐ×ñ¤ªgÔS†A¨éq„­QŸŸQ®Ñqcc×ÔoÛÃÆuö m.¥ï1ë±¥Xü–Üœd$Lެö¾´FcÆB¥Ù4+ñ`Ë.“™œ C¡ýÔ¬–þh€ðË2=3A¿EàUeŒrá‚¥×ÐþЏ¾EsÚlZ+Ñäç°°{o`àSrÆ´i\G²ùÊ%ƒ æ°Áȳ’º:“E¸e ˜Yû)Bw¢áʹVà{ bõ¡«þ2¶wûæxÄçâVi F©øïŒ[½ òñøŸsqK°ñÀeN9Àˆ.­šFqï®JHŒNv¨D9?ʂФ(ø_¼~Ã.×°Sß]°Ba,ÿˆÛ úý…,„ÁÀÄõw?]ü=ÙË€q™¢t{9åâ|eÀF8äv׳1%&BEÇS÷›cn$+¸(Ÿ'-¤jžâþ5¥o¯Îµ“ÛÞ9pçP6Íüzo=—ØAc}R¬€sÔ.D5 ŠGr%´%h>½?´î–»ömŒc”;=6û©› qËËåiç•ýI]‡¶úÿO×s¨ ÓA'Š¢ÈÖFʨ=[ЬTåÿXq¢Þ*ŒåžQKqÀY{6Ípsê!k§ÍR–ê·èÏWýüûï_K_ÎÄxÇKq©¸(JÁËvbã2E™sbpˆGÒÈê»~Bµ¥.Aµ·M}³ëoî³ù? ×Чê ÜqØJ˜©ž—¯LÁ*!.%¤ÑÒ0ûÑò‰—)ÊŒ|dÜíHúCå#RùlÛÍöŒ€¨@2;ëbˆ*<)mž Á-  „‡n¨w7ÇûzÕäIñU¢Žð@ÕÜJ0èœ ÿ3º–=ìi•&“~ÏJ'‡Ÿí ¨Ê õú°Î&ôpþTñ°<õšSŒ¶`cÿØîv˜Ü²±ü;¬pCŒRÑXµÃ%>ºN“p v­£—¥Øš*ª]‚Æ 1³¤%‡\¢‚¼n~_sê˜'«3¶0ç“ÕÉÊ$Å•ªZ])Îc¡Êä†ÚADÜ(•_R°Xã¨ïÝÌX-Þ¡ªPЬ €Ç{¨ÞcƥϮ¾ v©8„nkªˆ‘w ˘ÖxÛè»=ÕµÚPÎP üžcÊÐU)ÆmÁ«©±ìÕÜÇbèI¹Ó0ˆÁ£–dΞ©ÔerµS6Ñ)d/ꔃ•ˆUª”lnüÂÚE?JŒÍ}àX8f3a&Š—}x£rœÀÀóä*ƃ԰‹¥ˆšØCg–•˜€6pfž=3ùôÌ„ŒÒÑ©¾ŠôЍØ!6V ¡8æ!Ò íÎkIÑýŠSÖ°êòD'ÝE² äH'—¼Ðö…ÊÞAd¥}FÇ„´XÕOåÓ¤,Œv&«2±møq¶LvžéTN¥¶ê¥…kÓir¢„•Â<ž*ø›+Ìk‰röÅnD^ÿh®¨í |6U_DßOÑ4O ‹)Œ™'”©D+ˆŽfʧÇë'6y¯–æL]_Z3¿å¶HºÝ“÷ñÎü)qX“S@ønCÿ¤d;£w!=ˆS±¥øÓ[ˆ[­Q‰ØÎë ]Zr=™5Ñ^½ÈXaluNbœ‡›jºç|&4Îó*Ø»9R?βêÓ'Žc™¼Çû@4<Ó3Cœ}â"ž”œ„TPÄ[1æ5MŒ™™D¾d ŸdfêÑG‹–éå–M¦å5“Ìd ë"¨‰L‚æÁ-Bá1„ÿ`UÓÖÂP4T"›e¢Æ…ºLð|‰Ìþ€‚ UÓ–«mÝÿyZw9}Ó÷]Ÿ-»€sàU¼™ü­e»ñeK.7PeZÖ nûÛ&ËŠehÎó…Ú²°BÈlvZŠgó‰ü`ŠU.A—?œ9eÁ‰1trw:{ß»ýòÑ}=AEÉü:€Ë ˜Æ\Y>? f˜5U(EŸÏì&5ÀOVŽ;öH/žâk­¼ÚÝÖx‡C”`ì¸íèÁÓÚuGc‚TeMîpj'U5 G³1°kù*«¯ªŒËeæšGT÷CÎá¼ÌèºÜ…_ËRšäõ—öa &$¾íÚîÚvã*¨ wrƒçèúƵÆUùòîè97ÅC?‹Å Ü?hó÷j኿Îü©ð{îþ÷Ÿx}Û´TáZ¯•­ÜƆΠ¬cЛ½«½;Â)§•öT±­SìpÆ“›ÿâAH¹Ý»1êG8·'*^±è ‰U÷ã\¥òOØ_™Ûñe­£`’Éé]töøºŠÏ¡>qA0UÊ„ö.8_¾u3µûÉ’´¦à"Þ/}!þOÙ÷3¬°ÜN‰v÷ÞEÐsùÄõ/Vþ*Ë€¸ÄÇ5•8sÿá–)`îô!òõå¶FÕÆHÜ.”ûy={D 2ú6xÓ×û7ŸŽ9’»¦€Ž,O.±¹u¯úRærokÜs«8E¯r?ûÆÀâT!•vg¤©0¦q‚•.Uƒ'€ ÙÝbÑ3öTÖºè§ !£)Ñ›ð¸ÔèÅ·‡+|Pâ¤Ä@¾&)öþ¦Ÿ†¾ôæ_¬›cNOPÓ+,w‡ç¾Ô@Ï\ƒsjCI`jh8²òl­Ö¡O?±½nèÍ…t±0qF˱þ ©ž;ïê]±=Shªª*Øá'ø.H1\Ç{G‚^D É˔ʎÁQ•„ãµkoÉ.û÷±Òâï/0¥gg•OÖ­ Ì7äYx"Š˜-¬b覸öaþíνË@ž«ÒóŒXèi 6Æ:Çðo\"‰ünã$žÀyžk÷ÂûúÇ_ýxsýêÕÍßþ%[.ó½”Ñ«PDÈíKá@ð†øaЄ–endstream endobj 186 0 obj << /Type /Page /Contents 187 0 R /Resources 185 0 R /MediaBox [0 0 612 792] /Parent 169 0 R /Annots [ 189 0 R 190 0 R 191 0 R ] >> endobj 189 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.606 513.4664 522 523.1634] /Subtype /Link /A << /S /GoTo /D (Debugging A Server) >> >> endobj 190 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 499.7097 309.3149 510.6187] /Subtype /Link /A << /S /GoTo /D (Debugging A Server) >> >> endobj 191 0 obj << /Type /Annot /Border [0 0 0] /Rect [333.9802 136.0419 518.9697 146.951] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 188 0 obj << /D [186 0 R /XYZ 90 720 null] >> endobj 192 0 obj << /D [186 0 R /XYZ 90 124.695 null] >> endobj 185 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F56 104 0 R /F55 21 0 R /F58 52 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 195 0 obj << /Length 2966 /Filter /FlateDecode >> stream xÚµZéoÛÈÿž¿Â( „J.çà r8]·†$JÅîÂ¥%Ê",‘EÅMÿú¾k†”L'Eh8Ç›™wüÞ1Vg1üSgE|–6ËÎÛ±tß¿PÒ aF8žòfþâ§÷‰:SqTÄ…:›¯ŽˆÌ—¿o×ån¦‚¾š…*èf¡1&0¯f¡µ6ø¹é¹›µ‘5±–uËm¹Ù´‹©lÅEœ¸ ˜ä…UoêYAƒr˜4ÎB“ÙȘ؜…ÊD*‰YSîê/¸ buøŠíö€Ú‰Üû¾C&6w¬nj– ö¤)mÃcíêdmÕ³»o¨Õ+´Q‘Í%W «IF'ȆLæ”ݲ`‹;T¬¯¦H‡ZeQ–¥ ~*ŠÄ¦´üÏ3PÉÄs>`[úMcâ`|Ì9™úêhá Ü·i¹ëK¹9…—iü’[%Rp•«ô˜àË][7}ÕñÄzÏ¿MÛsYŒ¿·°Í½4ÛC³K|9Åžx›ìäž?WœI& ´›µ´áø(+]¨`×..«=íIä=ÞŠ–a»çÅhjr€Î[£@çYÊt¿/Z)^Š6à ð¡ Pâ»C{`ÍÂinÊûº|dAKZW¹³à9+VöƒSÉŠµ^Y@{Ìè Ö½r¹”á ·—ÕFQðÙh_bö°Ç Š<,èë­´Êféí¡s}Ý0“Oºp‚ ýÕÈh¾Ì’VÕŽ)dVÎü@\¡—”e'ý c;f mMÙh´Ž#“ÄñEñz„C†º«ë«s„/Þ³_Á:2¡qI¥q¬™}…«¬ò@€j‘¦ÁEÝ1©9ßñä&<æîåÁÇâàÎ墯wôBß«'®dø^Ò±¹åÈÆƒLq3LjÖ- Û‘h‘Hó  {ü:Pèò°!×=ómÕâ hg§F#¼5Þ7·˜úþƒB%‡FTê~CN-7Óâ `ÆÒ!õ å‹«¾¾¼xwCÒ&A?Wª„°ÂŒz‰Œ,Ï?Цnê¾ÝúoÙûèBàM¤?ìĪÊzÃ×}–â¾)QY3ï΂“ÐãM5UÛã:3„S8‰XDž¨“(cƒJ›A'}þGöAÍ>ôܮݯ“¸µj<·—L«oyBW1†rÈbò‡~±3Aò`2?¾æ dÔ¯ßbe)hêF<&°e÷³¥îì#rqu3ÿåâíÈ‹¸‹ué–?Ö¥€â]Ûˆ'ëªÅ¡Û×_ªg‹÷r„$‰J!àDÛ’ô€zºjá¾bYzÑÆœp'ö‡c#¤FÙÍÈÂJ¡ë ?(ÆÁGoH͇Êâ̰S¢ßS"ºlUåX3LV<|Ã!S±H~šþ§ˆÎ®;ž[¯xí€KÐIÇgJˆ®ØÆa²gT€ÆaOì¹ó˸1™ç˜TF Á};ÜC@àærœ)4™ŠLZ$Ç*ð§Ie‰2°¡¶aˆ[à•îö™<¤´Õ.Çš¤YÀæ&•íN¸ˆ³ìOUušëÄFjé3“'Qa ‡´(Òð(5öóÂñĉüø1A<ɧj1X3ðEÀö×Ï "Éà~©ÉKñÇuˆ5®\îÿ ÷îÊ;1BŸ^Ħ:J d¸ãóMäø~Þ÷.ò˜ ^$zBèŽèò˜Sä¹¼~û`1U¿zñ·€ú5^TR)Ï ïëlp[UÂÇEÛ¬ /é~ÀÓÌ׳]ÞÎŽ/¯u Ú:!öóî‰Û=q®(4ãTä»Á¬-ÁÀ1b“rpR ýQð YIßW”;u£¥/Mø‰n­›'lÝÆQ’çæšz¥:û¦1þŸ \ûsyçÛ>° µèÚ ÄºÊyä)kô<:Fvc@WD”µ ¸¡¸Á9”t6΢"µ'EœÓ´[%Á¿°Â…û5°›%RÕ¢£,o)z±Æ%Ñöp  ä>§Våâˆqd[•4{r¿H…˦´á Æî{Pã ߋϦpe’°]…ŒÞôM¹$ÚNŸ\Å?àêü ýVD™ï«·Ný,_ <Á(Î g(s=ï9˜—Z墸%Ç<Îáɽ¯ÂabT»­8i„޾û:¸-@DG uþ8Åj¹|BùaÛÝË—‹± ãúhÛTp“ôÆ©v£¸­S^,É+røRŸ’Ó˜ƒDVBûhwf ±žñ)ŸX)'´¸fïùÓ-†Â÷‰Êpª:éÃ/—Ç<ís!`‚;h/¦IxPYª‚z Þ_¾z7`âl†SËO|”‡ ˜a9wæ&Ùàsíÿ-wŽ9ñÌU¹øÍ÷Òy,õòG8Yrÿþ-ƒžW©N$¯zš’àñš]¹ßûšÎˆF9lv¬Mx´Ü¡¦aÍó|4Wx wùdÁGRr|éÊH ßzsÈÚ9¡h©¬Šf¦TpNÑ51Öp•'O({ޝÆÐYÊ”q•¸¸äIîmçì[z )bd>^ ãþ-Éqæšž_jRãíÔPo¨Œ!…Ò)¦`Þ9ÂívZ7t Þ/ÑßF-ƒZîPk Ðð]J$ ©+a9^”E¯]iµ–²h±{F’:WI¨M¶O¥Ï%à$¨UK¶z*“ˆ®ˆ£´HzçK¬¯ÏCÜ›xtį4èüÛ|ð‚’ð§ûžâß)T€%åd©èykÏ4¸Òé3TØP’Üz]v¤ÐöþÚ—•…¨{ÕBÃáûŽñß. Ðɺìèbüw ä]GÄ6¦SVjmÔ±tåêž;ýcèÌA%÷🠿F#*lp^²"ó,rDn£Ö¹*öÉÐ+@4q·cƒÅr÷`°Çƒ1 TƒRMÙ¥1ƒ]ž> endobj 197 0 obj << /Type /Annot /Border [0 0 0] /Rect [254.5092 383.2074 462.5398 394.1164] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 196 0 obj << /D [194 0 R /XYZ 90 720 null] >> endobj 193 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 200 0 obj << /Length 3074 /Filter /FlateDecode >> stream xÚíZ[oܺ~ϯðۑѳª$êÚ·\œÖmböæä´9+ïʶ`­´´ÙøüúÎÔe¹nüP @› Y‰‡Ã™ofHù'üõO2ï$QÊÍÂ$9Ym^yÒüøÊ—§P,Æ$o–¯þø>òO|ÏͼÌ?YÞM˜,×_œ 8](þ8ï6yU5§‹ uVЦ”³u'5¯ÊßtÄaèÆiq"C·Z{ÈEm'q†V|J&‹Âˆ9Â?ðhåJ8öÝA߮⮮á®'TB³ãÆU^së){n̹‰¶»ÈÙÆÉH{4O=!]k³Ç1»ûû¢åv´Ÿ†«7 éZÑaÈaKÒÌÙ?€Âcæ!_üA©ò¶Ç%“½îРó–ÉóõºÕó¢/á°ò„­ Ч£˜ ÇØWεyh¼Yì†QêW¾)?9f¼šn1&´ïéñ‚¤€¬üðåÁ .˜0–ô­à€—$V¦n%Z›1q|WÜ¢~îïÙ,¾ÂóÏ®d¾¨A4_n R7ËÐÚüÔU©ï1_C·Z–{ÈÍ—qz3~¨™m(¤A8o^¿»yþálˆÛ¦ëÊÛê‰)os‰"îJKYu¾)¦±åG#ÅkT|$ØÞt¼#„¥OÜCÛÃH[•8}’=›‰n°FxAã+‰×j»ÚƒuÐ@6è\øËa‡bL'WÒa=Ã0²)k-E¯RsE ê(Èq¶8Aö'ãÌcàE¤T¡rî*ñN•M£&6иf#oOŒvè¶bÜ 0¤!…iÈÚh°7¨!˜}x<ê¼gy¥¥mdN- eq&Þ‚4¹)²§éøB!¼ùõñDèQíJzh%.^5<¢nr2<šr è m« ±ä‰|ÏcŠNý@a5'%‚©v[½JÍÝÇ›úÿÇ׿’—Ü|8»øóò/6sO3áFâ²3J·dcÀsþi›H…0,Òú¢ï!ë\È"zÛ,Ix§!ÿI{³Ñ ‚(†À§²)D64øp~ñ24䱬‹E½Ûܾ o$Ž6É×nƒwK.ÉYj6J²à¥Ùõ‹#ð‚##¡É޼¨3.Å?ò „‰Y ŸqÊHæE^zoǾŽÎÈ9èK{œ÷Z‹7®M”e‡ö‘‡ÇþÄÃá¿­x8Б‡G™Vìwo îMZ r‚ŒQ±‡Ã¸©‡ñÊ8¡–uðkb&I»e}#G÷lŽî³£Ã*›]«—^p9?³’o3âbhÆ®MÓ ùµÅ¦/v³4Pâ ʃ?6ËƒÌ ÎÀ™¬¢]6ÅIÊ&aØ,Öƒ#- Ö9ø|v¬ÇÒ@˜"< ÛÜH>B„ÙC.>}|sve•0HÅÿ­ÐáÁ<Ù 9â9r@ñyvuóþìâí<îr€A "¤¡\=ý⮨W›ü¾\iô ¡«‡bõøÂ4ôÄ=(Ðþ&¦ÅÌ­=ïHŠ=D¼XöÂ¥¢ü‚’BH¦È‘êµæKóÑ#ùD¿Ðƒ˜ƒK SZ=?øKÕMçhÉröú¡ìû¢ãMCåœó¼V±¶'ËgÄ?Ë ÍËæXô§®—Ëï^aÍsÐ.ÄɰLÈ7† Œ’æÈóŒi#©©}Ÿ˜Å¾-yÏ C>ålj ¾n)Æ«’Y“q ˜€¶K!d:V@z/©}\РÇÁ}Ã[:"è%È û¼41AÚ,[Nñ\’{|lÆ#(ü=šPO_JHÍ*/f•S]Š­9ÿŒj˱q«d¢J}ámÏ]eσ÷F®Yú‚}n@r‘d–DK C’œœömÓ‹„"SÃoÆà¹.¾[#δP.ÚŸäÈJNŠt~WØ!lÀŒ„%s»üåyÃþÿ0€¡ µ€xÁ€\ÐóÏ\ÜjP ùôÂJ†ÑašÐê¤IÃ1Ö¬pðE¢›+Ýf¢ÿG¨ÿQ„J B¡ÈbvZÉj(ÓT°ú¶ÍõÉ(øRÓŽ|¹ZZ½ :D”®‘¬IP†J—1ZÍ3*³ÿâÜ\IOiD㉞‡µîšõFn’z)­÷-˜$;Ðóá9=”Þ•­©e°u×Ñ©QС´ÅÞ}EG¥:·…šd•[“:ÈU¬4ÝÏ6^Xø™$q ºìïlœBÏõ2/úaN ÒöéGD‚…Gpéy-;/ T5¢’;"*²:9ˆƒ’5LÕì\sÿPrU˜31*œPóÇJ:XçÞáø3c&0®ýë†ë¦ç‡ • *»¢œF˜Ýb{âg²Ôœ­ÀT2<ž ºòwy¢’Cº,κe‹ÇÕOŽ ã6àïUQ õ¢áRÝÉ{Nì) \åE™lJ^íó§Îºy°Ç~ªé ©L9m±­Ì_óÌû’æOÖ)s£8L}ĈÀô7ŒµT]ýŒGnê'És¬*ñÁB³è@éõ‹žËG@‘ë뵆orÚîx •%X‚&’x' é<ù|ùéÃ;JC>_/GY¥vc”]é…Î~(âؾ¯ ± €I´xY"¢’ÀŠ®>€”nº/ê¢5þÔe®´}¨ tt7RëCø$´¤+HÆŽ,Ài0;¤v»nG§t …’ÕrÎa=Üó‰~ð\>*€–(˜æ ±Õ'âìxžM¸| c®„)H¨ylD h•Ó±¢KFzØÑÁS0ÉÇ[î§}Fë‡Ø7Â.ìâÚÍB’× £Ùf6”²( ”„h¯ ±=“Òå(]¨`Ÿ$î“Å”œ+„”þ„Þ(5Bc]V¥2)†Œ@kG.w2‰¥nX›"á€íƒNÕò-IbÉ=÷|:S„Ê3bר<”/†³PÝ,ßh1¨&®„sßîV=ÝÓiÀftƒ9› ÙßêOXŽ9OA×1¾ôÀ|­9þ L‚ñ©š_WÐG:;…îœèªp«Ùp‹i𛌶á‚R{t§pø i¸ai™Ç8P`©lÍd`c=¤íšÍ¨ØÕi"[ÊÁÚK ù~à_SàˆÀendstream endobj 199 0 obj << /Type /Page /Contents 200 0 R /Resources 198 0 R /MediaBox [0 0 612 792] /Parent 169 0 R /Annots [ 202 0 R 203 0 R 204 0 R 205 0 R ] >> endobj 202 0 obj << /Type /Annot /Border [0 0 0] /Rect [352.9764 655.1059 522 666.0149] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 203 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 642.5612 185.1442 652.2582] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 204 0 obj << /Type /Annot /Border [0 0 0] /Rect [396.4572 628.8045 522 639.7136] /Subtype /Link /A << /S /GoTo /D (Using With a Debugger) >> >> endobj 205 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 615.6538 238.9942 626.5629] /Subtype /Link /A << /S /GoTo /D (Using With a Debugger) >> >> endobj 201 0 obj << /D [199 0 R /XYZ 90 720 null] >> endobj 198 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 209 0 obj << /Length 2962 /Filter /FlateDecode >> stream xÚíkoÛFò{~…q_Jã"†Ë]¾òÍmÔž{N\ØJ¯E[ø(拤@Rq|¿þæµ|Ht›|<à`ÀÚÝ™7Õ™ê,ñÎ"­ÝÄDÑYV¾òüøJÉh‹1Ê·«Wo¾Ô™òÜÄKÔÙê~BdµùÍùn›îÏ•Óåç å4ç ­µ£ßž/Œ1Î?ês?vžhœ®æÅŸ»©š´äùn,Ä–Ý6çÁU±nž6Ï€qèøúüÕ¯–«þÊïÿSˆ2ÕÄUWiWFñ~÷oyss}s·º¾¾ûöò(æg—6yÛ1^™~.ʃp”îvu–vE]ñ¼-þ“óžüs–ç›|ƒ\ 6ˆÜÐóàªJ»*ðXº@Â=" £ÈÉPZ@äRÛµa(j L ûºáAIÏRÖ(BœÃ¥açƒ},Øbe'9”“ÕÕïž2ˆ|h,YâÏ9”.¼0\gµÅ›´¼§ßÙÙO89´9i‡wJZû‰C<ä]WTGêF;·y.’š<–Ò«’ć#òÕÅÍËÛÕÝÅÕÕõw«ËësâU^膠D²©¨ø\âž^G9ÿž;Lׄ&‘m-]ñ¡u7<ýÌ1 Úžò ‚ìîr—IJÐçÆžŽ¦â¹ìðy5Ë~A\(|ä“í tO¶Ó夲#}HIhmó›Úmi‡¤;V5Ϊ ›é=syÏðg|åúÀÔ¶)Î>‘‚!Ä8íaOÚˆOŠèƒZá*(+ª'Fúº˜Óˆc!ÄÈB ÂB|®ú€ô7‚|¨ì Rß9…‰” CõÕ ù¡Ýôé<³ƒø¦tÏo±GÆ‹´ËwÏç±vܹãaCà™³…¯ÜDE1û}ìcèBwß_\^-ß Ž&~…ÙªóÐÔâV·9ø_‚­Ÿ§î§zß”“ý©ËY‘û"g7r¿8·÷ˆB¹ÀNŸº“Ý%ÎêFÞ&Š14@Ù3F»O3YK+yP÷ p’®°¶E_‡ ?T ý@ÅŸhXH¬Ô Í:1c/x£EÈ®«åeº8Q!þBµ)2æ& €<¨^Úñªhå7Ö"VML> ÉPDSÒmM’ºísË‘³”ƒË=ɲn9HÛÌ®(‹Bß¹&þ}–4H ½”vj±Nöò/jA&#ÂCiWû ±¶2Ÿ3ÄwãÀX+8ÐætIǮт•¡ZÐM²´âAG–ódÂ5Ì7V5îñ²‡]׊¯ôµrýN?ÕP£cà¯r>Ï :XO˜· H£ã1(‚(óAM…@Æï³'ÍÇG3:"ÿ‹‹V7qÌ’ì/R"’ªÉN/9ó¦ëá±²”ü>Úu!–ÞvpÛ–a©dÂ Ž™D,*”^Ý”£Ì#eÚõ¡³žuð•Ç)E.>†u§º¼i­O3ãçF"7ÐÆ'>\¯–³Zá»I|²^¼eï±Â[ñ‘±"¬yµ¤hóÌ“^6ˆŠjBþ:Áfý €{਒´;4¸g^ ˆ6”p’ €#¡ÜƒWÇvB^©frø>Æ…³iH{ÙŽb7T±M#ÊœàŒ¸üÐ…ÃmbfÒ«–VÖÁR$g] ~g¼°¼³JŽtœbèeâüŠcŠ­*"¡³È`Rå6÷À™=„µ+ª/sêÇÚ bûäo—wïß_ü4Ç-È0Tÿȼ9óé(ÇÅæÇ '@qLúÀY=JZç§]Î9°À ›·2`eËSôçøûñæê¸¬ÐaäF.xžëùÿQmׇåQmÑã-ƈ3Æ)AduÛuû·oÞlÈid.øž7Ç71QèX¸LorRåôx37™HÝD‰&ñô",ßÄi¬'/Ðt¢í î^‰Ë䥊–Ä|°›Ú+ºÂ>É|‚Ô'"“ü(8ή^ÞÜ]]¾¿\ ÙQý)—ªÓVà3÷yVÜìÑú|t(ÉŒób{9%Bñ@J„$år*æ|„Ti7$×\-%âšiDÊh«°d\r%˜ÄTÃù‰7ƒë¦SÁÒïÍ{bÚ‹ž§ã4('Wþ© dªâdˆ½û9ù’緜ͮ±X¡ ^*°±B¢}(ÇÏ ¸¹aâ=cؘF·#Î(ä)A¼ômž q̸’+ÿ¶<—»Ï²C8?c’—6„-ÿ£×Ì'ö‰Æ;1·D£UÄîæÌÍâýw§‘»y30ž%:¶ƒÐ;¶ˆ¶w×î¾…jៃ%ì!fwÖŠvR1ÇŠr ŽæQ†õ¡Ú¤_[“Øê´áªQCÖF³šï{_"›jAoòqêar4X8Î<„åÝ8ê-÷T6¡;ÙhÃøø2rºOÍàßãËÉXME%Ɇ ãë!`úaÂ9}_3 „›*T€{\/p-ïA•܉¾Æ³µD!Yúœ–û]N+¾SÜ3t¨¾Ãä4Ocœ´êÏ•3OÄ7£bGÜþ2÷ô‰«CJü^squT—wÔš¶©7~ì™c“Èõ´g„æ/W³wäªXÙƒç-\Ç¢N+é›åÅ»_﾿Y. éšÂf¹ÃÅsñû&ÿTЋ¶»gá¢ÍŠÅ¸¾.dÀ« ¦‚%7°*Ró/A¯:^]ñ´iïJl=ù=}mhx64 W(Mþ"¿]ß*%/”)e5©…´i¿,C £c¿ƒþ†ÒÔÝ\®V˃ﱎF÷}/r? V×9Þ­RÚ§¦è:|©¿¹”27/6¥Ð¥X4ë–CHêu /¸XïÒêqîÐPAejlUW7ó}y7öÛûζyöø'ÁÛ{ÊÄ]Íî£j¥¬o¤æÏ+Iã¤ó8pWM¸£ñ¨cÉí#G£ÌTTOu§TxÒ´{¢ô—z~*šdí8š ÛÉð·e.· ÚG…#³]VÚ`cÔ#ZضWÃ>ûo¼kM={Ô¯þðÏŒá}ÞÜSN1×÷dÚæö~8žÖ¦I>0³ÕY)íBñ}ºJ¾6æÏ•Ê<3~±CÑ–8Tϼå±D©šgmîàDTSÛFÍ« ñð¯;düb>Ô#}§°ë]TÇ+L t5rŽd0_Á#†ï^†ŠÒ–Ñz'i @iã¢t½qGQáñÒöM u\)ÌŒ dÔ·~Éñ‚÷aÊv:FÎh”Ì%Ó«âG¦h†|yïS†ø`ó¶i*ðÅ~.:©@.Þ½¿ü¥øí¨_§’+¥›²°_vº"í¡ÉmÙÝÚ^ýþÔ˜Ûœ¶²+äÑYÝ˦ÏÏ\*2*ýòWd@øÖû…oZ¦d†E‰KCͲ¢oæÇ>mšphÆí Xíe ã£t îUtþ£—|»£T,Ь¦Ñ4N›ðÛgßéÂ¥”a çU”:W/iùf%| Fg"5tÞ?r£ïà¼dc-ûOs®fn4? jö^>Ržù§zöîfy{{¤i”ŠWܹÀ·Ü4y+±|WØOòt=)ÆÿÕí_Ý¢¯Q7ìèüÙëÖendstream endobj 208 0 obj << /Type /Page /Contents 209 0 R /Resources 207 0 R /MediaBox [0 0 612 792] /Parent 213 0 R /Annots [ 211 0 R 212 0 R ] >> endobj 211 0 obj << /Type /Annot /Border [0 0 0] /Rect [367.7307 497.6007 476.5477 507.6007] /Subtype /Link /A << /S /URI /URI (http://dmalloc.com/) >> >> endobj 212 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.4185 435.9278 493.0248 446.8369] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 210 0 obj << /D [208 0 R /XYZ 90 720 null] >> endobj 207 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 216 0 obj << /Length 2038 /Filter /FlateDecode >> stream xÚÛŽÛÆõÝ_±HL!ÍÞ[ôaãu‘¸X«èC¸³%±¦H¤¬ Eÿ½ç6#’KÇYËá™3ç~ª»~ê®ï²( Š8Ëî6ÇW¡€?½R²òãü°~õ毉ºSaP„…º[ï&DÖÛ_<¯üHÁŸ÷p4uÝ®|{€E‘·^å‘wÚn¥¼ÊÔ«ßÖ{õníØ%ZM DYHÏ$Jó8PQœDYÄÜ “ðÝÓÓû§߯?¾}ÿôô¿¯ªp?öªf(»Ä"ìcyl»+¯ûºxµi»î|ª¶Aáç¶H² CPEJB6È}Gs äW` dÚ—œéÁëùÿˆªE¥çp(­Fƒ=#¦é®¯{š-¼«¦ê‡Î ˆñ9È@’D|3œñY"DΔ¬ŸÉE%m ã­E÷QM0ýD£¡Üñr¬ü,‹½õ¡Zqƒ>g”u‹oŽ2o†uõß¶G†ž%óZgF:¡¼ís]¿@¦-´ŠxÃŒ½ßXïî×P%xn/r°Š=2D¥ôi‡ƒÕ·¹`ài$Øìí â,¢8Õèmß¹[gA拤“­ü$¼ÛU¤¼ ÍoÀ–׸®z*Ž6òRÓ.øÛ'‡/…ªPJ ןv ¦Ê¼+Z¢=óË Ñ¢õ–!uõIB$V`Ä–¡[T’âÅ<#²Ý>ÈâEô!Ð…Fž©êRXl顤Ç'òמ7v¥8,íq««0ö 1Œv2åÂæ\Óª¾.¹L* ²C±ÅMì<KMKHÝH–^»³Î¦àr }Ï`gJÂ1rhÛJIxVG„Þì‹mXáz‡¢Ð°}©šýŸÄ©“Ê•ÅAª2¬IIAªžA}ƒæMt‚EŠ[ª®›»Úìû?/Ù(‚%ð›ï˜8£áU»Ûñ( ñòù¼ç%Ñ—íF„èÍçR@üØ´§«¥%ÏZp?›ú,Èß½Y’g¢#þeª"IƒÕ;ÄbítÕi…*š(Õ—âà±,"$ñ ©ÄïOÀ¯Ø±´V±d'2ÜH.‰ éÝPÌCù6ÒûfKwªfÿGlé,61®³Þ¼˜øI¤Yd/%ZÿtEC?ÎG /F:JÐXUŒ‰\Q qǶ¸‹U‹æôrWƒs.ã8Më» §§°°j¶¼pøX¥Îû½­H«/‰yÎÄNôTÞ£Á‚tå— î˜1(…hNÊ{Ç3£¾,‘ŽD XlãjéxZ0‰»¯QÍóÀkîh¼˜R@”Úl¸eÑnYÃNX¯¤Whéó×~(Ép¯o$Ž ¡aëê“ø(—ÈŒB­½®=Ïúh½8 G`Ærb©ZgÅÍV÷ã‹‚È{óÒrNa–Íôªph•+–8«‰‚ôìJ‰°“u6rbæâÝ0¢Êî²áþòšZ-„Ѿx§j65ús+þµ4`*•Â:.¬­x:‹—Y$±C}Í\.4îÖÂÃÕ# ká-b_Œ¶)ˆVBíáçûÇÇ÷o?>üôáþ‡ÇwKìó–¹=ðmnm“ ¹‹åAª9÷|³ƒÈVA¨¾œ'³f Ž„M×J#¯U±×~w‘Å ƒn> endobj 218 0 obj << /Type /Annot /Border [0 0 0] /Rect [317.7519 295.1225 509.6612 306.0316] /Subtype /Link /A << /S /GoTo /D (Allocation Macros) >> >> endobj 217 0 obj << /D [215 0 R /XYZ 90 720 null] >> endobj 162 0 obj << /D [215 0 R /XYZ 90 631.0931 null] >> endobj 214 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F72 9 0 R /F60 81 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 221 0 obj << /Length 3420 /Filter /FlateDecode >> stream xÚ¥ZmÛ6þž_‘Ô‹ÆŠø&JîC»›´¹Ë¥ºEqh‹T¶d[ˆ,’|›ý÷7/¤^¼ÜÝæEjŠ¢ÈáÌð™g†+^ÆðŸx™Å/­RQ¦­}¹=¾ˆ]÷§µÖ0b=òÝí‹×ox)â(‹3ñòv·˜ä¶ømu}ÈOWb5”Wk±ê®ÖJ©•úæj­µ^ýÐ^Étu‡z5´üò'ݵû.?òó~Xáî%7ÞW›úó&MVÒ\ýqûonG‘”Ïm ‡v%ç»:ŽT–¥/“TGBiC{{ýú ¾6$:þîËÅ1¯ëvËU³k»c>TmƒÒÁ¢k¡"abVÐßxÔÖ^ßÜüëÛ÷ï¼æÇc^5ÑÖ'“HÅB/¿«†C{þÿžVzý6‰ç›_ki£øÜDVÇ}þ{,,^:€Qb ,†ƒÞíÀÒ±ZÝ£¡Û3>ÈÕ¶=¢MÑ-ªº,xDÞ\É ÆÑC»ã‘Ÿzü &ÿØb³äÁGÐ> +ðE]öØ©Q+ðxp.l)µŠT’)'¢S÷Ç·¿|¸þxýÛëwÛH§ÚT”°}Ý\‘bU°€à¡®ƒ¾V&ŽR£’¥âGe ñáÜ|pVÜŸîü„ ³(‹¿û£Ðö%| ìdßÀ³³8:´ŽÁ£³ç~'3tlÀ Ñè-hn1Ò$Ù$;>r|úþf06^xPÉNù†qÚÁÑt{’ [þ%ä×Ny!ƒÅ"²J$»y÷ó·ß½s2Wf£T§Â}»Å­â2mÇ¿Méå&X® 5@žUCã\€k’e–EÆfviÅ?C¢ª(Vñè$|£CHB#"£uæ†~vÈ$J¿‚CЇ;ñ0`çt°÷šœÃ°¢ûWè‡ š¹áד«ÁÃ]…ûªù¡i×ð.†';ˆá7à{™\H!G’E`• Õ8%´É;K©å hJZݳeïDO©zôÅ ·Eù'ÐOÕê1WUBÌ’¡(kÓ•}[Oö/øƒ®Ü•]ÙøÐðú Ø[Xi5šñ£3ùGû§@xê?o Í J“é圛m{ºN©"“ ëÆÏAˆ¶Å6:–kI) ¹2Ko¦¯ªfïc®´«¼wöizŽòà)ˆ#‘Æ @Í<`¸ý`¬-V·äîÄâ T¡ïz›äºð8z)ÍI&ú´@,EÃAƒç'™óBGÐ~øL’§=  -íÆœPN¢ÇNz<”MÏü:wJDŠdªåRËHà þv%æx—ê+;I#+Ïò¾b^'°ª²bÆ7‹/3CjÇ_™i™%«=kIÙb~€£Â@£7Åæiê(±Â{Fî–¿æEiÉ—óñ–<†6Š{Ôr~¬ÜˆÀ–ÇýŸ;fYÕLÝ"Ð^JˆÂdÏ /½ì]0 Av ¼vi寮û=61ü¡™àªÎ|˜Áä^[²d¤½u9”OMª …žëÚÚU‹\ÿÄÖí1ÚK›àQ ,˜Èká=ûà,øÔ.¼—ìºòÉ=(‰ò"bhH~žØaÉòƒzyw„¨nS¬!×ß¹‘çþŒ”!ˆ ¥(U-é‘‹³ ú)²ú0œ®vˆ¤£ ”Ô1Kw›‘ã§DÛrpÜŽó>Ì[UãÇg†¿sL¦ïº?•ÁÓ/+Ü·¯x\±äfå¤B[n2:õ÷¼%¦žâBÇ®í¸Qx´°¸M¥2ŠNn’SÞ;z)![OÒKFNìrŠ'4̓¯jBñµ§y I!hõÜvñÄ|(ë{ŒäàƘխg5n† ’J%#aGýüÅÈ%f‹uøžŸOT!öT3ÁwL­˜mœ£¤âÊ@äøßò–m´Ý>bý,Óg’2ÍCE® †;pfÈŠŽËv¨&®ÍÇ€FteQMIÆvT8Œ$`n5tÍ€H@e"ýù¦ ó£¥°[òNèÝŠ×U&Þi5Îè„àÐZËgPÖ$vÏOư˜.Áz± ÐtŸñýê¦Úr™ðæÒ„cÄ‚AU‚u§üÄ1rpæy¸É ÓL-ëA~¼}ܺKìµð ˆ ê-¹,4ò3“㎠:bËÐ1p;çWáøgÿR?Bmfü;ä[tÆOóìçï[þÝ•}Åjㇲl ÿ^ö)ÿÈR¹‚ÎvÊ¿ÜÄœY9ìݦ‘Ó”ˆLeÞ{j,#“H±4¹ÃFõ‡ D;}Ž@Æ“ ºt¾<Ä$Õ'hË%ïºíßÕ]óÓÉ1|8­@cÎ×T¥5¡|-{,_»Á‡#Õµî%á?¼ùu‘§å|†ix¹9ïñw_v¡]Ç>!S$Àž¤†ˆèŽ µñÝ 7K[ÞKÁè‰/ЪøËùZÛsŠæ³_œ¡gJÐЬ&yØ»s>ßž{ŸÓáïØ.Ø} DQafbÉðî")Á‰×è·ý ®¢7NRÊ6uyœÊ1ñE¦ò¥ôe–'¬¼ãšô5Óz°m¦õ‚ÔÿS)*­@Ї¹RíB,¤~‹&<ƒj6µ)CÇêvg/Æà4»äOùœÀèáŒB5ÜK¡:s~d²4pBcWcˆ¤üsÏ;ß™œ«ö¼Éµz¹%Î\wÜÿìP"EcŸK'  =Æ¡±š]×®„Õîwc!·nïÂ%tY3¦|Ï€›ä[WóÕóºêüj8Œµ¢*’«`ó‚-2ïúØvT:5 ³Z¶âb(ýNU®M•ZšÅ’“Ϋ "ÈBaG&,\=ÚS•„$@©¨ò?Œ…tÓŽµ™—<©w\ì8VJàäÐȼç_¢–e]c%4…m—}¢Ô )¬°Ù”lWͰ>–}O2‡¸›‰€4L±›ÃJÃÂlÅÅöÀm0œCƒ€û€ïiÈÛã‹êÈÒNìGÏ‹††H¦Úd¾MÜðç]1ó¼ûy,_^£)ˆ³V1’ÀǤ)Þ“Ájôzv—6Ž[Ï® NøØe¡æŸßn.R½úi,…üñÊÁè‚ß©7XK–¤f±…Àuà8î¹-<œpdLã(–Ú,`óÃxßiÓùÁÐÏn”þT.Ñ ZI‰Þ~?êÇ"Þšø¦ÄQÙÌ—ôÜ ÄŒt’y2T~Þ^s–pŠà€öÁÛDÉȱ¾ÿð ¯v±{/óž¨&×h•4›%`)x¼¬Ävî³á ²{A{6cf‚Öš1¢°C.„j…(8ÇÞ&Ö\ñDz”z*óOÁ)¯HiFúƒ õüËôWfS5BØó{. OcMÈßù¾à §=t£–P«_ñ®„ñ4‘V‰ Þ!ú°íîÌ]äÆPõÓ "• ^¹~_)гû _°Ú“¿q™Hì˜_T®~˜»›KzÏ5°I³LŒÝ‚N– ®^øKÆ·p‰E.9? V(ĉ©P~åè#¼ýþæ»WüúwP˜J¸ÐÓñÊíñ8Æ÷&/ŠñîC¦Î¾LĨ¼MFžø;,Ò: é4€bÈÅ%à¾ØüµdZ¦{e:‹S(’!¿4™ß¶ÍÐUÁµuŒy™ÖÖ"eݢ☓j@w™Pln|.+cò…7.Ÿ5TMõʤÂÚ¥8DKn£ZðwÆ àéÐK–ÈËÊž¼(ùg¤œTï‡qÈHÇ¿Yô—N¾È_óWkcÓÖkÌÉzOÿ âŽ#endstream endobj 220 0 obj << /Type /Page /Contents 221 0 R /Resources 219 0 R /MediaBox [0 0 612 792] /Parent 213 0 R /Annots [ 227 0 R ] >> endobj 227 0 obj << /Type /Annot /Border [0 0 0] /Rect [309.7259 231.4945 494.9685 242.4036] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 222 0 obj << /D [220 0 R /XYZ 90 720 null] >> endobj 223 0 obj << /D [220 0 R /XYZ 90 518.4268 null] >> endobj 163 0 obj << /D [220 0 R /XYZ 90 335.5127 null] >> endobj 219 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F60 81 0 R /F72 9 0 R /F93 226 0 R /F54 56 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 230 0 obj << /Length 3924 /Filter /FlateDecode >> stream xÚ•ZY“ÛÆ~ß_±o V™0æÀåª<(–ØUNœH/)Y•` D- lP«Í¯O_38J¶]ZfÓ==}|ÝuÁÿê>îScÂܦéýî|I÷Ó’Öfl§SþüþîÛcu¯¢0ruÿ~?[ä}ù!ÐÉfkü¼=§S»Ùê,ØAŸ1ÁûMf‚ËÐvÔÅióñýÏw?¼÷äb­¿ÆN¹æ(Õ÷Ê„°$%™ •±1qdÂÍV9ýU›mœ˜àmÅ¡iñ·Gv°Ñ€Ï4þ‚USu4ëÄ¿v4ùñTù%ê}¡‡#?üó¶z¼°ÿPáß7º”HV¥abLNLþ´‡Wã4xÝ€¸ÚËߢŽgl¶‡®8ós?´Ï=7‹‡c%ô”‚²*T±ÊR(é8vÿ®º®í~‹âþ©5β<Ì"­äµŽ˜êþVH/ÃÝR†IÐ6sÒÊ. þi6:.çNƒGЃ4¨ºé¼$xîÚGXË‹¸¹ßj¼Ääc€ÿˆÕj×^N%¼”(Z*#^ Ð3w5õN:6QðS³k»Î±ºø…¢;à†Î|Ä(í¡ç‘vÑn™,í§|Ú8ŠÆíDÞ§yÈBÑÓ*yuh…ÿÌM‰AÇwÀgäÞ|bÞIÑ|ïûÅ–ê ©ÅP{fRÐP™KÇ$axå‡^‡Šh|}`ªÔ+èg·ðÛU3>¡§:-ÎÞâ"þðAòD‚…ßÿ$OQzO¯H´aÈÆ÷þXuÂ~q"¾„:ž1¼U®ÉÀK]ç92¥ó ´f·lØýR£âîð(“ûמ9:?ô<:î¤I#.à8¬žZàƒ“4.ƒ´. /À&!í=ÿž™FÛ½n2K;b^·=Ëíh8¿´çEëÞ€"~fÛOhû5j¬;wÐÁ2÷ÅAÍ»Áæ¥÷G OŽ6¶¼¢ØüùÄúp†­Û#¥f祴âet^,Ï—9Ÿaé§¢ÓPEÊ9•¶[uXàÖUËœþ±{Z]IC3Ëd :O½Šmðß6†ž¿¶èv^䕘pGó“ xƒµøcT˜èÜÌ•îÜÒ½Nõ­qzåg’(ù`cƒžN[;Ñh ^J×d¦Õs¯¨´w¤0V}®èuÒ/(y€öá^ij(.‡#Ù7ª\H;QB#Ä”­ŠC›¥–öAqX²pö’~u­°•Þ4¨Žmwf«  3Ù^ä§EøÊÔüÈÖcm‚ß"eQ;{yá¹ý÷|ª ·VÅÃå=×’Ƭ-ŸÐ¸±Éy_µ@*²¡"€©½Å¨ðß»£û`ÅÏwQh“<½AŒjcóûó uª3÷|º{w÷xø·Ó%WðŠ²Ðš$I#£t64Xtb_Á(ä‡û`øõDÎjá­S±²+ÀÀoê¹³¦;ºÜ†àŠEUï(l@sÇR*«¥šÿ"u¸à`*VßðÌþÒ?á­Ù°þÙÌùY°tn â£ã3’­ÏΨhH‡cçAÙ¤³©Ì¨è\™9PaÅߊ }*N—jÛUÃ¥kªr»ïÚót«V]D‡Iœ¥² IÖLThËðûCs@X÷Û¨o@V‹¦?‰%`T3ñ£&W. ªm°eî¶;‚º öpË~”¬ƒ"@ 6š@ä(ìx”Kß3€Å¸ŽóŠN^(«¾>4ˆBh©–{)”µ 4Å ³{N»ívÇŒ8OîÏBƒÃ+sX­Åh¯ ð÷•­@U9×M݇^ÐiÝe7P4«¦†31€šØ»ÑCÓŠñ<\z/"B'躺j.8jPô‰_´s·H˜;×ã‘æÆmž@)mž§ŒþæàÚ—JÞmÝÒq_™#ü !=¬díU8‚tæ8;W#‘ÞCÕn'Œ“~ÊœÑa.PôÔe£2¸bû*YfKø¤D×a9ªfëQæ×ûy0ŒG×Ãe-';#Å`ÍCxé…¸l²ªÃ<ô0Q ¡tÎáU L‚_ÃPìLš0ÿ-À ÊÖüÆt¬í´+ ÖÀ‘¬Ág9ßÎmââRÅQÌFÒ!ï*vŠM˜Æ‘?µ;V»§-³§–¨}«siŒE&Ø;`î4õzÌŒüz^Œ–] ø£Pj™q‘j;ú# ç¿ò9˜ppv– 3Ü®;,ÈÍž —CÍ .FÚ(Þ¹½VK`h¬ mž˜{«Ð*hŠ3£áIÉÏÛN'®À½ëqÇïª à€#7>¼ã&îep.æÜüC¬”" «®JeµrD°SöÖêenÞ×öq½ gWä ¬v«Lõ]U]ãî<„`”ß[“…:‰“âõó¶Ó‰«hz¹ Rþž«>ÎQD±üóÁWS®:ÚàWŸ"ü†'=³daÌÄË-è܆‰I’ÙV$ëç}m × âB‡˜sÈžu†‹}èq<‰xìg•wy8ú‚αpùö 2ò|‘,5õü:Œ­åÝÂÇʨE¡ðSÕÕûW¬Þ,BJjëÓzªRÅE3ñ0ÀÕâöm7ö±£F/»ZŠ!0Õ€˜2=WÀ—c½CJˆÚ­xߌ%º’ÄLpž52…4£C›jÒ®xbÍ,¢Êë#J“5¦ëM+™ø¼/úQ=­«Ãq{‡gæ±máÉãZW…­‡~Í·Þ‚ÐR– lå*W…:uvͱ«@Þ&OB›&ù ;vÓ¶Óyk6°\nî$7ÆbÀ?{Ÿ–>f¶ìçö«Ò+Ÿ% Ìql”‡ÎV ZßlJÇOcƒ“v{D‘4˧­°Ö©=lW*#,‰²vGºk§ØÕW¦ ÃÚ5>È;ΩÉ#­uÈÏÖA¹ËvßU#£É¢RKÉ9J“ViÛØ@cUÁ-;Ÿ¾ÐDÈù¤¹¼Ð Î¾nv/Tn˜›1ÛÏ‚þ,NsR-"£.>/Q֣ŰYK9Îy$J`16Ç­±„yÙPtc>å\š»†B_t殃äòÍlªXé)íênw9÷.I*HÀe¸šeašSe)óuàA–ßqû!úl!2eüˆZ£4·ñ¾ƒ„ßB ¡wºâOÑgµÏööaM˜_ ¤ÿ¡KóÔ´/Í¥bgT¢¯Q½ûî¾SQš2%Ø-¶‹qÂoœ+R{j¯²!4žÛº(­§Î)#‚[Öɦ')=#Õ -m´–N )fq¼P‘7R§ÆÈêZ4©àÃK}:q«¯*®dòL6p~ÃîƹZöP·!oRòØÄ“Lžçµ¹˜KRxf8…‹ÞÐIÒyQôC}~b×p³‚ãÝE̵v.´Ç€Nê¦â“€ñÿ¬YXP^eÄ&F´&ha\s‡^óx\zÊÆ­û?aFRrœé³R| qÊÀÞ㗪ēi…ws#°g>ÞS£MRuð–â@¢–ê$ûú~ØþOÊh&øn“ù)°r(wššÍÞ_6³‚hÊóüÂ<ÜœòñPM¼ÿ]*›ƒºûÚøèÀÖ¶§x…¡&[Œ¸ìˆ¤¨vŽg´-Ê’äÝû¥'x— |ãÈ _×bsÊ-G©Yá’¡z”†J›…Ú¶”¦êÀ³”IZ»½™¶«<Â4ƒCO`·7ÓJ7m;™·–U.—[£yè2JJÐÇ ˆÿtâäYof2e?°„«&ÐÙrgÖ ¹îl­úi_ÙÙÕr“\ï8ódôœr7HaÐxOÞsÇË‘/ (Yë¡‚’b|âîŸÙí‚Õ”²˜·NMüÇtPúÑ^HÕ‹«G\¹?:UÄ«ÆaŒg殞]øù=¾ Ô l¸(¥Æa²¤³Ô[wåJ™­Ñ#ÒîrŒ.†ÝÇ1~æ$9ÄzxAjî ]Œø€5Á«w¸frNö–3ŒÃ8Qnƒ\°ZI©å¹™Hà tätœQ¨ûÓYg¬ÆÚIÞkÓ¹ìØ ÁŽg×_¿0 zøXøKF3_‚¿l!næŸYÃî ׬E;9\FDFvQ¥šVƒ¨ €ÄâÑóˆÓ8Žc ÍÇ_O…é.ra›#—¯¢'Ë3,%ôüâ•fǘúœ}®+tÌS%38bÑñ߯ÁÊšµ}™ ‰3ú ãt)'Ùö¯jUž‡iœ&óºPx\ =*Œ­u¦øð…ÊBª 3ŽÈ›1Îõ­Ò‚›·N\«-\-¸âÍ•øò7×ß»x5‡ñ_Š]×®•®Ê„6eƒà<ÛÆšãvó¾¶ë§®;ÎÂ8.á˲T.ª£]¿R¡‹A5æç8ÉáÝÓØU»…ÚÁ±›×…~N²ÅFà™?JSùäzNeru ½tSÀ ôtõÒßç4Žÿ>53ìñ<3Vc¸^pœ]½ø¬Ö[ÙÂX-t7è_žÉ-×–x/©ó©úváßgí*äÓ'1¡Û”lwʬ¬€aÀn_Rÿ}ï+Ý R§Ólº†@ÆþZ ŒØqåó°›R²i»´S“âw±ŠA³8̌ǠýЕ—ç/}Aj!‹t6~ìÅ\5‹à ¼Úe‹I²¿¾e¦ü‡|ЖŒI‚(õÔ½»i”O0µ¥™Z–‰ Àê<¥à¬s_tYÙk¢nÛd¶Õµ-š4ŒsïÉ"©á(©¾"mJpp-:ᤒ]T%Ónaÿ±:=sëú„‘¨ÿîÚÝeäïwÞÿ¨ò,^endstream endobj 229 0 obj << /Type /Page /Contents 230 0 R /Resources 228 0 R /MediaBox [0 0 612 792] /Parent 213 0 R /Annots [ 233 0 R 234 0 R 235 0 R 236 0 R 237 0 R ] >> endobj 233 0 obj << /Type /Annot /Border [0 0 0] /Rect [343.4963 448.6891 518.9697 459.5981] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 234 0 obj << /Type /Annot /Border [0 0 0] /Rect [109.3939 435.5384 294.6366 446.4474] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 235 0 obj << /Type /Annot /Border [0 0 0] /Rect [230.182 393.7496 386.5155 404.6587] /Subtype /Link /A << /S /GoTo /D (Extensions) >> >> endobj 236 0 obj << /Type /Annot /Border [0 0 0] /Rect [190.9698 204.1788 436.9094 215.0878] /Subtype /Link /A << /S /GoTo /D (Translate Return Addresses) >> >> endobj 237 0 obj << /Type /Annot /Border [0 0 0] /Rect [271.6056 133.752 463.5149 144.661] /Subtype /Link /A << /S /GoTo /D (Allocation Macros) >> >> endobj 231 0 obj << /D [229 0 R /XYZ 90 720 null] >> endobj 232 0 obj << /D [229 0 R /XYZ 90 720 null] >> endobj 123 0 obj << /D [229 0 R /XYZ 90 386.0875 null] >> endobj 228 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F52 24 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 240 0 obj << /Length 3614 /Filter /FlateDecode >> stream xÚkÛÆñ{~Å5þp<Àb¹¾ Û¨‹Ô’ ‚" RžDIÄI¤BR>Íï¼v¹Ôñb'8ผîÎÎÎ{¤®øSWer•—6ϯÖÇ/ß¡d´ŒUˆòÛ/þú:UW*‰Ë¤TW·ÛÙ"·›£¯öÕéFEc}³RQ³2ÆDæÅÍÊZý³»ÑEô€@O~Ø}·ë«#¿?à‡ .±gÀ¸¯yðus×¼ê?J‘Y¤ó›ŸoÿõÅ«[Orªõ§…(Ÿqª¬°±26¥Su[ ¡H&!9…ŠŽtÄc‡äàܧ€À{üÏ}Só ïÎ#à4mí&ª‘Gëêp¨7x D‡„hĹNs éÆ~s> âŒbcc“#xñÍ*-ÒèæcwÆS]ñŽLüïc_µHÕ@§Ê:yöÕZN+'‡¯V:Mã¤(¯VÊÄ*Møâñ ®´ƒT¤V°|Ý?ÇwëY·]37àPEø]ÇФ©Â/‘¯Im»žžù€udæäëv¤‡}ç¾Èšîoêàæézgxx!=JÒ„)õ4޹>ݬ€Þºº\Ec*âBÁºÂÚŒ–ïkº˜ÂCe´÷–¹Û—'ÂScÃ20ðdÅP”ø"êðÒ y$my$¡Ü;BªëV>%R;®«Ñ3–#‡ç¶w'¨7À„L™èÍÈSpÒ6SG”Šƒ—ô2°Ï0DyA#ç‚m€æ‹ö·ˆó²LçŠÚv@SªS^ý¯“6M’â·Á\3 ‡Ò<¾û8ÖYùÅš>ë«¿%Ô¶ØÚë%É@¢‹4½ àv_/R«â4³DÀml•r*ÑÈ?up_:µQµÙ0£ÁÞã½ãcQʳ")Yå·áÙÒV*U¡2'â¼Å¯gŠ %a¨ù¸•»KÚHékºõ-Š*€ w¬«v¾B¿,ÁN HÊLÏÅ`¾°XT±q¿ž0#1EŒkΘâmZ~[ä²&N’D˹Y“‚‹ÏõÄ\,PB4·N ɘÑg†÷âª;rA¤ÆÎwSFõ‡êxò‘És’ñv.0`ñ Ú&À6U ™"íKÇĤL¬?±ß‚&•Y™ÏM‘÷‹ µØ/€èeBlã:¼ºù<~š9!½eX°Ã¢ ¬],!Ád»6Ïc“ìBçæŒMrÛ"ÑËže4x¼ O¯9Tƒw.º†íì_{͘?‡&¶_ò¼á<ÍüOŸD_Ó#ãЄ·¢øˆcpÕ‹R`b)ûéx4‹¬t–¥ v¢(¤iw ¢Ð žh(éô’J¤‚èu?ðÅ2è2‹“Ü^Ä »zä`ó‘TlÙA— +ö³…: „ –Ä_a†ÒÈîùLIÐË"Eᯠæ×ÉA¦ñÎtƒÅ•…œb'Úmòò¤ì³öB¿4Û‡8Z–*¤QØ3Í>‹½¹ŠÎ#ddE—<°55é§¥¤ˆA˜œ4U¨8hš$– ™‡Oë…L0¬L!ÈN"Œv i!dbpÁDËö ¢Ð4µéŸØ$Î_à ÒÅ€£gÅÏÀ(]\„¹.`³1¿G4M>/{B7ø=3xAANaJgZ8èäìòDG‹ Ûð«Ï K—-Á q¡^`ð|fWª ö¤SÕSÐ@÷r¦x,¼=’´,Þp]^†é…–o’‚ýŒ«M@Ž!8cþ3¡ÉT\ä¶paù ]3?V•p;Ï@œ‹ nË¥¾Xö ¿AÁ¦ðuwìNó\—t„@ê¡rRC§W&°Ø0¹èáâ³eá…L%Í ý'íX…Ör.¿.QáÎc­L6礷Hº(æ õdp4êC7õ Ènç+EœÄ¼¿»#Žå-)Gàq\vRylm–Ïä—ºï»~‰'9DÁ©Éƒ›×eôí¹u§«\©B8ÊÉZñGàÂ`¹äÂ|>ìIOÓ ä‚ñ]?UŠ‚C•¤ˆ0OªO8:[¾0ãL ïžé…+-¿Ö¡SòV6Ýî¾.ßlA0JÇÏÛ.ðØH¾k2´R÷¤§KV‰Öï†eYºŒÀÕga–” #yéÒDJ5×4Íf¶ï–d+;FB2Hœ–RNEiâÔR ¯t QHùDz«Òj—Õoëj<ßpù‹Cñ¤ î2ÑÁ]ÂKuð' EæÜòØ}ãiŸ™˜d^Beîhë¤Ô‹¾gé¬e¬´/G´õûº_õõy¨—N™eq™+‹÷”} ©™…guw˜Ä—Ð4Lݤl•¥—ßH¢ŸáÇÙeû5ϳ$ÃàÐ`cœIEž¾BÉPÏP¦Ÿ†ìd޾ò‘¹T@H tI˜OZ¾=Fø8p• ±yöQ¬¿Êm}O…Õ_Ï54J3¤™Þ¡Âò§Ì§ôuY‡,Ì™/~0pq÷°™è¢t¿š'³ ãh†–Ê!ëêìr\ ÍT½“„H§Êââ / RýŸI'j³z©6f ENIÀ޳KmŽY!¹âÁ•bp´u¡¥„1~SÒHR¤— ѹk;f:jÇJÂÆ<^ß”Äo]¯¾¹1°%„÷_Q€Tô@ÿÑ7£]láßRD";òqI9ͯ¡íõMa¹Ø¥È-UeÅF®€Äxn'Ïênd%µ·âZXgÊï+’pùð_¦h¤¤ñ5rÑäð¿”ϸ+@dHòQFßÕõe—Å™À>˜+ø⎌Ú(pnšZ-o".ô[/H6¶^OѱåÁ ôÿüܹa·a(ܧj'’©’Ë£(aé5¿2I[=Ñ4òh«oá –ãˆB*P±UT +y⤬R¡ã]KÔo¤(šø¾ç7øIV|úU¨0z6ÉäZ¬4Xjo 0v¼¸.0ÔµLíe°jæIlv9Ûz_¯ïWLâ’sÐèãÍnòÞbð±Ä›gK–&:Î’ì ‚¬¸Tàu—Ì¡­B¼…ky´œˆ×JŠSJ–™Y~±‡idIôLýøRBX~å»»÷­šÖÙÁŸŸ3‚¼,²êò„Úfqnt …A¦õ’çñV!âÂ/è¢ÙTO­׳Á`¶Ú L]h°ÓyÞ×µ®¿”» P84árø›c_ñJwÇb­›g¨Á à°«Rw Ûœ+»ØÞZ_3a8ö¬Þ<Æcï9ÎÃæÁ­! 'êjZkœ/BèQZ·|™„wîë`ûjôë|äuÏÚk‚ƒP¸š¾PSMÔòjãTuXSìï„Íoßݾz±5—1d{.ӛʘÉ©wθ¡/H.XªbŠ¿ ºzÖ± ‡RCA]W®ôI’q½àŒpÀÖY:›TéY4þfËqí,â%¾ÎjÖ yâîìâ{jDb8Ì24«©çêm!NÎÃùn)¤~rOÙ*nuèvR9$¨ðû©¾ sÕ]€èÂÒF¸g|º»d4P`¸¦³¡Ê¨30>/¯ƒ„ü³TØ—’¶Ô¶j0O£ñ÷o_¾ú–‡§f}_b· r¬vÍzÕžwð „L{Óî^,Œ'HÁF‡y|P›$)®u·\î=ÆëVç×KK½<OŒŽQQ×w'·6ßø]7ŽnQꥹ®45þÓ©Á‡I’౫ʄkºÖ°M2oNÖQàO´ËÝãI­ÇÃ@ò$E?Ù8»ð+³Ž›‚7“EɧT&q?y¨œßK¸é¿ÕIòÀ|ÈØWn&¨_¿"éâÁ·y׺“I¬H|#€’MºˆÔ3RÅkϲü‚®=n÷™¨ov{ñ»øêMž oC~Šåmv«­¥—ö&hÙÎ! Øx¬ŸÏ~Ãeg{‚Wgj6šj®×j–%t*ÎÓÜeP —ÄQCšÅôó N,ØN­óyшª}¥¾t¨ºTT<ï19Ä—PÇ ¾ó¿ôÑ|?ºœÂs5ñ41»çž”uœ$ç°%Çñ Í©a?#éŒþ A|ƒ$!÷i8Æ!o˜LÌßsSÒjÊÐ;Òi)ó±àëSYcæJt×ãÜU`fÛõÇÊexÙüGRT}§˜?].#}Mø’×M¬Ö@žX'¾–A;J¡ ÷‚²<õC“P ßߤ „‡óäÏ]xùç dOÚº„ÝÁf³yZfËyûa_÷² …¢0U?m?î/ÛHÝÇ{Õ!P·]3±ËKþ×§2¿endstream endobj 239 0 obj << /Type /Page /Contents 240 0 R /Resources 238 0 R /MediaBox [0 0 612 792] /Parent 213 0 R /Annots [ 242 0 R 243 0 R 244 0 R 245 0 R ] >> endobj 242 0 obj << /Type /Annot /Border [0 0 0] /Rect [417.2333 316.8494 522 327.7585] /Subtype /Link /A << /S /GoTo /D (Features) >> >> endobj 243 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 304.3048 126.3637 313.4563] /Subtype /Link /A << /S /GoTo /D (Features) >> >> endobj 244 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.606 287.7917 522 297.4887] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 245 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 274.035 246.7325 284.944] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 241 0 obj << /D [239 0 R /XYZ 90 720 null] >> endobj 122 0 obj << /D [239 0 R /XYZ 90 350.0333 null] >> endobj 238 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F58 52 0 R /F72 9 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 248 0 obj << /Length 3625 /Filter /FlateDecode >> stream xÚkoã¸ñûþŠ ý°r»ÖQ¤žE[à^R°‹Ûhqw¸Ê’l«‘-WM|¿¾ó"%9 Ò] "‡Cr8œ7Ü)øÜeê.1ÆÏÂ$¹+NßÒÚÆvŽòÍû¯þwò3•wûÅ"åOžN7[À?ï»SÞ4íf«S¯˜1ÞÃ&5Þ8´Ý&ðê¼Ùüòð÷wß?¸í"­ß"QÞ¢(P! ‡wqú #"ë›ëf†Ê«6ÛÀ;Ãþù®A*ΆGèUH,§çË¥ÆW&Î`\§8VÅãöXåÁ]lk_%@"ã–Õn„U‡7´µàˆÐ± MæåçR=Bûúp®aÂDZÅ XfD(àu_6Qìi°¯†a: à´Ü̑λm+_EX?ˆ_\¬ø„7–x´úx¿;ºµªû#ZyW„µ#¢ÅшÜjǦd ó2ÀXi -­äƒE¹\:¢ Ïõ‰à‡÷qe„'»‡eî2‘+=vRïÍ®¥;$œO<æ8pazÎUé3c?[´êVæ@|ã(ñS¬q‚Û¤˜£¬ë€Ã@¶~®Š¡nÏ,ô¡rã§ïD°²2ˆ0œû_>0’Ÿ*F ƒ[r5H E ¢WôÄá½EúËñBÌçê¿tšú& ƒ·¸æðÞ$àÅ‚HÀ·|‘,0Ò²ÑÚ•„íJè}"i:tùɱÑñÐD·GãÇ&NÞâ¡Ã{ë/Ä#øl 0&`AQ·&µ‹ê¢‡ÆÇsfôŽÅh+3ãuù¹oòÁ¤Û&‰½+êÊWy_—eWõ}ÕsŒ„Æ!JËom;‹ÄküÀöÁhTJZ½%Eë׌È­&#ZŽ´ˆööm#öÃÚ7“ïPB{ÇE{"ÝDÇš N­› ‚™u)™qÙ °Í€ib ©ÝUÈW~Þæ%®ÜUl8iÙžúYEªËÿŸ€[Ï®¶û =djeó#É;xa%?« <´l:bKœ‘}Óa6³o ô=þöp$Å(ä6@zË ÍX¶{„½œ/âpÉD~©ËªäÙ9þ½æ¨´‰ý$ЩxŸ.ÿµ>ï[ÿÒ¬]*HªNt ¸ïyÙ ‘%:‡ü'(ñ¶èjRÈåéì¥ ½«4¥™ĉݦhÏÀÿÝWk…‘ŸàÓ-AäµBúYœ%Ëû(kºsâ$è6´f·ƒ@œÐhã•h6Xî%"`ß’ ÑR¤A{"?Sl€² Vuòk´ Ðþ3@»p¯f2@5Ê áe‡÷Í8[ ½zÏÓÀ¬s…wMÄ·KaŒùð-[¸zà/(ùíÏÖ\Ñ©ˆ tŠÖ Àæ40B8J{RS–=kr_šh§åÙxdnø«"˜úI–Enøi”±Áø=4yWóÞe0,—’†Ôˆ„οWÎXžHÑôrþ< ¥BWýO0yÙÎã6ÀŒï•ì‚PÉ^œ‘ÉmR¢•ÄEAÆ–øPXÆú ´óà"})ÐМk?LEˆÌÛçEÝPZ;Õ0Ä•òøÈ]k£u˜›\—× ™âˆpì˜Sj —†ƒT¹’pqkÁ#éA·<=Ü]-°”žùìdGXÊ` Á¬c#f{Ÿ65K¸´v"4´ ¤x÷çÙ ËF‚w†Ê¹;î]:81­Â«O†'¡†‘²ÏØŠÉJ‹à+A Ñ’‰®ß(ïçÀ„äΚÜ9HXOgÂÝ<ûìßÁé¬äØÂŽÏ¯Uuñ}(I#­žÛ: ööcà vò’+{®ÜGÅ \/ 9±k/«îÌ€VÄv’Ì•³‚œ×1Ø0P,9N0Ù¡±q‚)kÚ–¢µE\.¿q|!ÉwÛ1î‘|}ɯ“\a‘w¿gŒûyª‹„äMj}åQb_oÅ#›W¡cw!/‘fÂ$™Úʯäñ`êNõ¹¥ fênÒjW ExÙN=ƒÈ¬‡°'Ýþt}0Ä~ûÜc\iI™+<‰# É Èz9Ëg+AŸ ùñóý?¹'Úš—2•|Ï‘€¯Åé³#qø"fÿ0© CŽqÐٓѶu”¤†ÞG¼¢éuc]5ÖÕFÌd›º?Vârpfuf XFD\9£¼¬Y!Xi–É2Q{Q›-“X¿fJCï(*6Ù2'à+̃YpÅý—Å.Ëqpcã`ºŠÑb«h¡1鎓™°â‚µh5v0„qžE;V˜Û˜%Vœaǘˆ[Ù‚ÀÊëG›¿Íh›²:ÿLHùtŒ×…:ýho_exF¿R¶I2?IÀc*‰:vį¶Ž~¾ædSåS(ù^ö Ójë(¸WÝóú–Ÿ`«Ðõäx€*S]¥ 8B7;òË À>Ìpúqz ´jNE™ŸEÙM¿'9£·–—áA¨¹Ãå²ô #ý‘äƒ^BÂ`æŸ`ŒV µþ‹¦•K™€äv㤯L&-;ƒ€œ*IH›!~ßÁ‘¾˜Þ±ººí‘qêÝËD±Î\:œÊk.a¼H¢Ù l‹Öeèæ$/Dÿ:ל<œaàl¤±–¸e88õ¡*h àË!§9½lÙå.šÈ$² À³¬%ÒíyžK¶i»b¾€è–˜ì·¡¾vgk†ü\µ£Ôm«gN:GÙZ*´m¾ ($’7ÅOˆÂ!Êõþ#Ìãb*½P9Ku²•áÞNÏ¥šz"`Ø\ü”¢òáBù¢n¸c?ïÍßZ_ sÐlXÓzqÏÀ{ŸëE`‡o‡$€&“Ø?£Ý6Ùð}Ïèõ™ƒÞ¼©ËíXFF~™…Ï6©€)OÇJ°rnOT’¥Ê±áý- <^×>¥GJÏ´S†Ê9Q-¥y[…*ÏÒ‡‡‘¤0ÔÌ¥_fÙXÑ÷LûÌýSöª´ä?ÊLæ»K»ÆTôÌ¥ôM+Ëi IÕ>"Áæ4Ý4Hº‚_æ³ôˆs¥=”ÍÁW<õ©>95 n~à!Þù_錑—è…Ç^&ðõGzRWwíƒü9bÖ'çQ#==—Áˆk’øí¬¦ž*‹6Ëf{ëA¶‰"?ïe£ì¶xܶçÕê´ÂÌËÓHöÅ^ ™“E~¦ÃèÆïSJaµ1Ž×ŸxVgâ>U¾ÉÛÁTy1Y+ž©öážÜï8I`ÿïÕÚ‰…ÏÏ2ÏŠÀ‘¿þC“D~‚OZ›hõêïNÚv†·ò›Ë­þêŽ2K~ÚàÚ^„><øÉe¿|°tÿŠû¶…endstream endobj 247 0 obj << /Type /Page /Contents 248 0 R /Resources 246 0 R /MediaBox [0 0 612 792] /Parent 213 0 R /Annots [ 250 0 R 251 0 R 252 0 R ] >> endobj 250 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 655.1059 262.3335 666.0149] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 251 0 obj << /Type /Annot /Border [0 0 0] /Rect [288.3941 655.1059 473.6367 666.0149] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 252 0 obj << /Type /Annot /Border [0 0 0] /Rect [375.7014 76.4758 522 87.3849] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 249 0 obj << /D [247 0 R /XYZ 90 720 null] >> endobj 161 0 obj << /D [247 0 R /XYZ 90 645.4191 null] >> endobj 29 0 obj << /D [247 0 R /XYZ 90 369.4317 null] >> endobj 246 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F72 9 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 255 0 obj << /Length 3784 /Filter /FlateDecode >> stream xÚ­ZësÛÆÿ®¿BÓ~08cÂÀ=ðÈ7ÅQ¥ŠÚŠ3Ç“B$Db  ZVþúîë ˶£ñp·ØÛ»ÛÇo÷ŸGðŸçÑyªu˜›4=_íÎ"éþxKk Ë1É·7g/¾·ñy…y”Çç7w&7ë÷ÁËmq¿ˆƒ¾\,ã ],µÖþf±4Æ?4 •Øi‚¾áÁŸºm6m±ãç|±B[îè·%7®«Ûú‹öH2›%Ên~<»¼ñ"[¥¾¶($ùV•d&Œµ±´ªûbB(˜RÛã)ceà Yù7æçõtË1áÌä§ Q„övïÆmÏe‡R¥Á§…M‚¢>@?m|ÇÂÞâOPö¼í* ÊrÏ#–Šý6Бt´²Îû¶¹Å;­™bÓ3þ/ou¿mpÒÍ–ßjîá7 äðáõ¾Úox¨{ìX)v"œ?èºÆ-=_j·?±c±>ñÊðȵ¥uñ;›}õ[h­°«Øã{dö¸È4mVžÿ\d&éÝ{¯~V±†uÜîýÒ𩆑7ëß«îø÷ßn-?ÝãòœÚ"¿ÝŽV·†îªèËú‘ûW î(¶pä°»—9Ab$&^~~܆hºþm%Û«ˆb"1 èXnhÏWØÃÒ쉺Wó¸ íCšªÚ›fÏJƒm¹:´]õ W*3LŽ;*2L¢öû ÝNK:¢çÌO¶Œ)v° S¢Ç ¨åÌzK`_Šßà=¾­Ë]H¤±›Õ9¼„iý(´ANÜÞuÕãv5û¢æ^RŽf‡©¦ãùŒÛCöðÈU‡¿*xØ–ÂéAV½dØ@¶{æ^ÔÕŸ¤ÕH {;âšq…ïä®[6‡»†ù ÕÂóÁ;ÈÏÜëþ}¬ð@6lÊG[T´t hºZ§Î?fA]¡Å¶xî öh6.:dwÁfÂ{T®ñ”tî×€mšÖ ‹„ÆŸd[BÏ|ª¾#ÉQÏèI³¡Ñ½sDmÑÌ G_û­¢6aäX; 1øåTQÚÙ¦¥‰ o6F[Ïš, û7ò{¤àØE.h“{Ú¶,ÖŽ)<ÞÓ:žPø±»k:öK·ìh„í[ëƒóÖ¨†p, XʯdEnÚ;¸ùáÍåÅw'±FgašˆsYZ• !œ½ÿ¯!æüx…&ÉÓó @¡Ò&?ßéP¥*sÏõÙÛ³Œ¢’㸳œ‹JF…™Žì05ŠyõêêæDÈ$ ­ÖÉÿQHÇñ«B¦qhÑ5L„¼~ýòï XQ°î¢Jr`¾µÓU (`C»‹õÈ;Âd«bÏžl»ä‡­w±ð°s‘.'cCÚj‡þVÇ‘ó4ƒ¹,U¢`3ÕQ<W$™jïê°ÝõE‹®9uP|z$”hÃcÛð—¢K³ý`Ï‘‹¶Þ¹@{‡Óúò³L3ö—`6‰ƒ+Áʲ;ÔªGÓ+þyØVôú–ùxË@ yaƺháM ^Z'–öFœ$ŠáíêŽGÒ4÷A°c_J¤§wH"èÝÈÓ‡Î$á¥c|Ááö@‡'Æ£«f ·9ú•…#,!µè©«ž¿õ3ß·ö‰óʼnx ÔefùÔËvÏøÌK ˜üdןK &é òrBZ;ÒžIvÒïPÖ—#ö[þ.8t£ÙYÇë±Ò˜  /\V@>šÈ½Øb× ! Ã"ð.©©ëI ⟙³o€—:ç.Jç¿;&çÕŽ÷ë@R ü$ ÌÃHM×£ûO¢à{¦#il.qÜ¢ß[¬ëQܵ˜Yœõ°ê«fßñ˜£ÙNkÎ; ¿Œ‚Á qåsV¶]áTŠwŠuF édZ<f ]$+,d 7éÈm˜dVOî– Zd4šÝGwðþˆwºaªbM:Ÿ»ø.5›úß4Ô:Îŧ.—år•rÙo1pws^8ÉRﱋvã³à"žy$ÄìÆaº«ƒ·eyü ²…&;·‘‚øc(¿!hp” ÕrL6ÎŽ™‘ù”tô,  A¤Ø¥Oi˜¥y6Ýù÷WÓ$›oöÞ08·E¥>ImU”CÜ…Pm²<Ô©ùBfëÉ–#º™åœ°ã¼–‘.(Ü0£"MƒJìå†û½¢u°*Ì•vg *VÎi€JBA†)1{;8×H¹d™<Šm”øDzÕ ªå-ïCÊy‡0õI@Çn°'[-ô4wŽƒ¼>¶¥Šâ:t’’Rv¿g‰ `üéÏ¢FÀLÖ ™óÆU¿ ‹¹}Ê¢0Î"g[Ïœ;ËÂ,O¬;!EƒZN蚃€jÒaS°½žÀ}?:㺠xàk#®ð¹}ÃC"ŽoL=H“‹¢*É“BƒzDœèÂÉ~ÑIFZ8¤ö3è S]¬Æ¡¨èÙ´Ii}bT´£8&öWrJ§Y5ŽÆáºêzg>^ÚÑÙ9›K41Œ‘œë’Ôy³ñét6÷z:GMnƒg‰ áż&7¼{*šSæ4´v0)B·YD5'ž–&-*J©±§M§JDŒöVgÜiGÇÕà¡Ôé$y¥IÒ•J:†yg+TTø¦Y‡FPOϕ͑Ǥj‡t\Ôêi9ÖXE¤ßV ´È•’X¼Ã€êYT±ät‚«ñ²ørÏ|,ÿH:­©"Oíl}h.•èãà©àˆêQškòQ5ÂFTœ¥FÁƒÓø‰eÛ’›Á¿Æšûæ % %Qg¢&ŒÏ%~5«’jÈŸ; ‘¤”·t[AÙV³¿«6‡¶\ϺöT%ͬ{ÆÂ°íùa¢Z:‰CkÑ '…ö©*eÿžÛ«ÆH(6 …ø0¹È2—±féÈ g²|Ç`0v1ºÜ tÄ€l”/â`tHÓN'adE sÚTx(žÐ¡ºÜñ6£.ªz3©›®JžR¥t¬JZÄÐõÈU>å˜o¡°ð"Ë}Î0iØI-”ËeC—7ªøb‰Ö>[&Xb!êÑMŽçªjÆw¯J’T%TÃUÛÉõÎAâª-ü$ÙÝSõŽ´w²-zÐPh»«Žº <à·jÉ;ë 5mI””ËŽ4NÎ7 ›àzò0O¥ÒŽÇjN ÈN6ÐÐu¢C€@ÑÝ30^¹I0‡^1áÎ7ÆÁjf\û—§µ/ìj_ø„庨 ‚Z¿§C@̬¯ÓÓ„¥p¬hË@U÷Äu Õ(éþ_Êa„¤.?K5¼ý(Qx?¸ÆÁ›p¢çØì³0jÑIM‚|#dX†6àßÀ7‚Å«,Lušøl-âã”~é$š%’„BoÉšGñÓÊ5mÏÊG=/7ܹçgÉ•ÁX>ÑË€c±cÎWÓ† øyâ·#R³Xeœëߊùohs¸þTÑvìwÓú&ŒSy~ þ¹ædñ€P~鮩†¢©Jú[Ù_îAßéûwE[aYóbÎ~ +ÓØáï;º7’Ú ÎO_ÀÌãš 8c¢ù.ƱòàºòÅðG¼¥R9ø™ø¨à8ªó jJõŒ™…[xKi#òä,÷ŸæÖ ËÔ‰v93Vx;TxÐXæxý$€×ä*ôH ç!"Ñ .ôÒ5ÃQÖl€ç„bôÚV:f±®²6´©qgùÝO×ׯ_þþú盫ׯÞÎÖ,4}ä™è$¸ìoH羄R$¼£ú ø ü8G¥¾ãq·*lj=¦õicG_Ù¹L_Ç NYý@š¨"û¥LßÓ-Ç„siò ÃIYå‚çÆûË©~NŠõHÀ©VK¨ ìó~üJ¾×‚E›èÄÃIJ»c9ç> endobj 257 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 731.8265 522 742.4159] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 258 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 682.0133 125.8477 691.7102] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 259 0 obj << /Type /Annot /Border [0 0 0] /Rect [469.48 500.4034 522 510.1004] /Subtype /Link /A << /S /GoTo /D (Installation) >> >> endobj 260 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 486.6467 209.5397 497.5558] /Subtype /Link /A << /S /GoTo /D (Installation) >> >> endobj 261 0 obj << /Type /Annot /Border [0 0 0] /Rect [178.9336 384.7833 364.1762 395.6923] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 263 0 obj << /Type /Annot /Border [0 0 0] /Rect [378.535 175.9343 504.5336 185.9343] /Subtype /Link /A << /S /URI /URI (http://www.cygwin.com/) >> >> endobj 264 0 obj << /Type /Annot /Border [0 0 0] /Rect [312.3424 119.4782 518.9697 130.3873] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 256 0 obj << /D [254 0 R /XYZ 90 720 null] >> endobj 262 0 obj << /D [254 0 R /XYZ 90 224.4565 null] >> endobj 253 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F58 52 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 268 0 obj << /Length 2837 /Filter /FlateDecode >> stream xÚYëܶÿî¿â|¨ÖðʤDê‘"b;q]$±_[IàêVÚ]Õ»ÒFÒÞåZôH•t¼8MŒœø’Ãyüf8«¯üÓW¹ºJã8ÌMš^mŽO” |¢¥µŠõ”äÅõ“çßX}¥U˜«\_]og›\—?±Z­c ÿ¯ŽÅáЮÖQl`,ŽƒëUç¡íV:¨‹Ãê§ë¿<ùúz<ÎFѧB’Oq¤•is•d&Ô±±ÄÖ›-°`’à~ì´gìØ _­u0Ô`çÀÓûçoñOÅ#§®½ÁùêˆÄ=vUQÖ ï¸mú{£…iP5´U—m›c…Ëa(†B»]Ù$(ººàhÿg8•OÙL‚M!ÛßÑh÷‘{í|nJ”ãÕZó­×:µU¬ â§F¦cßþ\…«µ›ÿc•ÞÔÂûC£(KlD,˜yÆ…VbY1UMZîÉ•ÐC4ÕC¤²0Õ*Í!/Ç2ÙL]QZGBµ=ÃvÍf¨Û†Y©…7‘HÇ£ •^¿82‹ŽRJ= qÁ÷ßxÊñY±œ¢Ø†‘5z.©åy±Wü¨´-výœ¾:lIŠ&øsÕUN¶"A¯ÄHœÅñt`ëÐÁ^y¸òÜ_6L"mF©ý¨¬ª›aÖoAë»Í3nnö`Ôzú†oNÓÕünÿñ ~^oËjËË_}÷Õ·ß¾}IdZ‡Æ;'~þ”æl˜Fi䦚zÊ[¼®„¿ª“Gåaç–¬M{ṙ·ï®ß¼ýþ½Üì—§¢ï¹…ª¢F_ CÝìd¸:èøî"<¸SÑðK:m7Êêæ¼û›Os‚é;SIWîðTên` ¡—ƒçl\s MLkÎjtW +l}¶Ìg¨HüÿâÙ¤’…k^5e½¨ æÁ•b¥c§2⹫zÑL+ÚÞ´¥Üµ‘kŠŒ‹nyïɺɼžûî†á¯ð÷_Ÿ¯#Efm2·ñë½?¢0K­à‚˜«gÏ8ƒÓ•:rÄÔÿW;ãͱSðg‡^™Š‹#Ò¥à¸eU€7Û$ Þ0#u@"{ ûb`ê;œÚ;/nx°t}„q2 °ô®|d* SB˜»`ƒ+QI_Ž8}·¯ÙB}" [­IžhÜ ªð0ð Ú©ÑŠÒ(¶^¾|ý†ç§Ù<™ ÎÂá0äÌÉÆ…ý©`a•¢ýGøfâu£±Üð²^,G;’CÚŽiîÄÕ|<7f$ä×Ï )mâ¡G› nÓ×¥p»åÇŒ{4¨ëC9>q¸h(ix®Í"6hô–D/Îxí]")#!´Y½âP2ÖÊw³«×7Ä"÷ÙÉv½±¢Ìå2Qvyæ‚Ôñ¾¤6zrMÞûð9Ô(„®èòÑnX\4¢8âCì&»Ä£ùÆxÓÌ.’¡÷Uµ¬ è@;7ÑU”ç¡É©B£4;©"Œdë ¯’°ÜŽ_§q…7~xMo•‹®ß¯ ~b$DªS±Ý'KÖcw46Ÿ²î)€ŒdŸ`ýÁvœ¯ñ Xåaë¹Eb@_•,Ñåë´m¦oè-Ì+ž?Ë#3VÍXã á½4hn7!ï=a²†;г{²Å$”"õ¶íÜÐsûÖÙàb‡â‘ÔûHÁðQ£ÝdÑ%ÅNWýŒ7­;¬¡d¹& × â¦ÉÆ:ˆRqF<6ØÈ…%hJ …MŽ¢xΙ]Û[ÚâÈ’6$û?r(…ò«¦zæ­I2KJÐP~ˆxe áuïòãtcÌÔ±ç…\ÄE³zpi!ŒÍàúÄz+ª·¢e:Å=\A¨«l&¸”̸¤ üpamÀÇGšª1NÏÀÞ¥‰Rà½Æ„&ŠíchàèÖSB<Øür_œÆðŽ~`ÓÀà' ~XaÔŽ0ùnĸŸ’`.¶ËËDyFq4¿ŒFºO]æá†ò¢³ ]ï…‘¥ƒZ‡Í\Ûƒ]Ïs_Ÿ -ët(ÖÁÔ–sÍ4“äÔfòøÂW\&ñ¢ŠÂQ|˜½Üâ1³à ŽÌjvßë®FObŒ”å-ÄþGuÄfçÞc#TL3Ĥª6zq* ¾ÉÐ4‘c›-×½fH˜8üX¶€sS$¤bµž¹ëä _ùĨ0Šbýÿ¾ZM¨T¢}åX¼à<%eX½Í Zp§$‹^—ø³ãn¼¥¦ˆ_Q)‘î…=´€zBdÍ)ÓŒúŸþÊ3˜tn]EcYwô\;ƒœJe®ý>Äáø@ò‘ðve-?°ÚéTê¢m®B£ÌoÈ]" K’+åáã`å¨Ö2oæ2ßl–¸ÀÛ<€':6 qùzå.¹ü©‚Ò\$þZxÑ!`5ñ ÄKDeõ £1yDi>¹/¡qT¿~¡åfV8î_)à&Î( ñ ˜ƒË˜…cœÒâ rÅi˜E颢´öþ’¡“ЦÊQÓ®Çô£àç½I›Éî<ý=9Èù±ß¾ræƒ{i'Æ+ú[ƒ ÞHæ)G°Ï¸ )¿¯Äà+Íèßï+dåF¥aœä‹ß ªÇ ‹b"®ü &ÞS…¿ù·‘?y*ök)d¯ü=´»mí~€Ø×;ïSöíy8!Sÿb>™ø$ò%è—ê³5U©âgp—îÏÞÕ/§¶ü?€ø*äÞ›¾§‚€å–¿—¤N™å³TIάl0PjÞð`ël6›£0O­«è: y~¤‹b5Æ’KÔuE©IEÎyÂø˜ï)¬ˆhs¶×$µÑajl"§M„»d BœÊ•½À6ŸU5~1¥œ”J¼t¨L´ø%p>æŠêòº€váª3c½–ǽ—H³PYÀß‚ðÌ‘që,‡ÕŒ­°Äd—§Sï‘"vj3ÆÄßš¨,Ìt:©÷CBÿ};Ô›1~ýBä+endstream endobj 267 0 obj << /Type /Page /Contents 268 0 R /Resources 266 0 R /MediaBox [0 0 612 792] /Parent 265 0 R /Annots [ 270 0 R 271 0 R 272 0 R ] >> endobj 270 0 obj << /Type /Annot /Border [0 0 0] /Rect [130.9942 296.7697 305.6459 307.6788] /Subtype /Link /A << /S /GoTo /D (Getting Started) >> >> endobj 271 0 obj << /Type /Annot /Border [0 0 0] /Rect [111.6002 241.6962 298.2322 252.6053] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 272 0 obj << /Type /Annot /Border [0 0 0] /Rect [132.4066 186.6228 349.4279 197.5318] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 269 0 obj << /D [267 0 R /XYZ 90 720 null] >> endobj 177 0 obj << /D [267 0 R /XYZ 90 413.8191 null] >> endobj 266 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F72 9 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 275 0 obj << /Length 2390 /Filter /FlateDecode >> stream xÚÍYYÛÈ~÷¯vL-,ûàµd/Ä“1°‹là´DJb†"–Aþ{êè¦H¥Çv—`0þ»Î¯ªzÄ*‚±Ê£UªT˜ë4]íN/";üøBØÖVlæK¾{xq÷S,V" ó(«‡ýâ‡â/Á÷Gs^‹`(×tëR*Pß®7Zëà÷íZfÁu0´<ùVwí¡3'î_pc…Gy`8–Üx[m;7Ý,Éâ, ”Xÿõá/~|˜HŽ¥üS¸äs\ !Â$Šä*Ét(”މ7 ®€)‚7ü9äéþ)qDýØK#ümвàuôŽ%·‹“©k`öìxd‡LãHvÑB8`d(•sJ¥N eÀ’øuµ/Ê=Ëë‡?þîíÛûïí®™ “L¦vSßò OÈE;¾¬kìGÞ‹\m”ÌÃ8ñj#T(âˆÕ¿kOH7š@U—¬iDï¸iW­zØÉÒfµ%lóÃ'xˆãPdBÙ¥¿F"6‡ÐwæF…©€ÁHÂ(U‚vœLÕüÅü’ÁA Vþ¹Lòe<—/L¨c}#Œ»oxa_Ü SÆÆËcu8¾äö¾6‡ž›ßÜùasÙ½/Êíxx‡g¤û+꿎>ê½N‹H½ªÛÃkøÝƒà¿B¦~Êò’öuÙÕþyÒÃ0ôîf)üËŠY/Ä,³0Íóx)åw`1oÆè !KJ¯F³0NR§üÉÛ”ÜñZŒ–aœéÜnòÈÊw“°K)ç{òÕÝPµ ^û"XÏ4íÀs 9L_xÆli19üà#Q€f2v4¢î}DI‰žìV½ò”„i∮ۋ—µÝ"™Ÿ²Úèü*ÉõRÉ­ÅçÖJ÷ŠØ…ëo¡1:—m-€4اѽ·Ì7-iJš-®³z¸›š‡Øg¹ýa'01–„Îøb€©X9‹"¢u¸Þ$Iü´Î4q U”¦««ZænÁ@Š%’´Ýíy‘†»ië¶3ˆÛO<„¶½ÚÀUÞÙåq…ŒtÌ ¨Ÿ7™c™€íKÍ4ÊÂL¤“.7àŠŸp…ø” œñ<~ø®I³P ©½Î« BUÂÅ6 žªÚlk–7ÎP,‡/éÁŽmÄÃ6kÚžƒÖQu%ÛCM2Ïr§â ¬i°·Úcv¦!‡³]ƒ»ÿ>…»ØFˆë–•… {0$é\’ùŠT4€ÁãtY£ÈñÂcÙq³lˆó í£mNÖ`hàyÐßP5‡,3Yð YæÈs@>7ÆÞÞ=eÐFf–É®*” Æž|áL”¸œIÛ°L;´\M¹Ô£×\ a,w‹ŒÏô¦‚Û;P‚?êPF¹òáßs”¦Î,.Õp´Yg–CxK“¥ø¯©ÂÕ´çtz­É§ƒÿ2'Lÿ?rB¤xÒñó™_ò?e~é"ó[š3(Wgzé–±Ó?\óH™äM‘§0AÆÀS˜¥ˆ…cÙ˜-¡wQBÇ®Rá-'ƒº~â“—5 n>S5¶`ìd=L·Ü`Ã…‹oÚÆ7˜™2¼t:ç†E9e*s³D¿Õ2"§{n:Ê9Mó¬þ¥µ=•G }ÖLZåDã”þæõ°T…±To›vÛO>m) © ržø’oãD ®À4ÇR7Z7@®ÑÃ4n8Sä*»SEËf™–vi›“„4Ë’›ÐÌáj7vd ð»ÒÐî8Ì ÁDðpä|$Ü—³tKÈ®ǰg 'ÝXrgOÙnœq­}¨6[*Gyòª„ùUoÞ1LWr”ì-_­õ.Ö¶cMxèñÚ‰Hgþ{¤4•ZчR/¬¾±s6ä©`óKÕÒvpÉ"uÀgº%w«fqüý¤Eê ;Â6 ÉœÝQP’ÃJÚÎ’‡S~ô¢(ÔtPIqì­Ý仾 Ž½û`º»át¾ãó®õìä¹ £,M§gH€ú¼õϘ‡™a‡\ƒ$c%Ù ƒ˜>å½µRwÜ3/GÈ@Êø“%·)ì0‘ËR”4V-/p¹#4É.¹C…%îqq—Á k|bRuD•±A·N!agMékºçÙžŸ]¦ŠeWÙ”×dt¦±7O:®ÍÆg§CåTæa~k.ЧLÇÎx=÷üN8)óœ$е¸ÐZÁ‹Ð8ež:aÑ œÇJ뤀‚‰µ¥M‰5®=9Ù`ÇÔìÙ@@€Wó Ë[ç^qÍÀ瀾œ›¨±o’ËñÉz5±qð¾YÛw>Tb”]Ñ;7Om×éŽ{Œ“°è Õå³°È‹¸ˆ™ÍA&BÕ¸AÑ%b ÁUZ (›²3X-“%qKS„٠ȳÁïFö€"${ø²û”dì> endobj 276 0 obj << /D [274 0 R /XYZ 90 720 null] >> endobj 273 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 279 0 obj << /Length 1355 /Filter /FlateDecode >> stream xÚµWKsÛ6¾ûW¨É!”Ç‚àc2>¤IzHÓq§V$ã¡IPä˜"5$'Íø¿w%‘‚íøP{lá±øv÷Û 6£ðËf1…œ“X„á,]ŸP»|{Âìh‹C‘_—'ç¿I6c”Ä4f³e>YfŸ<îÏœÁ÷nTU3_ø‘—ÂçÞrqoÛ7íœyeRÍ¿,?œ¼_îÔIßÊ qXäZÄ%<Ž£Y ¸ڮ¨ @Œ&©1öe™g*Ÿ¬ôÞýñæãÇË·ZŒ1"¤cáóS#Ø©Þ úB™Á«¢\¯Ì8¯’Ug†§ç.™¦%½ÎÔÍvu `ÛÍg*é =¿ ßD.ÂŒò³ªY]À_^Vê°×lá4í¥ª³2›î„SÆõþ](Æ(ÔÅÏL<ío’¦jc]NÌGÚÔµJû²©­Óm³ T¥ªûÇh0¨×{$4lï'}ž ߇øGÑÏ…— Âî…·uW®j•ñª©Wf´NÚÛ×.~VGùnÛvç¾·™lš®ÜÓæfšý‹Â5n ,™›Nrb²ŒÌß´MªºnêÂ$ÂnSË|‹ãˆ¨‘ùÅzóç_—oß_]]_þîÎB9VqÓªäv”ûûÇ8ø¹Ø‚{’„~ÈÇ8§CRØœØÖy«†TÙ4eÝ«vÇ`b_$_-™7JY“,Žõ‹ÑÓI •llÛ)ëTíSÒyØi¡]ðÝm|¸N‹¤^© ãƒPg–}A LH±:§çg.ãè)kÌgÝôèç?d¢JÒ µØ¯í]ÙY»íüÿ> vYA? åƒ%åì7÷cóÆu–VÍ ÷Á*»+ûb*òd'ÕÀ6R÷…qï"„}&I@)Ÿ±PÊ™o<°Xo¼wr‹CAÇóô½ŠMäDšÁ§÷`×·ÞL&t_ÎŒÌ&Yaqá±pj<‰9FÆ;±;¹§Œ?Ôej_AµÀÕùlLÆ×GTâõÆwqjuKîuS5½ ûZ ÃåGðj©q§¨+»QØA†q<üš‡‹ ¯>S&*+fî5„Ê}‚•U4Þ®i"ÆÆÙECŸÇoIfh[ËÂp0x4¢ÛŽ)[€k››j€_ëÚÖíH<ÖŽ(#PŠè—·£Anq(èjGG€ÿc;’!Ä¡M®v4È=eü1஡Þÿ[Šendstream endobj 278 0 obj << /Type /Page /Contents 279 0 R /Resources 277 0 R /MediaBox [0 0 612 792] /Parent 265 0 R /Annots [ 281 0 R 282 0 R ] >> endobj 281 0 obj << /Type /Annot /Border [0 0 0] /Rect [215.6003 172.304 371.9338 183.213] /Subtype /Link /A << /S /GoTo /D (Extensions) >> >> endobj 282 0 obj << /Type /Annot /Border [0 0 0] /Rect [201.1154 110.3239 357.4489 121.233] /Subtype /Link /A << /S /GoTo /D (Extensions) >> >> endobj 280 0 obj << /D [278 0 R /XYZ 90 720 null] >> endobj 283 0 obj << /D [278 0 R /XYZ 90 79.2031 null] >> endobj 277 0 obj << /Font << /F51 6 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 286 0 obj << /Length 3648 /Filter /FlateDecode >> stream xÚ­koÜÆñ»~…eøè}ñ墜ZqÈv*+1 Çp©;JGøŽ¼<Ë.úã;¯å㎎a4 îÎÎÎÎÎÎÎkOŸ*øÓ§™:M¬ 3—$§Ëí‰ð‡-­`,Æ(ß_Ÿ<ú!Ò§Z…™Êôéõí„Èõêmðu¾;×AWœ/tМ/¬µ}|¾pÎ?Öç& îè‚®æÁŸ»©ïš|Ëý{œX"‰5ºuÁËò¦xÞ|”4JãÀÚów×?\\÷,GÆ|mSˆr¼«ÄœjZÙUœºP[Ñ®lˆ\i{¾ˆb\`çÓn“WyWb»®€Ã$ jìÜr›Ù†Æ%Aï~SÚm°%àWûn·ïÿC‘‚Ðuj“ZZûEÝvç “™ ¾Å/H¦ÜزÁgh½gð}¹Ùpë>iPð¬=Ȭ%¡Vкc q‡MMœÁÈF 50ݽ,zKç³l<˜›&ÇsøÌ ¼= ØÖá‘+œ_7[J ¹#fjd«Y²@@´kêH±ÝÖ¢<+À+ó;佞l•hGÌÝ÷:ض §•y~^­¸qWtÝxnÛOmW.eN¿¢j¯¿;Ü.©h(çeÆçeÒ0ɲøÃÈ&ñ¯U–f:5&åLD—¿O·ùfS/¹ó±hZ’ vÎ~÷¢0 ÍÙœh¾Húv“ßµÜü;Ô'wëŠHه܇Ӿ-QT´Þ£n»{´b~Bú¶Õʪ+šùf²`¤”,•¯VÍ”h‹B¶ø—ÙñM¹-»éÈ7ñçÚÀAßqïʈØ0îšzY´"Ý]¹šÐ´Æ©xJ.ž’‹…Œ“ï›'W/Ÿ¿|&½®) ¡ˆf‘β)ŠßˆþiÂkH­º—•þñ‰¥BÞ(iTõ}u&[¬<\}*VV+•ªÿ¶æLfý¦‘ÖŽAùMO9hËÿˆÐµñê€Jæ7Ù¯y“7°­DÑL-šßõÛˆ|ãâêêÕ•´×E¾{¿\ˇ=ŠFìò¥4ïs9®Þ}SvWFvÑˆÊÆ ‰ý„{Ì L®eúªèòrÓÊ1Õ+äÀÖ®¦+ôGzs¼ŠŸäÏ ê2:;TÃÃlŠ"ùå Åg¢Fir6熡4Šb±k)1öcÑ qO³ $»¯‚œ»íºF+Ùq¯ø„î\“}ÞÈò^ˆYoÅ bïÀÿ á©ËÐø^gx]ðýËs“ë1ÁT<Ò"³_xÆŸ‚Ûä'ÈCÈbŸPqÎ ûÏ!RCˆ2ç¦φÄjCšRVÜ.väjáÒ_ž9h‹¥D:XµëÝ×ÒÕà/Kä¢#„]–ÖC¤„#ŠpòT^æèñ©Uï+ÜIÇÝû5zÍMÇe5FSç²²i²`¿E¬ÚÀ¡2òÎIÎ ›R”m‹È¡±Áu†° ÑÖ¹ M{ÅcÈ0I>ñÚŠ-Ò‡Imjçò!~@afáŸ@>â&‹¦¼¥$µÀ‹ŽDŠº€v?—%{Vsæ‡bP&Ãð©® =¯ ¢@íi|<…²­‰ðCŠÌ‚LzËŠh×~'²% Z ö¯Lç%„ÔòN¨Ì* Œü!’.À÷ß³¡I’…*6û"ûo ‰…^-;zLÂ=Vö±‹¸g”r<~ñúzÎ6h—A;‰…®Xo‘PgÉTf¬Í ”6».>c'¡ÐAÜ»+*TðB0ý¥¤YkÁ±(9AXÔM¶ˆ`›Ã3ulE¢àu!£=ÝYÁYeÂ(Ml°¥Øñ® W1Î $q¡CéåAÌPÈ_p[Θ®(0…ÊA2³I*‡)ÉØþãvœ‚Ûº¯x?N¹APGPl 6¥L·e(å_¬=Ø@¢ƒ†¿ÄEoDB¸¢` …\åճÌÊZзSgtéÌbÊôûÉÛwêtéÕO'*txæ÷˜k…ƺìt{bC“˜Ô÷7'¯Oþ9$`=ÅŘäLnimšÈ%ÃÒ(›ëç/.Ž˜Œ3VéŸÈ¤§øU& %vÊäË_^|qõe<#Ui `²?ážâ×vQf6;`øùõÅÕ4¨×Ï_½|(º æä>ÏìFƒÃŒMâNJC§Éÿ½›žâbLrf7Z§aÛlXyüùùS½51:†¯¾3Á¿p{˜,#|™WÒ7 ®Ð{6Òh!M2XôeƒQNÑ(§d”ùƒbYWäê@öfäÜ]åÝ@…a­´¬·ì+±q0¸)«aÎ} |СÙï48ñLfŽö¢mªµPØi!+ƒÐ ½„Ô|É{Xy¯ôxÎj…°”·ò;ž þaQ°w8Û5eÕ1 Âû|ƒ!†G}rõì×·êÆ4áw˜,Tßý팋]½\/Z–ÖB.¿ÒdWÕ~{Ã!ɱÿ‘mˆL¯I–à}tÖûè>@D÷‹q BÙ/q›&åÛݦè½ú(<ÅYËš­m^ŠÇ†ÄcUˆ¦#»¥H˜Ï³Ã)lƒQ®0 “§°í€|ËÌ"†híýäCQˆµ¥Ž£?{lO5¸õ¥42ÿFü|©/5<@>¿\]rƒxÅÆ˜üÈ£ò´–áìÌqSchî(h&%t¼;õ`rh‚0“ õËrÕ Ü‡³.ξ¡ÐžÏd#£%/¼ÿX¶>k žÝR¯£C"vprÞÈh·'mYÍÒd Ô&á‚SE‚5š½Gµ*7eçcÀÚõµNaéußšÔL‚U’í§ƒâìe¾8ÛcÌg• 0ÐS:xûtºeF•Ùw9TÚåw£Ûèa“Ø0r ªcžfʯ=Þט?&ˆ[ 0ÎrS#¯]bæMn9wè’+É”ˆFŽƒ9ëØ#<዆[w¾bøœ¥Ø£úÔ1õÛߨ©ÁkŽÈ_²b&5AÜ­¹!wÐæà×›,lç7â”Æy Ài¡OhË$ïGI{ŠùaÞqk™ïùȈ—bææ†Ü~‡3tê'zQz-†åc±˜_NµÉyF>äν<ÕlÈ¥ëàyǃtºXÞð¸À]ÞT|¯ÖùÈ™:`¬dJ_B?B8_¢£¦°7ÊN'««Kþ²Xê’m¹©}!AæJ@î„JÖ39§Ï‰Gå8RÍ8âÎ)ÃÑŒõ†ü$¿ÙøœÁŠØ[aQ§²iè.$ÁÈC­Çç“Ë( ÓÈY ž\^¾zóþ‡«‹‹÷/¹¼|ÿââõë'Ï.fÝ·Õab¢Qº„ sÒcÅŸ²’(4ƒ05Uzêæ³¶PYe¿-gK<¡” !ñs´Úp+/ûP ³ãúv)Žt\òâ°Áqi ¿9º&¯Ú|)ç‹8Ò+Î¥br:F»_2s„ƒ¥†þ°q¾ÜÝ9Á@$imd¯°ü‚xš­ûÙÂõ(ÒS5\7{q|1žÕ25x#ÐrL«“‚$³8ÊNIBã’ì ~¬Ç[ŒçBý#‚È×ëÂËØrXB›à-4Ÿ’1zØ ã×”ó-9¶8%OÀ¾ &:}”^F*LÓØN¶2ãÛz¼¯m嘠ø6”eïÛHÅb=Ê€;üµÜsþHucÌX±¹(ž9…ˆ=›ãfÃ@±q"ÑëÊg}ҒŬð¡èèþc†Œúè¤QŒV 22Ø™ÄoHwöaL!̾öÞ 19Ô‚Æ$OÈ%â¬ß÷}t'úÀU)ù Ò b7ga‡’쉬 ¶G³&ÆéÐÚ,“‹äÏÖs Rˆ²±‘Sbä4¾Frc<o¿˜Ôaþ´:ŽRuqÙ"½áð‡å”¼:àø=(DWšw¹B;˜{=2$fЗN%6ãÚ€ Ò—UïÛvN€p‰Sí"‘Êð¸4'ÁX‡ª÷/÷ë²O¹]Äû(xáu>~‚)'Ç5EõO0<Âu|rs„Ùjk(O…½CÄò „Pisÿƒçc}Ïn>:¨òŠïÒ6™DSßUÒuµÃQØØÑ‘ÜœQ,…è\H‡>™ïé4Òísüªù§®±=ây‚7؃8+ÊŠcÈFÁ÷\öK k²Œ q˜²¨lçî^SìÛᇠêH¸ò˜ƒÇÔð“ Š)/·´/|Á¹íù¢.Ÿî¶†/¾© >®Å o0aÙÿÁ¿  t]lv²6½ø¥Qñôƒ ù<‡·yÕ¿%ec5ãW²™½Ï(’JGr‡Žç+ÿ K†6yÛqk—ûzt8áéëÛéÈ{¨lâ=TÚg8#ôy¦¸¾žŽBrèŒàÕ ï’ORè 3èëüÑÍZ[†:Õ>N¤×â9;51pq£ê;¤ú}ƒßÑÊH|¡gšPýlôk>À£s‰ Ò…VÜ*ÒB’Qšó‰ãü+‘ªÉ÷øyç;7~Aƒ ¸?wk¬? .cb ýòuULù¡°úŒ´©Б4²èe¿˜\­û÷™” ß"þ°âa‘Ž NEÃo°ã3:lÓo.x{”ül ëbïðð°ÍW“,*YÙ¿kô’VøðÝÉKÅØ±ù_ø˜T<œûÒ‹ÝÔiG— ÊIHšp¶³&Ë‹eÖ– tCT…Õ:ÿ47~¡ô¯±ôVè1iÖŠ¡â¶‡·½äð¾ð3£nNš2/òÔyðH¨ý®×% Ö·9ߤ¹à† ôk­xØvüK<©òÓZÒ,»³ ÂÆÈ´B~Kö›¥ì·é~­n†…¸‘Ñ mSM§Ú9‹ÄkÏÅ‘’`ý÷oÞíendstream endobj 285 0 obj << /Type /Page /Contents 286 0 R /Resources 284 0 R /MediaBox [0 0 612 792] /Parent 265 0 R /Annots [ 288 0 R 289 0 R ] >> endobj 288 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 323.35 273.5444 334.2591] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 289 0 obj << /Type /Annot /Border [0 0 0] /Rect [176.9659 224.5206 350.8863 235.4297] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 287 0 obj << /D [285 0 R /XYZ 90 720 null] >> endobj 284 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 292 0 obj << /Length 1909 /Filter /FlateDecode >> stream xÚÉŽÛ6ôž¯ð­20RDQkEŠⶇ$Z’mu´”<ƒi¾o£,{4m`D>>¾}£Õ&„ÿjS„›Lë ˆ³lSvïB?¾S²òÃ_¢ü´{÷þc¢6* аP›Ýá†È®úêéxëkÿ¼iÛaëG¹WLko·Íµw™»U^cÚí÷Ý/ï~ÞÍì’(ú/åH”æq tœD¶>Ô¶îËzë+/Øúi\x»ˆ€8Œ¼ÖŒ¯¦-ÈúŒ9jzÆSÞÈc€'D‘Û’F¨êÉ4­ ›=èŸyÃ…8(ïùT÷¼šN‚_[ ×ùé¹Z5c9lá2s³uõ*§›`90ˆ¯t ’ oª „°õ(Òê¤ð†‰™NCoø*]÷jÑùðL.„¬&Ò5zÀK©gÐ#?ãÙÉ¥ò°wάp#¤¬»@#RmýÔ —-‹ wLY"5(WWöã‚l¹RB^µÄÁ:ùê üGŠ#c1ÕdXrJ(ÆÅ“½ck^ÎÌps¶Ã¶mÝá>ñ—ˆfά´˜Dy5ÇæÞ ÅÓ…yc°'m.£03ü©ê=åxœ Ò©ëû\‰³0Hu¦6i’¹Ö “Ò€Ž 3ãùKÄ•¬yMMù¥.§fy!ëÈܾÎÑ¥Ù¿þ66Sé ‰À†´1ø‰½Î+hË hi¿?0ÂÙ Ê¸Š’{E£$ tªóMÇAšGñ•aÆó—ˆ+о&ˆÂÈ÷ýÇ,Ú¨8Ðq!ª¯RG4£ ãêµPPè°ÊïÛ“‘ÉU5³˜g­¦D'Àp˜Ð/¸¼"iÐÕ, ”f b’oZ²c§"†Ìaìb‹òRÝœ-±Ìœê9¥4Ád5—¦\­Ô ,Eè}FXEí0Üà5JH„jÉ=!ú-LÂnÖðeïÌŽ÷æ”·0åÓÔ ØŠï[ÎQ“cYmyqÁ±•jQ6«õ†œVÆ•§Æbb^LË{²ã‹3è„…ãl5ÇæØË«qô\úo;±ÖòÔ0ããÈW®S.kmÉ RˆÄþr×b:¾™¢\Òˈ˜Qž’ ð˯!û(Ðu*Û§¨vƒ;Bã/8λ=ò`’  ZHbÀŠ âBGƾ U2K"‚„Hyp¼ŸyÿF²¿Ì‰9Žl­y|7×A©’!<†Ùl«ÝQßu{½Òí….XpØáúlr~òåñ…/PÁ5âÞqXÄÔd¬Ì ‘ªÿe\À↢žj ©Gyï­„óŸsþ uçP’˜ŸÍ¸”wÝsÎzg> endobj 294 0 obj << /Type /Annot /Border [0 0 0] /Rect [470.6371 655.7119 522 665.4089] /Subtype /Link /A << /S /GoTo /D (Using With a Debugger) >> >> endobj 295 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 641.9552 252.3638 652.8642] /Subtype /Link /A << /S /GoTo /D (Using With a Debugger) >> >> endobj 293 0 obj << /D [291 0 R /XYZ 90 720 null] >> endobj 296 0 obj << /D [291 0 R /XYZ 90 630 null] >> endobj 290 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 299 0 obj << /Length 2498 /Filter /FlateDecode >> stream xÚíkoã¸ñ»…[°ò¡fDRÔc Ø×9Üm®ˆÓ~Ø[t[¶…Ø’+É›z÷ß;RXÙìWôË"@D‡Ã™áÝíÊÙ\EÞWï¦Éw9¢Ïvbì_`^•›*ݦ2:ô´™½_ü8y³h93J=Å;¢œ3©©Œ„’&°Ì‡q ¤ 1Ìæ&TÄ'0¬jŸX °  áy3ÓŠ¸0q‹²–0 ¦Õ‡J5êHÄ¡f-¶ ⯜Bb<!‡ ÈXá6*§æá*«ñ„lŠlÅøMÉß”Öê¼nxžv} è¨éNš)^/×çxY1†>æÄJ±§]J¼†×?ÎLè¥¸š§·» F ¥Òø,á«Õׂ¾ö5 "ÆëŸ_üôÓÕ«]ý²¸¼z{=¦µØÀ0VvÃ31›GQä]gÙCkP2~â«i×-•/ñº-÷L¢Å›÷GŒúœ rp-›¼,Ø–¡yðî éÔKÒÛ£¶Xƒ #üc랺ÞÿÀ‘òÐKÒM†8Æ ü‡2Ú~êê³:bæ-ÞS2D™H©±wiyÍkægÅÖ€µ)ÜxÅ8`rxãs¸“û7Oœ;ùuäƒie8ZÛl·cØ’·N«“Ý_2Æ>½Cª–XK•ÂÍ¡*ñSåiÃt4hx‰èÛ)o˜¨ÝZ>`ìqƒcÆ}S¬±jŽèHi“íN³8ðà^5|8œÝÀ[¦^Úi_€ÎãÃß§à~5Ót0¤qÏ,Òb]Z‚€´µË#ÎdžQÖR÷¼FAÙrq>£òˆk«1¹o)rg¹ëcÜ&ªò¸ÙÚ9ó3’H„a[ÇÎ>B´q çþÎx€pÏxp¿E±-$wÈ+–T÷bŽ—%9*Ñ,Œ`&0C€s¡B&æR. dh%¢(I\ž|‰ÙB{75Z<]ȆsBÊŸk`Á;ž¾ØRZóôžfÍ–gÖCï†Í‡RÍœs¹f<©È<9Öß’Êÿ2©‹ÐOÔ“I¥ø¹¤Òâýÿ’JŸÕÏ&•'d:'ø-©|K*ß’Ê0©€Ä~"0‡['&¦Óÿ™“4è¹~§+º*Ò%º eÚ0Î6%“²÷k)uO§sºi†—ïØ§KîÈ_\Y¦‡ô–::=gË€-’‰·l¹»3¾ñn[ê=à®kζ~zÈš%k!¬•š³`hó‰öc]âÀÃíÓz‚#”œ¾«aƒÙ_)y»'2H8©w &θéãåÜR®Úbï6+V]èBi X†ÞË’´ÔÞ]½¥‘òØ¢àO¤ê-OŽ,hU9E½uÞŒ­ÜØÆR¸@iÑssT-—¼Ú´¦ˆVF³§4‰#Z·i½­–cŽƒq9ñË› ›Jä#DØzÔÒ„0ºÎwÙ(Q#b Ýùhù9Ž•¾ [âŸãWC. u›ç™â¯¾ vVUV(XetùdpεÀ Nn‡ñ9Üæ„–Ù4…!œ4¸6«tæ&¨$Q%–›ùíÇÒ †2ʹ'kˆ8ëÒ¾¥p¼,h˜… ›]+ÑWšýÞåó1Îᤈ˜ïE£õ±°•ˆQÆzÒ’'¿ñ‡b*>,]¤<ÃÙèûÝ÷þÊ£ßÇ„E½ÅÆ„C.×,Å ïe¤YO¼U›bÚŒТ´Ù‚œ¢ÅÕTõÓÈhÚ!0Åîjœ`cƪEwn×”§­ÆzGت•×T§qíË(¬Yöäëõÿ«ÔÁ§v°­1ÍŒ¡~—Ǻº€õtwq›ÃIk'A8;‰ñ¹vwô‰- Ô#.é7ØZÁ†ñp“ÈÅcÝfUc L àx6¥XBæÛRõÝgÖ{1œ¸[ucWTáx]Ú§FW€¹ÄGˆå@Ίgãq1Ö"Œ•tqùÅÂÀˆlØð¾T:†·óXh 4ä;¥ ÔóW‡¼ø‰·œŸG_ë)‚@=(½ |ÀŒ}fÃÏ>ëc¯ø‹ úþó/w°Å6·¡*u»vå£Õ¢«¬NKþfÿáâãØô”MÑœ¾-@©J¡¢ßÖ±©=iÜj¢ëa—tZqicµ9B¹ÓÔcr&F¨HF]Íi1R˜Ðƒ¡·Þ´¥Î\‡ ½è0î%ÛÊ”9u»¼¤«°aü’ªt¼ñª° —`ˆzt´pÒœø°»‚Õ^ð”a|ï‚Jáâ¢Þ¢ñ×Û8Z•Å3Ûxõaõ[ίf9I¾ìç ¬ë}eÛ \+²¶ö¹“ÄõÚ&“nb¬@#†)6bý )šŒ¸rÂ≗:7ç ÅCÊU–ZPÞ0„:ê‚î@ñiX´†$ë}Þl‡©ÍEü™›ü~%½çãaLDIò ÜûàjÇ ÎLi*„àÁßøsÑìØ¹Ž”ÙŽ®8Gý2¿~Izþˆà`d''| Á¼šË׌Öåì`*»ÇºpyG¦¸aT ~8HùCVnÉ]2h›¥UC?H˜Ðh¯Âü‘ ´Ä9pò¦®M-„àôjÃУfœPBŸÕ¢±ôFB5”Ñ÷ÎÍó¦É ÆìÞܶe•6ü¾Â@kQ°xì÷ã®j7§{;[gisluQ3>V”­{Ä%=jм5ZÀB¤{þb¬ÀhuÔ³·W‹7£ùW‰¤+óŸc$ñ½kúÍ´âYk'Ú$P8¬xÀâ²M^8¤<vŽ]“sF© 3DÎn¥W› Yx„K nSºŸ;žá{pŸj0Å ²A’k‰H$:ˆ†šÄ袤¿îõ fݯmK† 4ø%Õ°Ü £èÌn¤HåR* RkŸ=Ž~ g½öqÏ‚‡/@Ê>”)Ý<à_ƒ‹ ‰UéˆÑt\KåÞ¶²j¬bMELGrqu,š|?ÚCÇЉ*åÚfMZŸÀ ÇLj´àD<ôË&†X?ƒÑëŸJoègOǾ™’`š(¡ŽñAøß“wïýéjâOœø"“hzÏÉBé ™î'j¨¼ì|7¹žü½÷ÆìÎ{Çž˜}($Ñ©Šy…?»/PÄË+½½föÉ ¥jŸK¥{0´p[ªbÿn‰Úu,l4s[>µo­ø8£Œ ;áôó_I—pendstream endobj 298 0 obj << /Type /Page /Contents 299 0 R /Resources 297 0 R /MediaBox [0 0 612 792] /Parent 304 0 R /Annots [ 301 0 R 303 0 R ] >> endobj 301 0 obj << /Type /Annot /Border [0 0 0] /Rect [214.0902 630.3928 430.0603 641.3019] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 303 0 obj << /Type /Annot /Border [0 0 0] /Rect [214.0902 525.8819 430.0603 536.791] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 300 0 obj << /D [298 0 R /XYZ 90 720 null] >> endobj 95 0 obj << /D [298 0 R /XYZ 90 720 null] >> endobj 302 0 obj << /D [298 0 R /XYZ 90 574.7071 null] >> endobj 297 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F52 24 0 R /F58 52 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 307 0 obj << /Length 3217 /Filter /FlateDecode >> stream xÚZYÛF~÷¯˜‡B!‡Ín^~ÛLØ 'âÉ‹$Ø¥$J"L‘Iy2ùõ[W7I çŠ XÍ>뮯º­®Bø«®òð*Õ:ÈMš^mŽoBéþòFIˇþtÊw·o®ˆÕ• ƒ<ÌÕÕín¶Éíö7O'+_+øã},êº]ùQæm Okïv•iï<´ÝJyUQ¯þ¸ý×›w·î¸8Šž#§<¤(®” ´I"¡(ÉL ´‰‰"¬|åE+?N´÷¾]iåÝ=iì 8Ðrû×¾”Î5¢' :"`øç®ÅÎ}‡ÿÀÈÙ¸” ÈMåŠ2M$ÜâžÆäÞ±íqÝ€_™·.újÃg؉†Š½LÝAHŠ&vý :»vßGþ®x6ÿ'tDS:¢0@RB:¶¤ÑÆoþúælo(öK\ä:PY˜Ëâo@Ži3phùÄ¡F:#Y毗¶V*0±±t}ÃlZv—Y‰ƒ8Õ–ÿæÅ»þÆa‰¢Ea$;\yåë< b­Àž°‡l¾kTªG%^ÓJc FœzípàÏßC{»JGÅ•[-dQÁ?Cu¤Ã %]Éñ }Ù”]1T ìµçm¿kÏè%MÉŸvæ ÿô‡²®eÿø×ý‰ÜLöÝYE³í‰×pÎcWÁ'⪤ÙÊæëŠ÷“¿_eÆ}›È°Ñ¬ÈQØ•£T{w¥‘7 ÷܆¹1J…§l3 jUyd)¸*ëìóûw?.©V« “D¦• ÒúµÂ³Û†%L]Ÿÿu£ ‘«b]["„ hnÙ„ñ²;’ÜeÎÝ¡M$вÀdJYñ%l"l çN–éŒ-oø‡X?Ø3Px5lÚ#ö jXB:ËA›-Ê«ÞâgJûgvc1rËŸk˜w¸}üÂJZtäp„¶À£wØ.¬L°GØÇ&‘õ'“ºÚTC}Ï›<0‹jGº]°!Q(E¶7TE'ÖĆý$ åŸspL_ÅNL2Fŵìï®­/?¡T J%£ÃGq zߟ)0£ý9«€¡åß­ÍL)™3PàÖžQ QlD¢Ã×dcžŒú¬š’ûvª”v?H×¹'ùvß°ŠqI‡1)°oÓ6 !ƒ>Fï'SfË“ ò¹Äqnm-ΈÅéKʱ‹ ÔÎk&kv<Á)ú(àUõàƒð „6ðü8½ÏÖ‚ËËT­²$5ÙUœé ˲s1h††'ùÚÍó§`Äà )”›¡j…0ÄÜøíä ÓÿÊ­&*ÿ€Ö·Ð›'Þ‰Ò(ŽsI»‰³ I¢tFûÖpóž£ýá†H;ÉÐx2’{ ʼn˜‰ãôÍé(±§M•ÞK`ߨü…V@Áã[#F<š-E/nžÄ¦üYB 11Ñ­H,‰¨É&?ö:N%Øã:œUõ§ÚEèsÖ§ ТºÎÚŽ Aèfsr ½ÐVùD€‰òÌE{?íOçée¤Çœ`탌V=ÿŽùhwæhŒ½òd÷°¹‘¸G“Zòtlìxö”2N™¤„^z[Œ¬d¸`ñÝ,#4¼Ó¶E²›½PíCÕ?/>£ž aƒÛoù³¥¤`A¯&½”8DpƒçˆÂ`Ú¶¤°ç¯Y\ÄŽ‚Mí‘¿‡îž÷XÙ©A´™/¡Mß?÷@Š_·Ír$W`7­'`Ó»˜#È?L¨'Äp­8“ÝEù—b:HÝ3ëÐäT@âÎ$d1ϰ&žO¢'̹°wT¶ì^õüKæAÿ:éÂò#'à{ÙYõ¹„³ÜJ4YY Ô÷_çžÁfPWˆºBpf`2£M}v°fËB¿«hOþD3´NdµÔûB®³/·¸”ÉÙ´Î`°ÇU5¸›Å™GAfޏ€ rÍ…lõë//r¡/Ïu|‡aC•Æ™ÓÉ$ »yþt"ä¹>Ø™9 Ãéíõ5¤Þ`ØunSö×€¾^?ÈQè86$=ÌvÞIóñ`CÉ„ù¹‰±÷‚”¶ÏÚ*Ï—<¡í‰³hYHž„؇@™­!QéG‡Òd`/…c!¡êq;xïv´&Tð爣‹1‹ñLê'xì\ëvDŒˆnHÉ+ÑC!³7Ec­µw-oùwŽâ”÷v)$ùŽÊÇŒoüB˜ØnÁ û¥p§€>Ëhó¹$[O…öc%p’©T‚ž³tHA3ËFôŠ áTt·Z ÓG%ˆS%›|ÿã??~ütóßO?ß~øôÓç¥S³OUóSÁ©c:Õè×™;#QÙ%u‹¦Âša(T~5TRhD…Øi¢øÏ gLª8ôå¶o)Z2vÒ1ÃŒWÐÁ¢ŽGeM•¼~J¯Ìü'ªöORó£ý}G¥XGA]ëËB® t5wêj WØaRFm ^* ªþ„Ý×Ö”‹óЋ}µK–’ûåüÝüþnù’•YK!«0â*}Q$%¯ ‡8´ˆX˜qy‘Œ "ƒå<ÃÇfÄ›÷ˆm^Ãýæyîoê²è®ÏÃ~$>‘” »‘ŧ„ÞŸB'¡kYú)J 72ª0ëä€Áɸ“³)¯»°AÖ§=IœÚûA¼3Ï•¨0<†+‰›`IH¦­„Ksî¦ø52Þ  I”b"6¾JlÊ»ñ’ТŠÃ,’³&²y Öxgc›¿ÿ Å„ŠdÔ+ÈPÛX3033ˆÒ,ˆ![Î3ÓOŸnß-^AhÍC€ß"À'åüTP¤“SÚªy¼±òXϽ±h,d¥M©È²…{ñFPðéd‡aG[!qa€5d˜ˆ“-ÊN¹â‹«…‹çÈIN$­pWK¤ÜX´ÿkPèÆJÙ»º±ï£iÍ] nIh-/lØÚR2è‰FÜúšÈ 2XWñ迼.¹zûíô‘2Çè É3ý2ýNî¢aïÕ*r†Ÿ˜†Aš„¯NñÑül©¢ùÖÍÅZ`ÒZ‚¤c"C¼ ÍZ2oTŸÉ#¢±Î­D£Ô;½á„ϱÄ/¤{'è<”’¹+¨sí½L‘ß– ߤŠ»-e5b‘ÂÄð}nœ3olá×Ýó%<ŽW;þ-øGÌŸŽZµ\üÆ*¿>_}¬zªâcÉP†M¥¬]½îS˜h¿0ÊÆYh…½ãÀRõÇž$**—«f/Éö²‘Í Ø%wJ&™¨ >fï8Q²‰ŸÈ:éÀ†©Ó’0|7k&û¶[ÚfèÑ»üã+Ò˺~#.Îɲ@‡Úºžÿõ缄Þ?¿ÏÅÕÒ„Ö‹ë%õnBž‡t<5D‰ªàAMû¼MþL%»Ã»¨Þæ%ö8´ÞÙº³:û°Åž½uq¸’_ÈGZµîudG¤¤|RÖrÉpÄåáDFJÀ½ÆW¥NÝUuÙÇòÅ)„߉Éjd€™l$jÐÓDçÊumý².'W9ýÀ@e{Q8Û²æ¹;p.¢§[,ßÍi|OIlÖúÇûO?¾»䊮[DÓ9±Ç¹% j¼ó6*»áþï'{Tûú5ÖÄìÆS— ÚYžÛ°ºr¾€bŠÅ”¨ Ýc´Ë¯|ÁßÝÉä %å V†Ji¨Ðè¹r7…<»à›@:yH€v]­éž½£—tyª„~еt2¤qʼƒlà ¤8ñH9>ç»úÄû “5-¬Ü)ܸjdÔÆÇq¹¿Pi•aÛ¼ØWûÆÂ"‚\«WâÃòb¢·«gâ!ûØXz™ ¨ùäRÚü–Ú8“g6o”—à#ÌŽm‘Ë%8tŒÿ‡ (Ñ9Pž’«áx×2(>òy¤vèßÑ&(Ü(ãò5÷\Úß>]°Ã‚º:Vƒ´…D¤ì¹XWtu:اƒˆ_ªpl[ŽstÁ®äIw²Ôhr ¥svðœñÆtsSïv%—¿3ÑCœèð½ÐºüZ‡’©$©0œ¤³ŠŒmvÇ…—íÿohN±endstream endobj 306 0 obj << /Type /Page /Contents 307 0 R /Resources 305 0 R /MediaBox [0 0 612 792] /Parent 304 0 R /Annots [ 310 0 R 311 0 R ] >> endobj 310 0 obj << /Type /Annot /Border [0 0 0] /Rect [313.6748 581.1609 458.6627 592.07] /Subtype /Link /A << /S /GoTo /D (RC File) >> >> endobj 311 0 obj << /Type /Annot /Border [0 0 0] /Rect [268.9935 498.132 429.3554 508.132] /Subtype /Link /A << /S /URI /URI (http://256.com/sources/argv/) >> >> endobj 308 0 obj << /D [306 0 R /XYZ 90 720 null] >> endobj 309 0 obj << /D [306 0 R /XYZ 90 720 null] >> endobj 305 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F52 24 0 R /F58 52 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 314 0 obj << /Length 2369 /Filter /FlateDecode >> stream xÚ•Y[oܶ~ϯ0PG"V$E]òØÖ=HÑ …ãž>¤A¼ËÝ,­’6¶ÿ}çBê²–íuƒf)rHÎ g¾¹D^DðG^äÑEªµÈã4½XÕï"7}÷NºQá”äÇ›w?übä…ŒDåòâf3;äfý%øiW.eÐÛËPíe¨µâ—aÇÁÏuQUÍe¨Ò`…+qðg_V%’_ÂÜ#Sÿßm³m‹(•ÑI Ó˯7¿¾»º83J½Æ;’,0¯N˜O²XHb>¼Ã‹NE4©H¢HÁ±Hó3 Âìͦçqk;׺O’ÍuÐï,O8²¾ÄÝÛ'Mp¿ƒÒ×žÉ &î‹-JGØHwDº*ÿŽdl×T+ãàfÇD1e]!êéVÀÒ£ãéV¿á_¶m˵¿ºCÉAÄPj!MÄÙ3g¬“lª™ m2ít¶Kz“F$‰ôzk=V6 £ÎLPì×<@¾u–‡JÌ•këw¶µ¼Ü7<Ó ¥xöñÀõ3üia’ü ü•ÇOï®.c·£Ò­g~=èÍ1Êì›0¿#Ž.PÛBÅy:×é€DÅgr~PTeÑ ÇäÌDCo}¡ÌDÖÊUì+›²²û¢¶/™íìö¿.30×ÝÓD &Ööö¸Ý¢¹ì·<ÓQ–üMŸZìÚ-õƒÅ¶¢¹a|¿{Áþk{ÄŠlÎÖÔ¢X2\¬rz ¤ôÊQYà°éX:`ÍhЃpg¿³KœÊ,Kã~Õ“—óµ$_KO|­`¬3`¾eUܦr–§iVhy®BuœöaúÀqFZÌHO S VæÇ­-ÖaéÉ7ü;¥¢yÛhn¼ÌØk›|ðÀµU³w.¸=¶vÕ‘•< ?ŽÝgy6ßïxž yx m‚Ï^‰ö4(k#…̳ £ˆÓ8Á  Z£ÕI`ödá”n!³xròþÙºÇGÞ´^dÄ_þìJÄ.ÿ…Ã$Á 2ë5Ý}}Ï#c#òMŒúÄà;Tf¦V£Ç@;È}¨ÇE–¥:ºÏrÏ¿'Ë ½VçÖ6³ódRq¡ÉøxÖ—/2 ©´^Ð9ë]e'xDÉ1æ‡ó@FøÃ=žĤZNV¤š%+41à Œ]ühgž*iCkLŒ\¼iÇÓ6³s–t,A+&S£e_±ì 5]L›1]HЊ“7¤ ÏØð禶üFö¡¨•íÓ4…—#ô%"Šr.7¿ƒ„W™ j¶˜ÇóÇ¡mÖǪ¿8Ó|é¦ìCo÷Hôa)¶Ã‘ҤÙ"‹¥‚)ÐX€PM¿¦!Ê¥C¨DiV|–.ƒ nQ‰è×SQ|FÇ_„Ò8@ß8á¾{‘}ÇAxÛ¡B+j=D/]”Bnš&>p€¼zÏÐÐêXj7 X·Ü€sR/öì– RC¬Ë´ÌOþ“³ì².ÏH—>SÒáT•×Î&ÛG^˜¶`±—1”Òd[µïö¼{Þ×@²û’º›x Ú´#ùØ&H]CÏõqg푦ozò|â“î^´2b^cF:oí$jÃ` æšû+h|%û.þ7ÍF|›ˆ¹¤=Jù&6¾&‰Ç:Òòqü"´ÃušôøôÄìy×BŒÇ{Iî›»2¸{5!à~ÑÏp~Ë? ú¥'ÇÁ´>¤…]G¨ëtçèïʪ¹E0d‰éšÈYζ8ч[¥àN\”Dâvã=­5¡ŸÈ꣨832¸z€šJE}„B,Ä£¨v×â§Ü:ÚðZq26Tâ4zjÂH€94þrZ»²®vŠw´Kõ‰Žº'¬­xëvÐèä²ò`­Ø?×–›H{u}ýûõ?¿ÿïêúŸß>~úx³äȹ*•¾Þ¶mKŽ…¿ÔuQ¹*‚LJ)ü÷LÛe  §„Km‰'Î/FZ$<ørEÁ£qÿÐó{æø _ßó‚ë«ÀHE§Ä&*èòµÐWè^àéÜWYÝd8tšìÏȲØm±Mê,wIÓvèç>ºÃà™Š»ƒèTQŒM÷ƒË—ðÌa/×§uÍÕ/âYÎfÈj†Ðæ[÷H=Æ{wÿRkùxÀ›ªÒºNÊ΄¡HùÚmendstream endobj 313 0 obj << /Type /Page /Contents 314 0 R /Resources 312 0 R /MediaBox [0 0 612 792] /Parent 304 0 R /Annots [ 316 0 R 317 0 R 318 0 R ] >> endobj 316 0 obj << /Type /Annot /Border [0 0 0] /Rect [351.198 532.7473 522 543.6564] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 317 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 519.8997 241.2192 529.8997] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 318 0 obj << /Type /Annot /Border [0 0 0] /Rect [293.2659 108.4949 456.2964 119.404] /Subtype /Link /A << /S /GoTo /D (Error Codes) >> >> endobj 315 0 obj << /D [313 0 R /XYZ 90 720 null] >> endobj 312 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 321 0 obj << /Length 2913 /Filter /FlateDecode >> stream xÚ¥koÜÆñ»…/¡€Ë]¾ûÍmÜÀ…¶œ ˆƒtu·wGˆ–¯¿¾óZ’GQ–„Ú€n9ÎÌÎÎ{ÕUÿÕU\¥aèçQš^m«W€ï^)Ymc3GùÛÍ«¿ü#VW*ðó WW7û "7»ß½0»Þ„ þy?V¦,›ëμ-ÀÂл¹ÎBoè›öZy…)¯ÿ¸ùç«77#»Xë§B”‰ôB¢$‹|F1I´i˜{_T¶CžË-Ä©ŸˆþÑö€Ÿ¤^´¼ø ¤ÆÀŸ»MSǯNµm;bŒ¿¸?"ÐSïÈn¡¼Þô°¶¸ì„Š˜d™+¬ðÐZ³³BòË5±êЦf@³w‚29üªD¶·­AŸq³°« }|>Ä*нºÁmF‘WÔEÏçQü‰D‰D8å¸+ÚÈCGv€Y¡LCo¿Êˆ^`›¶¿Þ17V*¢·¸?Óžù™Z_”òå@½Y ÿmÛ›‚ðW6HDZ…RÜ’@¤k i- rŒs¶=xO§BÊÅ×[xßñòh$«Ÿ!·|ìD¶f²”½IRí}Dº¢ªàIq„Th÷ˆb­H EÎ>Þñ: Öv\ …‰wÂCon *¶<3ìÀt¶©<1ŠAF> ÓÉä ýS‡ÂÈôÀÐߊM8Œ½›cë × -Býޱ:o{¶N@Þ“Á¢Â|‰,‰øž +žÜgõ4 k¬z68±€œæª$"ÄÍwÏ(ãÖ`}in‰wÏ›"Š+›B-e$½±ËXÚW?’Pùq¨(AT¡×³€5âmæˆ+qô!AFÛi_ –€wóû§n*²»uÃÓIäë0‰†×>]A| Ó©š‹¬ç¤XJsr|l QœQ.¢…¼!«ªwt6P3ÖàìÉÄ2üŽôœ©\¾ããr`˜Záy´B÷ŒÂBºf™Z»fH­í %õÄ›­™¾ÁŸ”eë9qQ%²ã×£-³VÊæT¶.²3SïxAÑL8â0ˆ\6<>2¢0\ƒ v;ª™ˆ瀜?×ò¦Ð¡Z1Vü,'“ mvL‹ö™I›ÛÒ‚®v Ϧo*HGXAœ¯!‹ÀyäP ¼ÝóÇ“–³l¹ÁL¢O! gõ‚ b!Ko$:[zñwvoØÓ$Ê„8HƉ€¤gŒb,È\ý|7Ú‰+¨y‰1¨0’D×üj Ènõái·zOÂ"ÂYµ[þ펗TGÇÚAäíMU¡QMé=†åÆé•´¨î—‹ãØ1q,›Gž³BµºàPK@9 óz¾E`¹êL·£¾CW/…¡ºµºJ²n›Ckª—è·&EiÿZµ}vªäv(t•”oÿYcAÈNu.GÕõ¦í×XèÌOÂ1²/u+ňž©SñF즂q•#„ç4È#!õãϯ߽{ÿ÷?ßÿëæíû_>®ñÎbXf ÞVunE¼8p‡z[JaÌ.R‚u2¨ ›ÚT"ç,Ô€ös?ט>æÚ,)œÈwßè ´ž5SóÞ$âš„ÄõÀºfh·²†ˆÞÊr¬e`=¯ñÛΙ3”¤K9Âá¢|G’ñ+õf¬<—Œ$×­ØùÑtÉXè£å‘c+–˜®œ4Ȇ²¥w~tm¡&·¶üÀj¤FTbYÛñò(\Œù“¥€$Òšº3TZ .Á˜W{Žg‚ÜSØnï85¯E\ö`­Aé’qCM¥ >†lJz^˜ Ž<¥ZPc«)Éãøû•$¾cnÅž¡c^A fo"ÌÛóØ-Ì$pÛô‚jÎæVtæ¹Ö—Q†V3®‘ŠXGS6SÒïã‚­¦Ÿ*™…Õ’ÌKGÆXæ„ZÿøuCb΋'‰ø5¿§íBmÎ=þ™·³âÏŒG-œ‹þûnâAóÊ®»²á>ý…Ùí#Gßz¨nmûÌ”ÎñîL­GÀ0÷£8N_s‘ò ‘iE Ë“¼íë4~i°Õ—L]°Å²˜l 㬠ùó(´#Bz¬Ü@œÊ´w.Þ&$ásgAì^aîE|ó)<²É èÞ5 ˜|õe=vpQÀUCñ6‡-~ímÝF/%øa¥¸4ïÌÅ@~oö4îÂåX¬!QÊOÃ|íšuò<0ò*;Åì3ƒ0à9‹ç¸7/… ¥½¥o'w^1G~F.Ç¿{ÿÓŸooÞ|x6°fiæG:rvgkH§në;fVÔ,cJ©«&˜)°ãÌ%üŽjóCçñ'êÉæÉDÂTùa’Ç—Q{–Ì!]£Ô²’ñ®§2¡o ì/H2‘‡hI"ï 2[~˜2 <œZ;bQ~Ã6‚?≎ˆ4‰·Èv³ŠØ’+£P`›ÁÚDà“-1GƒY* AÐÑtnAò—4M€ç®áß½W‹cœo•?pJR÷Ôü0u)@s–þ’ü‘yÇΖ†[£yïºÖ´ú.8õÔÞHáQËãªy(™eNrQL `¥¤á/©o/Æ;D]K|³¾Ó¬TÒÍKR͆òÀ¦ãa>ÂÕ‹ªý(N\›ýXµú:]ûù™)sæÁMâã©F}”]¥t¬²ÿ#û ›‹ìƒ€Ù‡æ ¿”Qƪ•¶üäçÔ£S?Í—ªäÎ|ºéAHN7aJi²,šHÃ3ĉ’Wó Ÿ9»„i¶Ì.º4Ç4ùf …ÔäZÅyZ*srª-ñ5‡©Ë]«tÉg°7IíAK-FEj2÷h[óë•+ò*»9­ÇÖz–ù}V.‹b"Ê^"|gep,µn,&*Ô­Àföh‰BúÝÙÞ¹ €¬f»Ðo®X7¹ ›X†M¾×ÊçÀ9úÔßó³ýÊ9H ˆ—L*õþÊ m¢0fõò„%ÞÑ€¿žuÇ·Neq7^gežŽ:uœ˜Õ)”ñ½ ô¯È;ð¶Ëºè)~Ï|*{0b÷<„sù5•L†py|@|9†Ý%4$}Ïýxm `™ôÍ’(ä1™-Êäíù³º.Wt2¬1nÃÙc–`zs[Q¯Ís6\È,ü“ëA(_àÔÊ8\¡NávóåóðÕù=èÊ®q~ÿësæ÷ÔPË%Ü\ØæD·óBrM×aáõÍrŠ>\\5ÁÍfèÌÁ¾èg1 £Ùuf4µóãÝ•ìÿš¶rº‹ÑÛâëox82=ך¾qD—ÆôÓÔ$P.k§l˳ŠfèQÕCOs’Ì{3Þb4`¦ÏÁÓ÷8ÏÇ5Ïóqµ\ëtºž. èvhÛ©Dz–áîþZ'´L®,ÆùÈÚD¢æCϘÌã%>ùëKÔˆÌVJ©hiÄ΀^6ÐÌlªŸ—s–éˆÍ,nµ#É™ ¬Íl¾ûàBA\oZÿ¦ª­ endstream endobj 320 0 obj << /Type /Page /Contents 321 0 R /Resources 319 0 R /MediaBox [0 0 612 792] /Parent 304 0 R /Annots [ 323 0 R 324 0 R ] >> endobj 323 0 obj << /Type /Annot /Border [0 0 0] /Rect [402.1091 628.8045 522 639.7136] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 324 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 615.6538 232.5397 626.5629] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 322 0 obj << /D [320 0 R /XYZ 90 720 null] >> endobj 319 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 327 0 obj << /Length 1376 /Filter /FlateDecode >> stream xÚµWÛnÜ6}÷W,P+‘JÝWúÐ65š @ÔMÚ>p%jWˆn (ÇþûÎ É]IQì i`À‘ùœ93Ô;Á.g»,Šü<β]ÑÞ0³üþ&0’Þ\åÇ»›ïn“`0?gy°»«FîÊ¿œŸÎ|pG × ézQ9ñK׋ãØyÕò¦é]/ÌœwbçU75ª»°ö¨µß»ìO’· &QêD¹ûÏÝ››Ÿï.‘%aø\쨲|¸ >=Ä~Å ïy÷BŽuß¡¿u¦Iæ§ŒÑ òƒ„ét›0úþC’,uÔd¡å{7<8‰ÀQÀlÁ>l'zAáVÝôRÕK-ÌÍL€*)4÷è"Ç7ÆóCûaš"ÚÛF¸Iàð­„±ÓõP”­¼r?}ŠüòÏÌÅ&ÒW‹ ÁÉÎ S6g鯦>by9Ú€zCyáºC©Ö†Ã$@¬Å1÷†<—¸:ˆêS¨æÀ‘hEZ¢ÓÛ„Y÷žâ.‡Î sGõúí·úÉX#Þt¨@3\ÙZánË5øô‚Î |)QíoDä[‚wØS[&_aÖ}«©o±Ey"W-0µÁ'¹ãk|ãÐO“è2?Jsíá5" Pk|æ—'¤fKvt`£Ý1îCæŒÃ¼¢†TbQ¾À-@|Ù² \¹©Œ™Þ0euZ(&i¬“ÓÜ*PB)*îi´§¸Ù6åÐPmq*XP£B¤Î?ˆ¡³ã%ÀsL¯ÞïkÙ£ÇÖƒÊc0NR@¢æG¢˜c*qnÝCLC2ó€ÁÐñ_š>Z “ðàgyž@D©Ÿ§Y@½ÇéäÝ6Ó Xœ={ˆcI‘í]R P'arêTÝ ƒ-âüP–RŒX`AÅØá…>^ôpV‹ßëG´eâu§„¼‡^‚Æ€±-­_ûÓÀEíhOÅ/ö[š¿+.•w[Sc&Y‚ãÅ…Úš0xð$+hþºPgàV¥¦‡w¯Ÿ=Ý!4_hËWjÅÞ,vÏê:¾ÀÖ̈¥´®§GO [ècååÐ`N–^ˆŒ –F¸¾ÅeÔùˆË¨Œ Ú-Òì•z:õúЧùÛò®³Î¤¯/ÍçÙˆÒWgdùÁ!ÈVÓ¼?y£â„:Ä÷®ï¼J 1[:òÒ^صâ,Š÷^%ºë WÅÙ릦1à·ôKº `_· ÒÿÚ©­GH~+CO,®…Hs«oí {àíЈQ¿áU‹:3‚7¦#ö«j²?mªU šßhÜFÌH‹ªŸNg-–Èš|¦ÌKh´pì£pp…’$à3êÑ–5`ðdmëXtåÊ"G uF-×A‡¦Ÿ!Ò”ñmsZék¬0qÖ6+¯^é5ÇdÙ˜ S?‚ ~mUÛhûÉÀõn2Ê_JìXMÌÒõxí²JâçÀ:gtý©«`‘‰w5½ˆ4žGZðik'õ¾Á—Xžycâ¯Õ(šÊf%:»j %Æ•=n[_ØC‡Ñá‰RW‹T¯4ñ·:m™8_¸z™>‘ÿÿÆ+ G}‰ÔZí9ë²è»r|n°âæ„xP¢Ã_þóE_rÔÿV=AS)Ô$W¹]ï0wcmoþÞf€WÛé¥A°h—+Ús3´·íÁ›\Ù|6Có4!=‘žèøÑêÈǺ¸ÔìÃf"C3ͺϨË>âÆ‰~ŽQôÕ©)É»‘Hž™Q¼ðhgfû †db@®*ÙÿŒ‰µèƒAÖöмÔî’5~æˆNmaveü;˜êø ùØÛ††I=_Ðwöü¿ª¹2¬endstream endobj 326 0 obj << /Type /Page /Contents 327 0 R /Resources 325 0 R /MediaBox [0 0 612 792] /Parent 304 0 R >> endobj 328 0 obj << /D [326 0 R /XYZ 90 720 null] >> endobj 325 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 331 0 obj << /Length 3255 /Filter /FlateDecode >> stream xÚZmÛ6þž_±èá«”H½¸mÓ9ô’â²mQ$E«µµ¶°¶dHòn¶¿þæ”dÓݤ °¢È!5oœy†tt¥àtU¨«Lë°0YvµÚ?SÒ}÷,’Ö(–S’o®Ÿ}ù*‰®"ªˆ®®og‹\¯ßF-–:‚ÁË}¹Ûµ‹eœ+èÓ:¸^ä:8m·ˆ‚ºÜ-~»þϳï®Ýç’8~Š!$ñpO9Š¢<ÌŠ"¹J3èÌuN|ýc““`W÷·†mÅò¾¬wåÍN^×ÕÍqÃM`%äí]ÕôÜ~¨‡-·~®ºÇå}ÕÝ´½LoÃá8 hÀñ2Òa”(ÖÌzºÜòåÏ–&NC­"ýy\åF˜¹íÚý m'¹­-ùÈñßbv¸Gš/_e hj“ƨh°,+šDÈ"q€p±Œ 3S|×,tÜ×öµÍõ|:. ”4\³t:Kƒ7à %3YÙ¬¹ñ é+)´H;zï™Å¹w¢TEÅ9«÷ëFˆ’™Ãdaª Ð" p‹ô4u!Ñ îI‚ 3¿ äÐóÝHé0òT­{ÚÀ3=`Ö€`>É Ã¶¸U/PhÆÁÑI{Ë,±ãÈ„ÀC÷\¾ð°ˆ³€6Ø]ÝÀß wbÜ#ç]‹cÖV8øv¯§\ k,£8 M§sé·eWq\ÄÁ .òˆmXd·ãNâRæ¦+÷Ä-8ˆÑ ¢´·¤A ÒÁ¢ÈùfNŠPÅ©UäËÿ~ýÃo¿ýýíׯ߾yçS}ž@3eÂsæàLãØ‰VÁj<“…9\[¥•hø1¶!Ý®¾éÈX¬³Ø˜°Ð&·:K‰æÀö±özöyCF£¡umÙ݆-ØfÃÑ_2õ#w¯bhœwÜlp¡fÃc·v œŒ¶ }á9áZGö‡ÚùG(J6S%kFGÖ,oÞ^÷•Ϻ²Âã—n,犸iø…J,‰‚Ž}ÅzÔ ì¤Låsßmø¶{.ß“ ö;…ôßûj8¼›5ŠÃÜ@LàY·èÍj¨[d.-ØhðìIƒtZ{d*h¨TGß3Yt¼Áß“$^Of¯J¡½ïÉì:ì„BBC3À6ê,1û%¶·²Wyƒêv H0Sy¤]þØrLkl«Ý{)®à( neô’«ã¥Ž¶3îdc‚wUušË!N… ^Lê*Œ³Ü`²­Óð$¡;ºå”Ѓ3ÎD¿Ý–ÈÍ@Êq ?Þ;ü‘YÆtqè·Lt(7"°NNE0EM6ÁƒIÝS"œ/ˆ"„âç… u^ ŸU–q¼ ÄÔ2¯£wÀK-OçЗѾi]3š»{ïxäƒJToƒ¯Pß”ýVšw®eèOG S#î;ònèú sHÑwk¡paõ+ïF…}$©•7óÅ÷ß—»c5Ç'¬˜êã¡í#}BRXz¿ö­W5+‘e¦Ü±úí¹$_ÃRMU‰ô4 ‡‚0'^ ~wø—f}ŠRXV\Usï—•1ÕÒSb‹Sá&7I.YçÒ+D+xŽ©ûÊÚù­“@úI„¦$S‘"h-y–¼$©®ÝsDá.vA©’7ðšGýâlŒLÄ‘è­é'_/WØ·åd¹dä&°‡¿ÎáR1¤¡yt\µdÁň¶Á˜ç@˜ÎªÇ¦N‰v×6F¢OL ÚŒnPv“0ÊjYYO©]Èg¨E›˜zv¤å‡‹Î[ ª2lF.TQlXq®ŒùGöØy¤Ã´òYG35ú5•tC“Å…T|¤GÜ#Ô½TcÞt®© ]‹@ÃÐn(ë†;h‘ûËÖ¦„k-ÆçÉèHÁ·ë¹yžú¡S6ŠÛc°âŒE÷Iðκ¿PÂò¬ŸœášOÞ_jJ–8!?"W ×¶øÇRÉöÀÁ9Û àwK Tqc’j;HÛŽl†O3 q;õiòT7‡57¡}Òl'§ÇèÎ=„Ì4tëcmÿëâ**t¨£ôR¦rtË)¡'ÖŸ/8ËTÈð¬äè÷§¾&àíÑ t-øž¤8=ÖAœŸÌÍÆÌñ[º§9_ÐÕÈgV'nÑYˆÝ|b|%¯u€ _ÚÙ†û "³«šr/^í.`”¶×‘Ъe³]¸ŸC£Ï¯¶žW [T„[ ïÀ’\­RÖâ“€HÍvàä¾m ¥ìbQè-B(C£@}VÌÛ7üP‘óÝ×MÝ åØÉò„cì-dí§ÇN$pð%í_ ®º®µ§Ã9Ÿ«a·“#OÉöš^{!9¿âóáiºÏä½·çŽÍéÙ»síQ?㣱¤GÉ סû˜ï*¤Á†¼ /+Q7 ‚v±f~aAlA~6E-ÆÆ8§ûN\‚£ÿx D\¸pxçÉ\›ôrq9¹PL¦Š `kŽÎy÷¯J…PÙZúÂÆ‚½n”M|8³•?Þ]ò\E|˜1=LKty‚©¦ÆÕâÿ\{ù0ažö(Wdø(J踀3¿ÏŽÒ Ì\<Ÿˆñ2N~üÅHèÿ<Ä— ë¼†‡D™ ¿óPÓ…!s1úŒ8ï Ë‚rå0)ˆñ0^vòLWBûP $/ÙÕ)Þ¦Þ;aòéŽPJã*XŒòÝ*pÚ§-·ö®§vá€`«ðÒDplëÆ&‰|ZLsÀÿiò '!P¦:9¹üe‘eÁ×ÈÚÿÞ¼~ó½×NIXg'¬‰u!×…ÿEËårÙ?òWÅ䞊`¬Qûò«LÒÁïsBBÌ5þ‚¥|¢§›|ˆ1‡¯B.ÍÈÖVœ™©K6Ô-á¡ÓKî²ÛÛ“H$Vnå*°Œ…Ó[ï¶¹ô³‚­ ´þëŠ?“16œ„Kü?xendstream endobj 330 0 obj << /Type /Page /Contents 331 0 R /Resources 329 0 R /MediaBox [0 0 612 792] /Parent 304 0 R /Annots [ 333 0 R 334 0 R 335 0 R 336 0 R ] >> endobj 333 0 obj << /Type /Annot /Border [0 0 0] /Rect [310.0911 517.5511 495.3337 528.4602] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 334 0 obj << /Type /Annot /Border [0 0 0] /Rect [349.2891 383.6064 518.9697 394.5155] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 335 0 obj << /Type /Annot /Border [0 0 0] /Rect [167.7298 273.947 343.9252 284.8561] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 336 0 obj << /Type /Annot /Border [0 0 0] /Rect [234.9639 190.5891 442.9944 201.4982] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 332 0 obj << /D [330 0 R /XYZ 90 720 null] >> endobj 206 0 obj << /D [330 0 R /XYZ 90 607.9496 null] >> endobj 329 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F72 9 0 R /F55 21 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 339 0 obj << /Length 2931 /Filter /FlateDecode >> stream xÚYmoÛFþž_aà>X,v¹»|3mâ=´qQ«wÒ"GK+‹gŠ4(*ŽÿýÍÛR$E%¹Â0¸ÜÎÎÌÎ<3³ /ü…™ºHŒ 2›$«Ý+%Ó¯B-€bÑ'ùiùê‡wQxª SYx±Ü ˜,×go¶ùÓ<œµn¾gÍ|aŒ™ÙëùÂZ;{»Ë˲ž/t2[áŠýÑeäs˜{aêßཀྵš|”:2ñ̆ó¿–ÿ|u³ì$‹´þ–ìH2!¼ §6Hø|½np«±’QÄJi`ŒTÿÞ‚„¤_‡Ñ¬Å‰b/q÷ÜE+5?s^Ûº/ò¾^£¶n´òáŸ*Rmþ8×éÌÉ›¨ê¯·[Çüt‡æ%ŒÈ°)ÖÊúañ§ mÉ¢âÔ¦n˜[QÍi3.Çá ‡¶%3ƒ’‹Ða¤ø@×xh¸}ÇÞèÙss0‚½ïi¾næ¬,.ì4EËO7\ï™æEWn˜„>#غ†©ÚåmQ=0)©O2}纵v›ËžC †Q'rêK6(Ò¢p@»çw2LNg @Œ}ÍÓ¨^ŽÇó™ÎH¾­øùñŸŸ…6 Tj"q ëê°»w“žfU 2e…ðR¶n;ðØ­ ”L2{7O-[Ö‹jß?É+9欶ü|ÆËEµžwše¦Q&&:@K¦Îh©‰}d¨/ÆÙè:T“A‘µ™W ¤Ô™eoFöeq•7/ønA\ñô4$xì¿-k€¾±á©VÜN§ñ,TðFlÚb'sŒ3DÊ>ç$èpfˆgÖqD™MO©kl`bã-sÉž·0qÿ„Ð§Ž§ÿìÊJI¸+ &Í;<Å{ÂP XÈ1ÐC8䀪åB`¡Ð#TrdõÔƒX$Øš÷’bo˜Œ1£~’a®ÄÑ<™·î¢øƒ26ö!ç9íé[ôñ$ƒ¸ô°j£îy`m`éPòŽ)`LHõðÀÖƒw¯Úâ3 ¡½!!Õ¯%Š8ôÄ¡¹jÍ0Ü26{ÁÚ)]NšNR >›|…'øÈ¯kVàöÜÁ¥™íŸøxqjU h®xÁ;)‹æÝó(žWÝ2²ÇBCæáoÜú þ¡q-ùAù#òG ‡nëè"(d–1ÔÔ¸ïô çµP<¡œ'Ðý¦ $K<æÝ-o¿ùtwsóþÓ›Û?Þ/§b+‹‚,³Në'Ùü&¶fv×僓²AiHäñE”&‚Ø„ªøÒb¿rªEl¢ò3#áÝj!ä«(¹>[NÅ eh~ûø«#×¢4*uÐ/Žmÿ×O<åŽG:k€Ø0i¤ihÎTEÝ¢O8¡Ý)C”?Ó°}ÒE'A¦vèVïo—7“À¨áðÀ’ %NJC_bŸyaŽ£›Ç]dã#{N…†7|æ-Ý’{ŸÆgCN,±2ôYü„©Võ5˜ò`¨“!'(Ì›iîlI³¢jÝwT“ˆý¢cŒý:KQtE$ < ϜרÀtúˆoxáÃÓ+q‹ÔuU²Ëi j Ù:P,‚ãµíó'^q¾üÁ:¿cñA>+8õ*®^,åHP]^ùÓÀGt&ÕÁz½áçÚÝðÔèafÓ‰×|&GVLjî=°âŠ«r¬8J·‡Û¥ã!'º.!ÂLC W>|5©ñ•ë’^É•¹C¨z>eºj¸hå³|罬¯¬aTeCð;¦­Ä“…´áZñœTÓ·øœ¬aâ0°:óðªÉr-L‚0 ãc%Šì¨†$zÜó®4ã¸,ÓÃøÁ‰F!Y~_¾ð4;Ç®nä½àâÖUûÂ{2?²« `7òÙ$ â0S¤zcÌ6T:Id¿\œ¡Á&^`¼RêGï›Üû4p–¢0QÕ­ì‘·,[~uMCÆ‘=Ü—œÓb9âÕ¯œp’÷á¯H°'©ª¡¯ñ“ïK¶âö‹ '½üÃs¥A¿²Æ÷@­ b™·]OC›«´A»Ñ´ß†¶;‡fÊ´@0Ä ƒ˜ƒXâá„?ðƒŠ/œt¢ÈÈ#™î3xÀPù ôøYwâ0!ì¸éß`ôDùT³*¹ÎŒâ à—Ó—ö·sz¤X{qðÔq,6®­ÉpÐ)‹/ÒË7Ôkœ·#=hFØt‡ÞæEÅKâH…G V>›P÷œ“Uå$ò¨””÷8ëEÂÚÄázâØW8Ú"¤Ä±íÇÜì0¢‘fºYÕ&Üó½Ûðþº,*÷Ý*@Oh“»¾7™¾Hô›Xn¿‰H$*öüäîH&!È´‚®R%#$û¶ ¹lZ}jƒÕuÈUáXèé3•êþBد †w;aw·ªÎ¯ZÒ&΄´Ðú ”­Ã¢ëMëݸái¿q‡}×z)Ož)WÈ8€Àh÷<,ýýÖÀMÞCÉV—ð¦»KùJX‘WÏ®O±Î®úÌtoýñ—_nß|ºýmùóíû»ãÇ$ùŽHR½–==O@?£äAĬ°¥¥6eþ ª/áf(ó35ý€Å ÓãÀ,ç­¶êO½úç\c‘ŠÏ{Y•éÿ6 ©ôU¸"ñ(éíõºÇ“ cÏæ{ÏîJì-ÉVìX7_±^tÒO´ H©½¼:õ»FŒ5´ð3<ˆ·ª›jVd7” %¦TB–Õæïºœw¯+Ôã5‹Eâ¾æ½®…ùïI 1- s’Aû‹†ÏâˆcÒb…7³Àʲ·’) ï4„O-=j/IÄÝy"ç` ‰{ˌݑ=ðúr-Fý8Ç·ªýö£òYùÂ޲q‡°˜ã\[˃{~§ºËýˆ0¾hx¸ªù-ƒûȺZówqå÷+ŸºAK„ߺã-Іcúñ79NJ)Ûöù¢YÆt£Œ2uâ]*²µ'ܵå†D[I½HäóÀã@ƒ†îø®„¯˜ìó<ŠAŸBn|üeBh¡Gu§w©*Ä$¹Èt`°rš¾&îÈ=ºÉ›Ô;¹(f”GéÀ7yðñfîµ)(+UÃuÐÿÂä¨ ^ëXËå0qS'×ÞȲ8(4õ‹¹'û†B'캛a̞ǰ3vþ.ýQÊ5O ¥'~ûpBF©[…]Ó‡ÔÇr¹¹Üóòt-†?ògÊßxRŒ5«3w:ѽîÙŽJ1¨âͤë$iéø"É­LxÎs„jÑ#›rœ³ß P6ˆxðñwô™7l”wìF¥ô[ÿpkÖžõž,_õ¯Ë|®ó Üôfødvendstream endobj 338 0 obj << /Type /Page /Contents 339 0 R /Resources 337 0 R /MediaBox [0 0 612 792] /Parent 345 0 R /Annots [ 341 0 R 342 0 R 343 0 R 344 0 R ] >> endobj 341 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.606 584.9108 522 594.6077] /Subtype /Link /A << /S /GoTo /D (Memory Leaks) >> >> endobj 342 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 571.154 315.4186 582.0631] /Subtype /Link /A << /S /GoTo /D (Memory Leaks) >> >> endobj 343 0 obj << /Type /Annot /Border [0 0 0] /Rect [314.0277 89.6265 518.9697 100.5356] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 344 0 obj << /Type /Annot /Border [0 0 0] /Rect [378.526 76.4758 518.9697 87.3849] /Subtype /Link /A << /S /GoTo /D (RC File) >> >> endobj 340 0 obj << /D [338 0 R /XYZ 90 720 null] >> endobj 132 0 obj << /D [338 0 R /XYZ 90 138.1487 null] >> endobj 337 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 348 0 obj << /Length 1945 /Filter /FlateDecode >> stream xÚµYIÛ6¾ûWøVˆQ¤¶k›hP-:È% PY¢madiª%îüû¾…¢%<㙦ÉÁùøø–ï-䈵ÿÅ:õ×±”^ªâxW¾™¾_ 3rÂ’|·zÿS(ÖÂ÷R?ë»ÝŒÉ]ñÙQÁÆ•þ9ŽYU57Hœæ¤tî6‰t†¾i7Â)³jóåîãêÇ;{\/ „$/I$|Ëj%ÊR…$ÖY¾AWùÒé›{üÒW85ó¦áœºf‚W@ö˜‰òòO_( ¤¯â¼Å²È¶•îp³r2þéžìÏy¡ùla0ì÷%îßóÚn\Ëú†­ö6n†ÎO›D9`8"*a¥îú¬Î‰Ôˆ‚³;&xDíš ¼v›ÃÒ¡Ï^:dHñÕAJåô°û qØ3˜ÚSµeªÀ¸³jö.Ýw†tfú0ôD"¤!­\³÷g¦*Þñd`…Q„ 5ضÂã‘—O¸§«Š'àxì-;´™!@ÙÊ®/óÎèÕŒiË}QeÉ<ˆ’8JÀ>±¥±$Ñ ©ˆÝP™“zþ yË?B‡·#8Ùg(jS3éøK'㎠Ñï¾3t£½“~ãÄ b•+F&‚ÜŸ–ìá0]Q"qî(õT¢QŠо=ctj†©rš7|ÐÛa‰_Ö• ¨=ÄÁU¥ñô'T’Ý‚®tqÄXk·Mg\Nfkh®@¨+:Œ>Õ— "|/Ó¬#åCh‡)f0-O²„¥s§„ ©â)CTã‡Cö2ôFRIñÏg›ÔbNjÊù ulömvüb0ýíz2¼TAù¡—Æ3Òœ¡zIüKfìü…†ŒÌ ᩈ3bÝÔz1†! |?0XúÕ„OaàÉÊà¿ë¼/ŠéªìÑËÇ<]°w”Dâ†L2î`|E´ã—kÁO°É/ãŸs:©€®Û0ܰ$]xFб¯CȉTýïÕç/þº}\ù`:°á æô¸’©A2~W«?V¿Ÿ½h9ºS– ~”AàÅ,[:Ô¶; A‡¾ ™axb¥I™Æà§uönôÀ÷é·SÊr|I)Äž 9W ó÷¥Œ*ðü0 ¿¡Œ#ÇeT‘ÃôÂðJBOi~s0±.®ÄVh˜üÏ9ºS–K î$MÏG? }R±Ï:ÙÂ[¹¦.E:…™njÖkz‹pâûQ{‰Šâÿ¬·åèNY.5©€FBÛaé®D‡H DI4Ð7“qäø¢ŒqɹŒ5=3\b"º%RRÃÏŠ“ûº9Õ¯ Ê(IEbàJÍŸ ÍQB5™ûì{R[Ù©;²ÍoÖ3)6Aí±„jiV¹ÑÚæâ€zöÖƒzh 𘦜Ä#u³‡r¼…ྡྷ!ÐúsõìIFŽx&·®ï«²>÷Íc-hu? Rµ›ÉDט1•á ŠÚ´ÇŒª6ËTŽ­5¥œž‰·ãÕ…úòf¿¿æÒ‹Ên]Ú·YݽޥÏö£æfqr; C2jAºÑ<¡ÿ÷Pšî ·}µ=ܸå\Ùi Þëz•¬8–o@)m38ˆE*õåôêuýqV {ö¹J¶•&àݬUg›n÷åú *å¤Ê`½ƒaÍ_¯;«S¢j&CdmC-c1î€ÝÅ9:J˜ó: ÜbµýÿµZ,ÎY†•x%Ät•=tºpûòøH”Šî. ÈdçÈ7šÚN ëõ³.ÀÀÎ\Ȉô¯%¥(ä°š{C¾ðK:H ‹äøFðÝuàJ?òº´ÌÝœm«ëþF"'ÓÓ 0!Eo1¿úPÖ µ\I.Œ¥®Ë—þ75\ðR5‡T~Ðù½»ÓõMá™Ë¯Î±èÜ›[nvϯaœnL…š¶¢áöõê5Èg1{«;?áûŒnËݹÐþsÆ5Ï4‚j{{‘q»¾EäãúÐêÛS ‹»­²úþfy§Võ?Jù¾ SÊPæ<‰AÌ I›-ÔôüqB^YÇ[¼Ô¢0¨_aøÖëcA?óÌt®¯tâŒÝ“äà›˜ ¶ûäI;áҿМð䍨Á”\à0‚ËÌmÏ/£('®5ÓŽ‹Cê4ʾ×5½j…ÎÏ;¦ïíëð+ͯ®3²Æ¯L8‘'¨;`zó*“¸»ÉÅP)b|íŠMR‘¹ê×RÏl’AÝ[Ì^ a8ÓKßuÖpgˆd8Š‘ èÇfÒ2ä|ª(( @–1-Tè)•,`z7Ôy÷&LG‘y`…AÖɭˆ©p·ã¥Ž¥Õ<‹ÁK· ŽCnzÌÌ£ÇÆ0uùÈÀöPüS 'dÝŽmS‡Y’¹œŸ{šûñ•}<0½ÝmöbšM[Âvíp•}Íç" gc‹Nv¼x5ÒsLÚýÙÓ·rl$p¦ 8Âf1äü—ÃÔ¦ÇÍI‹ñEÐÙx]ý…Jendstream endobj 347 0 obj << /Type /Page /Contents 348 0 R /Resources 346 0 R /MediaBox [0 0 612 792] /Parent 345 0 R /Annots [ 350 0 R ] >> endobj 350 0 obj << /Type /Annot /Border [0 0 0] /Rect [220.7274 637.4086 405.97 648.3177] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 349 0 obj << /D [347 0 R /XYZ 90 720 null] >> endobj 346 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 353 0 obj << /Length 3020 /Filter /FlateDecode >> stream xÚ½ZëÛ6ÿž¿bÑ/'‘N|èÕoiºm÷nŠÍæ‚Côh›¶…µ-Ÿ$g³÷×ßưCâ°¡ ˜ 9ÂYøíÀ Ù/™pyì4u,ªÚ2$Dr4öZ§ÿÆÝ nyç'g·z’G™ÒÞíx7K®SÇSDy'Žvpª¶tœîi©‚ð8¶3ói§ ¬dš<â˜Y8 ›2Þ)»‘[¢qããÇa,¤û_ƒ?½t°s<‘žJ®¤ ì7hÂï:²'$?c÷¸×IåYÝŽÁóŸ”2ÉF€’î&”2IPŽÒOˆŽãÏï˜#I—‚/yux’¸öÈtVQžäY+ͳàŸÌäS°Rr®ÚáJù8ãbÌxé=àå#Ð2‰Dª½¡à鈾±åôYóר&QsOëÃå½ÇPÛÓ,&‹{³+©‘qаÖéÛ<Š…KðoÀ¯à؈ƒ f½Ú6Åñœj'8¡·?Înî¸áêi &ŸcUä¡õã…‹4¬; Bë•s4ñò ¼œØÕ˜­QÞÈØÑ‹#¹*7ö¼‹©œàPµâ±T;>Šœ>™Ý¸¦¬h¿ìî6ÉÉPmCu0NKq s,o—4ì˜÷%9Å^óÍZ›©mR+Â¥]~ Œ´Ôì…¸ò@]" XÄ0w’ÃÜIޏ'SÒÅ19L¦dŸLHd¿Ê6닞̺ˆŠŠŸ½ÎqûmÏEz­p‰Í'Èf¾íÎ&Õè¦A–üŸ=;éJU’ž']ShR¤³<£‘C]îÛpg› ÔókÁo*·³?ÝlMª«?¾ä{YCV¥¥È¾Ô7,YÉ¢æ3žWt•XTêÒÔxnB^˜¡ó7”ö¸¾?n·*…¦K# ¶‡% ü.w».çsQûÙ™iº/IC{T’.T°2tÐGYñïÚº•áÀº‰Ý¡2žéî[ÕÕn2Ö ¾±8‘¬5BŠÆ£q RTïÞO— °éD{¯ÝíÌd"Ó(щO°«zšU¤Rå]º™×wOC¿GÐw"!ç‘éØä{ûÙÖamñj~®Í‡ŽÌ_.ÐpªËd<€ÔE×?RÃAf‚=­cDhœF%Ï݈¾ÉÛŠޱ㓖%§Õ,Èþ§J •wÒ ©4Gœé„Γ…Cº‰´èŒKè\iÀUÇI~â„ä_Z Èö@æ"’üõñWKQ¸r¯HØ÷†=ü®ÁœO§¹ËùpHNä|¤Q EDq!ÍùY8 ›ÌùNØ ½NÜWDZH7?̲,x…rß\_]ÿ<épIT@âï&|Ï¢W-j5¾àZ·Kîêì¯4÷ ÂÂå½ñpS¦ÍÇhsaŽ}ŠÝÂë\Ré!î’.õ„÷ú8ë2Ä×Xñï(wB"xV@NŸQĘ<œÃê(&£Â ·¨Â•e£k‰{øòàvKYÏä<ŽÓ¹£ß•ë’àé{eæßåüRËQ‚*€ùd²à’xµ¦&hÚ3%‰Ý¢'†ÕCð8Kúà r /ü¶ûEuäçÂnUZú3ÕE ãBŒ_˜8 ¸LI±cT:¯BÁÁŨõhI-ÍàôtׄqWi¦hÅx*Zuõ"‘H¢À­Ÿª? ¿V€êèþ‚ ÔP¦¯– žþœá£ ŽW‚¹:¾$’2D{ýöör2†‹µˆ³>©¤¿ú¨4v¯ëØ"¿!\ t÷3BFÐsÇ£ä¯É(ý„¯æÆx¤jއCªØYSñ•‡ ©c¼bòüd1ãendstream endobj 352 0 obj << /Type /Page /Contents 353 0 R /Resources 351 0 R /MediaBox [0 0 612 792] /Parent 345 0 R /Annots [ 355 0 R 356 0 R 357 0 R 358 0 R 359 0 R 360 0 R ] >> endobj 355 0 obj << /Type /Annot /Border [0 0 0] /Rect [401.0571 515.2933 522 526.2024] /Subtype /Link /A << /S /GoTo /D (Error Codes) >> >> endobj 356 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 502.7487 183.9639 511.9002] /Subtype /Link /A << /S /GoTo /D (Error Codes) >> >> endobj 357 0 obj << /Type /Annot /Border [0 0 0] /Rect [147.6002 458.5378 322.6307 469.4468] /Subtype /Link /A << /S /GoTo /D (Dumping Core) >> >> endobj 358 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.606 232.1215 522 241.8185] /Subtype /Link /A << /S /GoTo /D (Memory Leaks) >> >> endobj 359 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 218.3648 321.6033 229.2739] /Subtype /Link /A << /S /GoTo /D (Memory Leaks) >> >> endobj 360 0 obj << /Type /Annot /Border [0 0 0] /Rect [147.6002 148.4585 322.6307 159.3676] /Subtype /Link /A << /S /GoTo /D (Dumping Core) >> >> endobj 354 0 obj << /D [352 0 R /XYZ 90 720 null] >> endobj 351 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 363 0 obj << /Length 2936 /Filter /FlateDecode >> stream xÚµkÛÆñûý . 0î‹sœsƒà\§öEa(¢tĉ¤ÊGÎþ÷Ç.EJ¼“‹:6`퇳³óž¡Å*„¿b•†«X© Õq¼Ê««Ð‚®„]ù€áOQ~º½úñ­+i˜ŠÕívFävóÉÓzí+¼Ÿ«l¿oÖ¾L¼`Jy·ëDyCß´ká•Ù~ýûí¯W×·ãqFÊK !Ê%Ž„Žƒ( å*Jt ”6ÄW §úF%^·ö…×ð:«ñ7õжuËŽAmqÖc¯iûbÀ;a$¼ÀxïŒ”í»†Wýýz„¾¾¹y¿†[ÿóô‚:4H}ä nðŸ«O¿‡« Üö׫0ÐQ¯ñêT:]UW*±LÜ~õñêïGyŒý)É¡è0EÉ\(o?\Û×g|ª4HÓ$úŽ|:ŠùÔ:•™³ù·ÜÜX×Àï†5õúÆGÆW¾L£@ãÝ|¡aB6Ä't b˜8«(†S•üßw)úS’K†'A$¤9ýŒ$(LÅ‘ú~|Ž/ñ)AŒZÈxÎ')á”IЖˆ#ó™t/2©“óøEù½ôõ|÷¯$X@1{}Ñ÷%ЮC`ê•°®q™x=,ï ^ÿ¯ çÉ™òdÄ"UÀ&žÔ­]Ü[äs&Æ;J‹û³ð9zoè†åÈæ=YõÎ=6جŒcZÍÍzSl³Ð÷=ÇÔ;ŠR”0eHðŒ¯M0k1ÜCJGYóŽ@?ˆ ËMc€ó øU¤¼·ëTc€^[῞mq­A\>Ë |êµ ++ñÁz¥Æ‹ï†–i•~kFxK»}±$CH=" „L±øÓ×5D»Ø:;/3ûš9½H„•ü o;Á³ž:J+Œ5©}éshBÌxD;‰•¾¬ &”7t#TÙÐf=ɺftR±Ë@G0ø+hÞä$ûB¶§TØ1å>Û¹Uc‘› z‡X5 egqš-Û‰Ã@ “žÚÉò¾c+é›äøBc#w¥C¸õ>Åyc‡˜¶2Z“b8!€éñÃ4ôY<ЏúN "‹¼'Ù!‹:мøôó„uÍEƒe¿î~ÉH´utDÑâôÊÈŽ³ ,Ô#Þ¥ œÄ X3zŠ 1 lPƒÛù" "§?ßß^/Ÿ’Ail|¯¨zÄK·¼±.¾+ëšì`Çà¡+ZÒ#ŠD ô`3/¼rh›]Y…{ §ãïóf8°wжÙòS¶G„ %kÏ€rô‹†qËž]yead¡ âÏÜ@±ÐBåáÌꂼ£ "]Ö~eðQZ^¾ÄfÍ4 Ôñó||:óÊWKÁcM[b­jr÷åÈNÑ“µuÌgw#qòLAÒÊè(¦œç¡„É7íí{$Ô|?lœšuÒåG¿eñøø¯-O»žßÍ‘ò}A 峨…1ŸI)cÏ9ßlötœÃ²•ê+œ+jßìvLEKÖ’&ÂVEÄ!šÒ]°$ãcâQG*rÄ/‹ŒL­ÜT„ú&±õ,'4$È[TÃ`7UY—༙ˆnÍè*øC‘Òõ¤'’3’ÚÂRÌê #7œb1µ-’ëÙ'#ébò‰­;ºØ …“ -¤·m º‘Ýv¬_@e}ÿò¬ŠM9T—EzÓàá£Ê¬·àæ×ì?=CÐÖ^B\·úKæyÔ¬!вýrIÉPèi#]ùÓ\uBaXao•‚¡ÌäÄ1TÙô‹ÍYß>ôú!œÓàVO— ” LÀTµ1R¡y¢tñü)âR¡F¹~sŸ¡ö6îpáê‡jêp˜~CÕ@ ̪±~‹eÎÚßHJÆÉì ÅÈwé ç§ÅÃÜ«UìˆNÝú¾ÜÝ_vêwàü³ªI™¹µ-œØ­cÙ­wüã<š%€ÿËGå£[”}_Ô6†‘kÓ‘6Œ9ß¡õ~âzYŒvàæôŽuöãk .ý\’iHãoÖRq^Ù´)¹½CM·^ˆÄ?”Y@b€Äî]´bÐ$RìiªŠ<=å|<Œ¹˜êשۧ·‡·¹ƒr®¯Ÿ¸>@Cƒ£³èþ'¢xÂý 8x˜œ¹ÿ¤X]{Xfœøº&.ÀÝ)­}ƒ»+i! Æ“J¥~ÂÝG<ЏThŸü³ÝÝÀé „=eliôhÑ.]àŒÜèë<®ÓBÏ«M¨õ5—·±u±/k.ïÐ{†£íðN`Z?é²Ê• T¿Çé ‚ …`p”ÏÛ|1¬ˆÀè±!þ²M/’Ø"ÝÆ:€bè7(¹QĆ"¡‚ïØ yx!k‹ÉýGïj¨^ÝmìH$ÆRªyN2–°mC®î–w\êÔ¼±îLþN±#C†’ÕÒØ»EßÐ"!27Ë@†|ãÂÆlÀ1 ûn¾ƒØ%« —‹ÊP!´DB8OýË/ïß]ÿ<«“T@:¿°:^Û€>–¦ ¶øD:Ëç¡ Õôô¥#qB¤"11ƒã rè¶¥øÇ’rQMÑC,yÒï$H}^wOJÝom_ѳ‚^Nj; ™ØpÀîkÇþ_ñÞ–L¸´½Pyd`öøhŠjL2€±‘¢n«-ò3¸¢õUèÝc)õ¼‰¿u±sê Ø€Nná&o˜“¬´±—ʧº°-¯ƒºÛuÑR /Õ’?i¶¯–ý9HŒ‰æüAÇ¢ˆ¤Á‰OQ Æm¤ÝA°¤l‘àeëÁ#—RÍᢣíhŽn¡9 #h4ÜØy£í×6 |,ANøMAtM\,ezB=d]çjzÃçæ¼¸žº9Œ‰»â(öQCåÞ9DPs:hû 9UØI«Uû„*D¨Ñ×ÕDxFpŒÄŽöv¼Ì³CFÃÁ½+Î Üó2qš,fîXBŠcˆE!$?•¹ž?E\ÊÜg—27²§ù‡3·m|XFz¿ÑÁ&o;wLåîRºZHéBFôì1D°(HÍSüˆæOð–¦—§äðü—g‡*«õ ±¥™©C»tè)¹?yb ¥ Ü1¹ ²í÷gä&UûÐ"Mæ‘æ57Ò{JÊ·ÂyfÛë1J ÔÆÞºt5ÑØØF"º¹íÚù牚( â8riø³Pz±‚LO¿æ=9Ù8‘EÍ´ÌígÛ{pfxAÌP ãRXÃE]|éO¤0nŽî(“„ÆÂ$ îƒlêŸ~å0Š–°( Iœ8I¼ø1ЫµÕí}96xŠF¡ˆ’C5©,ôØ%ŽÔ”WîjJ32ûf2…|tãUw+. ýd(ÉÎÂ6g,(i")æ¦÷KánQvãlóHôKV&¹~œ>#MŸ®á*èç+;þZ(悽<´†+H¨†““åÅRçü‚S?·J9oÜ”›6P±lKúžEáA[Ì{¼¢ÿ!í'\Ø„Ë)É}y×âÔ~‘ ÄXŠmÈ„­º™PÝ¡;-¨›ÝD„!/gäô”Ü]Ö•ù7P¤‡ÿk‡ qÊíw}Öw¶JÂ=œããhÖ‚òû"ð·EÏ\¦jÚb$AGÓ†f½¸è'sž‘Ž”ŸãR~;—êÛ¬v(.¨a°ÿ/bþ}rendstream endobj 362 0 obj << /Type /Page /Contents 363 0 R /Resources 361 0 R /MediaBox [0 0 612 792] /Parent 345 0 R /Annots [ 365 0 R 366 0 R 367 0 R 368 0 R 369 0 R 370 0 R ] >> endobj 365 0 obj << /Type /Annot /Border [0 0 0] /Rect [179.7576 594.1689 352.0911 605.0779] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 366 0 obj << /Type /Annot /Border [0 0 0] /Rect [276.0852 452.6032 461.3278 463.5123] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 367 0 obj << /Type /Annot /Border [0 0 0] /Rect [325.1154 406.6651 510.358 417.5742] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 368 0 obj << /Type /Annot /Border [0 0 0] /Rect [372.8977 297.3785 522 308.2875] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 369 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 284.2278 126.3637 295.1368] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 370 0 obj << /Type /Annot /Border [0 0 0] /Rect [133.0303 284.2278 305.3638 295.1368] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 364 0 obj << /D [362 0 R /XYZ 90 720 null] >> endobj 96 0 obj << /D [362 0 R /XYZ 90 645.1153 null] >> endobj 361 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F72 9 0 R /F55 21 0 R /F54 56 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 373 0 obj << /Length 791 /Filter /FlateDecode >> stream xÚ•UËŽÓ0Ý÷+"±q$büÊ‹%0³`5eÅÌÂMÝ4jWI ôï¹×vBÛ©¡J­}}||Ï}•G ><*Y”KIK•çQÕ­X0V<¬@$—OëՇǔGœÑ’•5mƒðlg~‚ý`ëAw€©ÌˆJã—õ×ÕÃzñ,â-ßrÇyqé<ÏÍx.¢¬P”K•: ÕÞT‡dgúʼ' –½ÑÇ`0Ã`‡Doì0¡kQ¢RZpx'•Œ+Gô΃kk·~uB¹ScFw ‚Ë%å)ó‘ۚͩ–6–2ÒÚ:'=áAÜ÷¶Ovƒ1¦iÐý yŽwñå’ÑzÛ5ý•¤Š ¦«J*{<ß¾±øž9vt+Ù´º?üW€(¥xz[SH]¤i‹ ÒRú´<Æ…"KªÄ•×oÝa­µn+–‘_¸v%µ÷Høå—¥$zãŠÏbµýŒEáí‚<ƒCmX7=Ľmý%N¶q Æú„öäa•î?ZÏGGl‚š«"yFYj˜O³k‚Ê׺Ë9¿ƒBP™ó%½›f‡BF·™ÐÜôµ±Ì%•E!®3ß$+÷=FdØÏ¼¨¸…ΈÆu£Ý9íЂßf˜¹mEÁ-Ó2ÒLм€dA¯w|Ñ .¹Þ™(¯ ïΠüÏ›¹ žp€g'/>‡’+rÔµñùj¨È"ƒaQÊ+%w&Ë‚{KÉkBWô>¢ë}3zOLu‰eöÓ>¸ˆi°uùuBíÎçY”³—=ˆã¢§¦BÉ8°À<,ZG„µŸ¼ÀåìhrseIðÖtn×ÙáŒ}èt¿yCWU…í´ÔQ…evð>p~g7ŸãƒÎE“à·o;Nž«3.cÝ ÿzp÷ôèfEÄhW×£á¡E¹ÔÆ”Œò‚÷Z¦ª¹×€9£þüɆ~mF½iÿJÇAq-œåbfOס_B¡'×&4Z(Ç?Ú¿Øäendstream endobj 372 0 obj << /Type /Page /Contents 373 0 R /Resources 371 0 R /MediaBox [0 0 612 792] /Parent 345 0 R /Annots [ 375 0 R ] >> endobj 375 0 obj << /Type /Annot /Border [0 0 0] /Rect [202.9597 560.0623 386.9493 570.9714] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 374 0 obj << /D [372 0 R /XYZ 90 720 null] >> endobj 371 0 obj << /Font << /F51 6 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 378 0 obj << /Length 122 /Filter /FlateDecode >> stream xÚ3T0BCKscc=Kss…ä\.¨p6—!”¥ T¡‹¬Ä)„KßÍÔPÁÐ@ÏÒÀÒP!$ Å”h 3M]cC ÐpÉMÌÉÉ×Ô5²ÐHŠk„hZk”–äijd&æhƆxq¹†À­352Âá ÂZ%¶endstream endobj 377 0 obj << /Type /Page /Contents 378 0 R /Resources 376 0 R /MediaBox [0 0 612 792] /Parent 345 0 R >> endobj 379 0 obj << /D [377 0 R /XYZ 90 720 null] >> endobj 376 0 obj << /Font << /F51 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 382 0 obj << /Length 2737 /Filter /FlateDecode >> stream xÚ½YmsÛ¸þî_áé—P3'–¾ä[ÎuRßù’kìÎMçrM)‘²XS¤*’ñøßw_’é\š¦LLrñ¶Xì>û,$Î#ø'Îóèá¶xOÅѼ¤ßñAƒ~"…ÌX¿?W˜(Ö0¿{áǧèFØý¾1-öèh h«Ú˜¯7#QEØyÐz–a‡A1Kø}ØâG›…êv!sç|fÑž¿ÍuËÏpÄ{\d½ipbÜÙyé„hË*:b×^áŒEÝþze™Ÿ¤®Ÿ‰ ©Wè%Åáq‘Åa–%Á­×þœ¢¨îyžÂNá34¦íx×°'1Õ„—ŸQÈ—þ•JìÆˆ5Kó |\×+êRp5ü;?¼©lUFF3T`¹n¼²ØEï8£Û„½t­&’IF;tääåËÏm Vù—‡ýŽóÍÞ’yôt±o¾z©XÞ£³ÛÔ" ŠvmÑ1 wœ ‰GÆÀ#͈¦æ (žá»tIÎí¤G5I ~ì‰)L•]ôz&¸½« ªßŽ/OH´µ§‡øCGJ´À]$`5ù,G± Ó$³©êêííåû·¯®?þtùÓ»÷ûxóó«‹ËyÓ«0×ÒFgYÑX ·bݲzS fói5I ©èÓ¬ZÖýl¸§qk•¹ÄÊ:@™U’ëcÛy$Tß8ÅHðå7ÉCšÛ'©¤3ÊÖt·‰YR>¦ZÒ\ÇQÂ’9Æ÷rç§ ê:9-¢k,ÄTæHŠH~Ž}µV†Š7xΪ=ã{r¨‰ôÊT{ú¥ñ©N¦ÙK`î·@콞è e2UÓuŽ¿à®æ×ÄÆÆÊ Þ´¿émÍò¸Y3 q\Ò^ÖÍh(N:Í¥%þŠaï®x+Ï\sA©ãØÖC/^Z¯„`9¶Ø…©eèög‚ …L{MRñï^ëóêzrV¼xþ7ŸÔ¹dendstream endobj 381 0 obj << /Type /Page /Contents 382 0 R /Resources 380 0 R /MediaBox [0 0 612 792] /Parent 387 0 R >> endobj 383 0 obj << /D [381 0 R /XYZ 90 720 null] >> endobj 384 0 obj << /D [381 0 R /XYZ 90 720 null] >> endobj 385 0 obj << /D [381 0 R /XYZ 90 658.8294 null] >> endobj 386 0 obj << /D [381 0 R /XYZ 90 413.7069 null] >> endobj 59 0 obj << /D [381 0 R /XYZ 90 197.6298 null] >> endobj 380 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F55 21 0 R /F52 24 0 R /F60 81 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 390 0 obj << /Length 631 /Filter /FlateDecode >> stream xÚTKÓ0¾÷W䆊׎ã$â‚x\¨¸IÚF›&U»]¡ýïÌxÜÒJ•*Ñ:žÇ7ß7cW¾20"È”â&ɲ Ü-„wß/¤·"ȈÎSÞ‹»ZRp#Œ ŠõHQý`IFJ‡½ÛÙ¶íÃ(ÎY >¥XæŠÍS?„’5¶ Ÿï‹S;Ç·aÊ-FЛ§BÄAš'\ªD;^_ë¨É~c[¨‰ÏkbÉN° æõ4ßúÌ ôDó\BoÊ|˜‚­Aè4lÚú.6Ù¡N™mZ»Áí1‚êË0ÎØ¶k7œ¡!œ}Wö»}ÓÖaà “¢éì„5}7ò0J”`ßq¢ýL™;×ô‰Xd;ôLä™zÔDiƳLæA$—ZÐÚêƒÝas„ŠSC”жãˆáúÄ¥}€ÆÕ!·åê_úÕqwØ”%?…¿|é4Î{(ËX=48>¹aôŽÊàJRøÕÔÃx$Úw䯭TiÍ“X¦~S¯®-Óð8KÏXÞú†h¢’¹£Ñ©4á©Éõåì ‘Óò•0pÚéá¬OX(ý j·¾”}šÈïá´û +ònL§'´qÕØÊú Â;Žß…Öän™G?ò[Í8´¶r;öŒ<ö¶îRÞ{ Hf¸ì,™wФztøÕç”óÌS /ÐÐ '¸½p4.z õ’~¯Ý„áÿ&N¹R¹‹7ÆíßÏÇþÇ9ïñ"t Ð7ô³\‚òvjº%=쥭ª¡GwèÔ;º õ|×Î6ÝR;IºÙÿÿ”Ï[‘endstream endobj 389 0 obj << /Type /Page /Contents 390 0 R /Resources 388 0 R /MediaBox [0 0 612 792] /Parent 387 0 R >> endobj 391 0 obj << /D [389 0 R /XYZ 90 720 null] >> endobj 388 0 obj << /Font << /F51 6 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 394 0 obj << /Length 3740 /Filter /FlateDecode >> stream xÚZëœ8ÿž¿btZi{¤@° òeµ›}(§}D›Ù;²ÑÓÐÝhh˜:“Ù»?þêeÝL¢;EJ»0Uåzüª<ê*‚ê*®Rc¡ãò·Ûþ8Ìv,™æ_'ÿqbN>±'ÙæMSƒì>¿ ¢£¬Ê„*‰Øzˆ‰4Ý‹ºa•= =ªw<à„Åïê|ó((uYÏõoEÿ߀We²©‰¥‘wý7OVõx¨z‹œda^N˜D}u'ù^ïÎ>EQQ) ¯ >˜i÷<Õõü±±¾gà[ÄT1® ?} ¼àš’ñKõ{œÙÜÃÀ3¤÷6V1v »ÛÐÆšÍèïwFx°ÚnPuu±o»¡&ŽaªÀŸôRÏq>£cØ9’þïRjͤBU4Ä;è#‘Xp’U^˜NN›Dé„G>z™íѰZÌó'&vþDaútO’^ô™bÙ r’¸+~ø œ Gн²_¥ÀÇŽ¿=M/å–ßâS¾N€Çº)œŠpe×£ãàh„ÙƒÌد`t_ìeTŒüûÛ¯?ž‡®€Jtz•äYˆ¿ <Àò,~yº`NÈáYÏcÉ冨Ã8Þ¿|ñ¢$ñ¶!¸ü‹‹ ª²0·ù9'—‘ÔÑ­p²ˆj—"'l¯©ì2?·7x2ÇÉÀD±Ø ºÝ8·fH¿G*þèæJž+Z7àŸ¶zà×û C’KD0±-d›[:l™E?8Ñ×á*yò–,¿Úu½§¢‰î¾‘‰ªÝv'ŠRS„­Gï€Çлf™1$í?%,ÎÏ„¼ ¤ìÂìôeW‰Óeæ¾ïö}qä‡þÔòê Abhº‡¯ÖRJ£0Õ‰•|)>qC%ÉÙiHÒŒÈáû¢äg i´ƒŽçŽEË¢±)öài%‘O ð|ôÑb:ÜÌiŒ÷”ýê¦Y쌰£âÉŽðG}¬ÿ¤–/ì:y{¸/¶³íaz%÷̆X¥2 o¼ewÎc¹ÞÔãÀ;Çk¦yê+™?N1ž(“ñBÛBr‰é¹¡oð𤘤$*Û3#&ÌâóÑkv¥vOæ¡ËIò> ™ý¶8 b#·EYí d®Q´ÈåLXYxn®&tEN(üƒ†}âuø"ÊŠÇŸ;žëY16팲ÎT ¹š`œŠnýÈ‹lŸ`yL2åÞB /‘Ãâ®gçDŒ ô×YÌðh8šÃ`i\ÈŠÏÍ0&LuK'ìX`ñœoñÅ»5éÀë+wä`Õ:1•éÙs›LؘSBóÈô·¸ù#S{‡wð FïÙ"d'Ih08³eõj\C­#gýÝ=ŠM*¤;þª;"— ¤ãx„Ë‹XÍ i[eT·±ù^˜ð—rðˆ ³`ø²0Ž.˜®À†Ë תL+foh%¯wÊ¥$`ª°žôî­6ïaôå7‚ÔÄ$çòiˆA€Ý²«8±ažÄù°ÈÓsÂù.7dXÄPÄD>|ÄÔiäk\81vÇé§Ì%R¡Îœµ0„­Ø‹N Zzœ1‹–ôA„Q8X°Ñºä¸XÂÓ cÐ :móå1Ü¢c¤¢3.Õt–ø°ƒã]1Œ—ã‘äPB¡ƒâ¢Øìš ± ³$ŠE†cU֧㚬& ¡èwt¤/6Óa«Dh=­*-š§#¯´E{ Ø-…x/)79òÓY$Å©B^=-{kœ9¶ðé…&9¦¢nfÀƒôÀCçÖèHƒ@çP¥Ý{…”PÊ6\)ª·é8÷9CõÈ#†_8"ü4òxËPÈ”WHøåʯuñËý²•®…Ø·ÕEpQ\$±LJÃ$ÒÙÁÅÓsÂç»Ü¿ì[,U„ï~E^1(ú¾öű®Å÷šâøœw塂ؽà}%pxºÏñ~¹á¬žÒÊí Éî­0 )0 ÁxÝ>ØÕTá©íF^…ƒ,OÛJšÅntøñ5¯÷…¨ñ¬NY-FÀ2Â(ËÔ²Ñ&¡vÔ«ÅìH†G¦êz% !l—¢ö4lĶ…SHxD—œ¡¬~‰’©o Øø å²»ÇÆk=3×›IÂ\Åù+Ä{6Ú|íB»ÍfÁÖR«¤âÑbz×53ÐéÊ.ôyk>12Ž¿>ßÃîõèÛ¨¸T·—$¿+ÿPcn¾ç9LücÑUùaŒúËWÜzJB›%æ¬÷š F NhVj,Çq ±åÈ£ZÞT+ûd§ ãïJ€²¤£¿%c®D “P¹… '•féQÃÓsÂ5Ï»Øp5+jæõ0ÇJÜóÊÛ‘ò÷è+Ë÷ϧ0Ÿªó¢Û…³±P$B@”'W&ÖáÓÅ“3º5 r¾Ý¼=cÃÄ5Áh5­i1ÚßðHó\=…@l¦©G UûaÕ÷Ó0Ï|.]OÊo e‘@‰ºŸØ  ”…è Eéh#Ž!‹'f;üÎÚ’¸âÛ’,·k§‡JŠºŠQ£ÏŽëóöÛŸ¾þñÇ_^ýñË››×¿üüvû BDÏ…Á 1¹ô{êÙÞbÆI©“8Gq>#wÆ_ =?öȸ¹ÑÍí ZîaHkó°F…–ЬúöWpÒ`E1rÀ´àO¦g¡ æ„«éù|Õôl$=w-Ì®òO4Ã"±èëâö2{s·oJàÑEI³0‹lºn-;ºÏIw¹á<"×d–.gÄå~ºžÙ,ö¥¼Í⃷Y«ÍÌ¬Ö ü«LóvÙICØSâ6¨Hü¥›ì}ÆÛR-k©#Gu5?̼d5P©é{P[¼UÃ+Fñž ÜUšJéý“€f’Xäë²jÇU¼q5N“P%efj‰Ñ] MèJíŸÁ 6hïBBõÄ´CØHƽ3é÷ÀyF&ýœØIN]ëfvq‡szOòh´ãŽŸ­*|‡Ǭœ%õ©û"†à¾F} ·ù©ìÖÔk JqÌzFˆ·ûAjl·¶0 õ渆ôJ<Ì KŒKÿYû8(ÐW~íûJ:Ûà `»vÊiZ¥Ý¦T²¦&ÚHOj3xTTó` ÇSW•+ ƒ:©ÑËû6œXì ŠÜØú>˯˗® ‘‡Y>5!¬t,‰ýçX…73nTžç/¢ì…–bCé—&})~E>2ÝwE_¬Wñ8¶S7?Pi¢¥éC¼*%àÚÏúQ®\—W'úÁßskŠ®Xã(ó–c«†¤Ã]×]+š"Vʽߦä,z“§\;kc\˜<ŸNœ²øujáFéÔ©+Ú­óâ¬¯ÖªÉ ïCmò=¥:RÓ`;Y¹›ÃiüóƒÉÉÆ}Xð>Ú{èÐ |³èKô&]¨è¬á óØ+é?H×{/#ÐÑð%qçÚ†¸XÖ³½TÈy؆³®G&aÌ# '¨uOg¨&ðãrÞ6{2¤cu8 eÚNÞõàâëÍ[ynf78YKÈr?‹æpcŸ¯‡Gi ðGSãßY´³qbÖ¤Â-;þ]íòÒ ß>uè/´ßÄø™UÙe“›Jáéð.Œkà¢IêͶœÿ¥ ¤ÏCån[Üý^íÑuCîÏŒ§ÖŽúS˜ˆÞPÒœÛL»8CU5üv-ævãS ßa÷hëRÇúãZ`Ì ÊSå¢ùápËî¡Åë?º°[k]GiE.ö;~¸Œo¼È\¢Õæa´¬‰e©\&KuW"h×ÎrifaOÛ_<â´|®™](õìo(Ö¤6i¨Œv)³úXŸ’Ôdan|ͳ¯È«Á¤·ðáªéÒHK°˜µºÇÞô3“ÿçSdb;HmómX“˜éoy‰e’‡ÕÔ¬ÃÜÆN½êÚ±ïšàÕj– í¹£$VKjARú­­?òˆ/§’yå…åå cwÏK5ÿiXUârà`W†#ÙRTÈLdÉiê¤\98lJgñÿi­¼Ý«r5ZI'0ØWþïŽìŠ]±§É„ÔˆŽúfÀ3þ…Ò¬;‹kRéqVg'×i¶ N»ÅPïÛ¢awåðQ6|]Н¨#OÁyµ“éíë^ÿ|óëšôq ®ÇsÐegò‰åä<çÌr¨š\V®òfh–$O²å-¯-šÿ ŽéŽUçöìð·Å¸=¬Õ?µƒ,Ê#uÞÂåïWšIQB‘“Ó]tdÔS½$GÌèV›¸gÛ­¸±¸ßV·'¨ûoÈ\Ü•Ãûç™jXuy;Λ¤ñœû•Ö“}†û‹í|‹ý/UN8iendstream endobj 393 0 obj << /Type /Page /Contents 394 0 R /Resources 392 0 R /MediaBox [0 0 612 792] /Parent 387 0 R /Annots [ 397 0 R 398 0 R 399 0 R 400 0 R 401 0 R 402 0 R 403 0 R 404 0 R ] >> endobj 397 0 obj << /Type /Annot /Border [0 0 0] /Rect [410.1527 596.0106 518.9697 606.0106] /Subtype /Link /A << /S /URI /URI (http://dmalloc.com/) >> >> endobj 398 0 obj << /Type /Annot /Border [0 0 0] /Rect [474.9609 467.9843 522 477.6813] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 399 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 454.2276 279.3798 465.1367] /Subtype /Link /A << /S /GoTo /D (Dmalloc Program) >> >> endobj 400 0 obj << /Type /Annot /Border [0 0 0] /Rect [166.9941 414.7756 309.1155 425.6846] /Subtype /Link /A << /S /GoTo /D (RC File) >> >> endobj 401 0 obj << /Type /Annot /Border [0 0 0] /Rect [383.9161 352.4514 522 363.3605] /Subtype /Link /A << /S /GoTo /D (Getting Started) >> >> endobj 402 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 339.9068 200.1095 349.0583] /Subtype /Link /A << /S /GoTo /D (Getting Started) >> >> endobj 403 0 obj << /Type /Annot /Border [0 0 0] /Rect [169.2004 296.6082 378.8067 307.5173] /Subtype /Link /A << /S /GoTo /D (Environment Variable) >> >> endobj 404 0 obj << /Type /Annot /Border [0 0 0] /Rect [300.6239 76.4758 472.9574 87.3849] /Subtype /Link /A << /S /GoTo /D (Debug Tokens) >> >> endobj 395 0 obj << /D [393 0 R /XYZ 90 720 null] >> endobj 396 0 obj << /D [393 0 R /XYZ 90 720 null] >> endobj 392 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F52 24 0 R /F58 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 407 0 obj << /Length 2082 /Filter /FlateDecode >> stream xÚ•X[oÛ6~ϯ0úRˆTQ¤nO¶n@‡= ˜‹ah‹Ž‘d[ˆ-U7ÿ~çBÒ’£¶X‚D¼’çúCŠM ¿bSÆ›\ʨTy¾©Îw±~¼¶E8'ùyw÷æ·TlD•q)6»ýb“]ý!Hãm(üoÏútê·aRŒIì¶… &Ó[´ú´ý´ûýî×?.M’1„$?âH¤2JŒe…Š„T)ñ•EÛ0ËâàÝ~ª"ž·ÀW? Ø+‚'àhèƒ>s¿ù 4‡½ž€àdÚ>žêíÒÞa°AB”낼”i*7«i´Ýçâ—wÌYkx‚ƾ"©ï· zØ£@o t²:ÊŠTnB!#‘Æl‹ækk>Æi Â.ZhJæQžg¨\¤z’elЈ*8kÔÒ3vd€ã½áö™µqúÀ!’Œ z"ÎkhΕ,‚¶…]3Ý¥%îé€/ø¯áÓówpZûÓbþØ8Íb·©7yj”s:Éêqk©œ©]£“¢`W?UÁ©}@ÐÈÃ3Uºc©šýD2<óÐÌP< »š—†üY`G»?xàöÇX(¯³ˆ¹¿3.ÙsëÀ^™‰,É@èËÔ¹ š€Oøox•‰ß …\ó8 ‹!BØH}õùÔ>F›ñ{Î!©$uÞƒ2¯œÄ‘(d±rÀÔ퇦©¿wðžDiRÜØ—@ô­É“GI ñò´ê¨»Ã÷OÀk’ eWY(cð‘Ö;ceÈè0H~§Ëdï¤0ˆF?Úö­3ÁÐÌ- Çn”ä1ûÄ©qξœf2s:Ȉ»¿ú3,OTÊ8óìÇ4g>cÍŸõäl´“.®±ÓaP'JÝ£ßû¸MJ@횢¶»tLÞîùk‘”W§Ñ°9¶ö´â‚Îßã&Ã*‚IQDJfÒªÿGØzúÕo¾šAs¢ôàk΄Í3õÎý`£øŠu°Ü³Œ¿ô‰FûÁ4µ5N^FI+ࡌDRHâáßUñ¢XÆN¸w|dÝw¯ Ÿ16ÃËOÛíûá¬MÛwL¢úÉÌÙÒt}Rqõujô#ù¹àUçEüiþ•ˆÊ2Ë,S¯Y¤¤È!®³|©×¹s" »ÚÊe¤¹$AD?q‹\ ÈɃÓ'ôk§Bt=Ðý-‰\Q0¯"Éq7È⦚Çnæ„"xÅËiðªX@ÎO‚cÅYHÅÁû.$ ãe$-ö´ž¡»Ñioé$”:´qæã,hi}~„¶E…YjCŽœÏ8Õ´Ú\í†ñ~“;NXDt.uàæ{*œH6p :òÍ2ÅŽ#¯”Ö2Øò”Ì)Ãñå ©)´á{ í2·jYy¨H©ÜyºÀ¸–b™Cf‡ †FgM¢øÌÕèQeTdª\{t\;)Qª<ék+Pgepúèo$ÄòŒ~aù´l Š$O!*®(ÌQ5 Åêž¿^_dÉa–úmVv…b3[$ñú-UäaP_ 3>º‘|‚zô;Á7±°?Þãøž`®"¸°¹ÀbTšCŽ“ÿ‹Q\¾Ûʽµ§™†ÎóeŽÖk›a`]¨àÕ|$¿A»à9êÑÖP½óë¡©¦al¿4¯V*Žó"YdH¨Ë0f§W%Fëh¸E!ôh#ë5UÆì}u[AÚ%æ¨ Ïy b=žæ§ÑWþDÍvÄöÛóµìõ5¤?ûÁ§}º´†+»ûØ£ˆb vµMô’ ðo)O´qeA€§H$nÂ2’R·§®Gî{ÇÌ2rÉáÙ×ñHÝó6ÓØ¸å¶ñ²VÎfåͳåĬ‰ÕwUC0¬‚?)¬´/â%xk3ëøÚÉOT.ƶø½–ð;ªRô‰ç5ãM˜Hïs ©uä¥{vÚÞîö-¤]“jq \—øùt-wwK€I2'bË çzRVÍBÍ5 •¾½BýåË—Û[³ü-„•¦Q^Æ^‹!ŒhzvuötáœpåþürC*8g`QFÀŽ ›~|€ö{2ç\œ¿ÑÙ銶;’ï}º·HC‘—‡¥*ŸôÁBIRÜJˆ¨Ìd¹Q*‰2‹o<xºpN¸öBðbCdÁÂ¥Ì"¨*s—Rløj©+<€M`”ÊlLz=\à%ì¥ï‰.ôŠc«[îL‰Ox‡#ÿ¡R¾æó—õ:–8•žT®[~4˜¥òį.·Ž|9Ò¥œâ\ÎqJfÉâç‡J~ä ÊUhèLXap‰[jHÛÁ«U<ÐÖü™Õi<Ìåß8ôhnÀ0C®šhM„wƒeæž^°9QÒ½´dÐ'dƒï­µ±³–Ò²»«Á0_¦WıcPL£­åe£åaôºfrlwµ¿„ ×f9试ì÷k’ýyöàô4Ïó³·—Óóð —,¬#Ø\”Žî-†Ja˜jí»PíÓÓøªx =¹&òé¬}¢ÚÚ>„„ªHñž„W†PªlV[)|#F]eÂUq5”BëršA·M…Ô<õÀÒáŽCå‹-8 ¼jÏLÂe:4ˆê4Õ×%zíš1W×A¾H¨žÛ:ö>pkVW+EÆÿêN‰endstream endobj 406 0 obj << /Type /Page /Contents 407 0 R /Resources 405 0 R /MediaBox [0 0 612 792] /Parent 387 0 R /Annots [ 409 0 R 410 0 R ] >> endobj 409 0 obj << /Type /Annot /Border [0 0 0] /Rect [354.8113 453.0636 522 463.9726] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 410 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 440.5189 183.9639 449.6704] /Subtype /Link /A << /S /GoTo /D (Using With Threads) >> >> endobj 408 0 obj << /D [406 0 R /XYZ 90 720 null] >> endobj 405 0 obj << /Font << /F51 6 0 R /F52 24 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 413 0 obj << /Length 3781 /Filter /FlateDecode >> stream xÚíKo$·ÇïúºÃ÷ã¸6Öƒd7ÈÁña¤™µ„Õc3’àýåCv“ÝÕÓ¬âl¬ ¶¦áƒäQm»~ÿ.>ºÉ§<þ'N?uJ± ;½¼=áùã'"ÿ¶Š+hò廓?~mÄ©à,ð Nß½Ÿ8y·ùþ웻͹8Ûž¯ÄÙ§ó•Rêìþ}ÿó«û»ø—Ëô—íÇLJø!·ÎŸqþûoO^¿Â)[ K&ó–9y*“ÂèÜ2ë5J›Ò²mj’3}“œŽMŠ-º»ìZûñ1þþÚÒ;ÒLi+“£˜Í™ãNu~þÐÛÈSÏ‚µ:[D{+¤í-®zå0Lx#£m2a1¤ÄÙ6ù_üóÿSXðÏ÷Ä ½c^(yj¥¿h›hGvŠìVа“$5w—h(7 ãÒÛIØŠ;:lÒ¢ðŒ Ùkñ×5…梂ôÏQ”<7u @l”N€7Z'TؤžJ×½N>.•äù+IÉpS!ÀPF)x£B… 1Á2Í}îk ‘L*…üºR2$º%hˆ e ôF … ›„â ³< b’Pž–Ròì¥dÈpS!ÀPF)x£²v:²M1†y¯ErÕÚþ²¹~H£åõÅÍvuùéSES&N´=ºqÌŒ•dZòpj´`Ò tÁ@p‡ÞHî³°³_Ù8\+³ÑìñŽ2¶»Ýý®ˆ¤†³Mu8¨XàúÖ PÄù²4¶=€†„FŠUJ§¸F€7Z#Tؤ­˜6ºï€ß@ Pô=SÞùc, %mMìÀÀ)PØ7;6aW’Y#û>HˆûØKÚšØ!R °o4v*lÂ.ó†÷]P ö±—´5±C;¤@aÞhìûag8sÒçÓ\’Ë@àsÒY§Äí§JÐ×È`ÕÐôFj„ ›b S"?S’Ë@àÀÒ0¤­‰Ø'ìÀ ›°Çñ¡Ef õ©ç¬5¡vó ùè‹&NÄLÀãÈÐñPfþÀ?ôôúˆË{I[90$˜C ÄZôFS§Â&ìqdx^Y–r¹Ñ¼ÑKÚšØ!}B¸×7;6a—’ ž×—¥TËÝ~ØÝ^ÒÖÄ ìu·o4v*lÂ.S¡ qìÀ ± ˜ ¡_×fÁ~ö!m-ìÐÇ>¥€c‡ÞHìdØ„ÝyæƒëîH»`?{I[;0$°O(Ø7;6a·žñ`ú—ˤ[°ˆ½¤­‰Ø'ìÀ ›°ÇdPy™À/ØÄ^ÒÖÄ ì vàÆ¾v¶t/¤eñóV¥æÒ½Z–n•FMãÛ“ÚÈ„øè¾ +ÿ<êÂç®YÿÝRÿ…œI©Ûª€†¸,+\Ð& 2Ø  ísš÷ËNN.Ô§^2פ êB8B©SÁFê6¤Ý\¹,S¿Ï ^2פ êB8B©ïCz­¢w}¸WÍ^`}Ñèq¿«3'5ãJ/§‡.i˜Ôî€nÒ)VÝ,W•p„J‡ 6 'þâl~m½Ùì¶}¥èNxéÏ{ìŸ!ôe¤²ñß3¯ÃË:òe]òÕd Ö0ýH™ŽPÖT°‘u*J<Â:Ÿò³~¼¾û±FÙÅ®A†ã \2Õ¤ Ê0ñºz46t„R¦‚ ”UPÌæ”»{yû˜sèNw«cŽmNk/°üc´‡ŒµhCCœö@6t„Ñ&ƒ´½b*ï Zon{®}¹þŒG\ú£bžóÖD>ÚÄ„znPÞD¤·“ÌKß?QX÷‡4®¾÷÷Õö概XÇAuÇ·ýÖpÉŒ6jÌB¼Ø­ áùÌݰì>ê˜Ø ZãžÍZ1÷œ¥_àÊn\è(m2èÌ]÷:‰©Š»q•º©`£¼cVYÞpXÒKüýúº?ypÓ¨hŽ… åQ V†¤5C8d€T3àNÁ¼Í'N¯.nÖwj¥Ì2ṉE<ò*)lâ†~HD×ñG(~*؈_ ¦œ5üqr×ßôër,ñõåC}þÉùËÿuòýütã{™òVœþ”ÃDP§·'ñbl:&¨ûß›“·'ÛWÜ­ ¿yJ¢ñÓ6~ý·×Ix¯gMt!L¹~¶6FÆÙžŒ“îi#¿û{¼AÞ¤v¾©-Ì[fÌïân@RB+žÊÝÜ1VŽPÅ“ ŠâeLkSü`ýLЇþpÅOÚØTüsµqP<ÝÈ¢øI#¡â»a¾HùÀºuÜa|ìÆó›#Ø41ÿonL¬ðjH±’—=w׉µúX:ÂÄJçx«š¼ -Öbý\bþ±Â6¶ÅúLmÅJ6r+lä^y†íLG,K¡ž­ƒ?º:ªËJµ×Î?¿~ûöUÚðó§!§ûshǸà¿bÅwÿòƒc!Žý'—_¹i»ÆeÍÜõ›™°u6èŒZg#ƒÎœÑël+å :s‡÷e­«ìÊ©ê¡<8Ï´Ë»TÛå¡X?WyþˆòÛØW‡ÔÒ¯f­ŒÑyãž­™ÅÝNÍU:G/—Ï×9¦M˜MsQ1‚¦Òb¤®iîŽè«€#TŒ$èAŒi±Ö‡²è»ëšOK>›çEßþ£m^òíΡߥ/ù­­ü:‘œÙ—½>0¤¬‰¸!ú’/t„⦂¸c†›~ñÕwãÛoV_å·ÓÕ>æu~ ±r/ü}“¼27d«µÐ ñ…¾Iò« AÐ šŠ5‚Nƒ ™¿Ôn½ûñév{—ú™G¸#y{™>ú€¿àl„ü ]rÔ¼‘!q#Ô [å ¡|©`#_§\*¿§¶~è{ºÛ„óâ&Wî«uGùCúSuå>޲cÅ8¦†¬5‰C‚8„P_Ú…ŽPâT°‘¸LÞò¦õãöÓuÿrIõÒ ^ô{ÄÏýr)Ð%ÅÍz ‰z‰ÕëðƒªƒŠ5ªCflÞèÔÑUû÷Ow—põ¿þõQNã«çCâš%%r¨¿? ¡Ð©`#tn÷¹xz¼Â†åÒÇ)WpKA8¼äÌ6 ÁhGÔ€©úF"ð‚ ‚4èA„´9UŠ"ˆa@?>û»3ã«4b`€ ¾l2«~_¸ÑGøÅ/#«’¾&z`H ‡4êÉ@G(z*؈^ feþö¿}›ÞµÀæ¥6G ¾$¯ à! > endobj 422 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 628.3165 297.0286 635.5394] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 423 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 617.5144 297.0286 624.7373] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 424 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 605.4669 297.0286 613.9352] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 425 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 595.9102 297.0286 603.1331] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 426 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 585.1081 297.0286 592.331] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 427 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 541.2715 297.0286 547.4982] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 428 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 530.4694 297.0286 536.6961] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 429 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 519.6673 297.0286 525.894] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 430 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 475.3326 297.0286 481.5592] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 431 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 430.9979 297.0286 437.2245] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 432 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 420.1958 297.0286 426.4224] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 433 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 409.3937 297.0286 415.6203] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 434 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 398.5916 297.0286 404.8183] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 435 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 352.5134 297.0286 360.4835] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 436 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 341.7113 297.0286 349.6814] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 437 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 330.9092 297.0286 338.8793] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 438 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 320.1072 297.0286 328.0773] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 439 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 274.3728 297.0286 282.3429] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 440 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 263.5707 297.0286 271.5408] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 441 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 252.7686 297.0286 260.7387] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 442 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 243.7099 297.0286 249.9366] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 443 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 231.1644 297.0286 239.1345] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 444 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 222.1058 297.0286 228.3324] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 445 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 209.5602 297.0286 217.5303] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 446 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 198.7581 297.0286 206.7282] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 447 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 187.956 297.0286 195.9261] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 448 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 177.1539 297.0286 185.1241] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 449 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 166.3518 297.0286 174.322] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 450 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 155.5498 297.0286 163.5199] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 451 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 109.8154 297.0286 117.7855] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 452 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 100.7567 297.0286 106.9834] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 453 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 89.9546 297.0286 96.1813] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 454 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 627.7235 522 635.6936] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 455 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 617.2396 522 625.2097] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 456 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 606.7557 522 614.7258] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 457 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 596.2718 522 604.2419] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 458 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 552.8603 522 560.8304] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 459 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 542.3765 522 550.3466] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 460 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 531.8926 522 539.8627] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 461 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 488.4811 522 496.4512] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 462 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 477.9972 522 485.9673] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 463 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 467.5133 522 475.4834] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 464 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 425.2476 522 431.4742] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 465 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 414.7637 522 420.9903] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 466 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 402.5363 522 410.5064] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 467 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 392.0524 522 400.0226] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 468 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 383.312 522 389.5387] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 469 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.5453 371.0847 507.153 379.0548] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 470 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 371.0847 522 379.0548] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 471 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 362.3443 522 368.5709] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 472 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 351.8604 522 358.087] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 473 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 341.3765 522 347.6031] /Subtype /Link /A << /S /GoTo /D (8) >> >> endobj 474 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 330.8926 522 337.1192] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 475 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 320.4087 522 326.6354] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 476 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 309.9248 522 316.0518] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 477 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 297.6975 522 305.6676] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 478 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 287.2136 507.153 295.0841] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 479 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 287.2136 522 295.0841] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 480 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 276.7297 522 284.6998] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 481 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 266.2458 522 274.2159] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 482 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 255.7619 522 263.7321] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 483 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 245.2781 522 253.2482] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 484 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 234.7942 522 242.7643] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 485 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 226.0538 522 232.0531] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 486 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 215.5699 522 221.7965] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 487 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 205.086 522 211.3126] /Subtype /Link /A << /S /GoTo /D (1) >> >> endobj 488 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 194.6021 522 200.8288] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 489 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 152.5903 522 158.817] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 490 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 142.1064 522 148.3331] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 491 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 131.6225 522 137.8492] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 492 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 119.3952 522 127.3653] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 493 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 110.6548 522 116.8814] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 494 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.5453 98.4274 507.153 106.3975] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 495 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 98.4274 522 106.3975] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 496 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 87.9435 522 95.9136] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 497 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 79.2031 522 85.4298] /Subtype /Link /A << /S /GoTo /D (8) >> >> endobj 414 0 obj << /D [412 0 R /XYZ 90 720 null] >> endobj 415 0 obj << /D [412 0 R /XYZ 90 720 null] >> endobj 411 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F2 418 0 R /F38 421 0 R >> /ProcSet [ /PDF /Text ] >> endobj 500 0 obj << /Length 6349 /Filter /FlateDecode >> stream xÚí]Ûv#¹u}ï¯Ð[¤e .\ xŒç²bÇö$k:/±ýÀ–Øj­–ÈEÎdþ>@UuŠlˆ3ÌŒ(Ê^v«Õ§öA½Âõ€_4þ¿üÂ5­”Ì©¶½¸y|× ¿þüŽ?]{‹kjòÇ÷ïþð­æ¼a®qüâýÇ ÈûÛ¿_jqu-¹ÿÏå׋‡‡õÕµ°—7þwR^¾¿²òr·]o®øåýâáêŸïÿüî›÷É¢V `2/‘¸°Ì£†ò«—Jwåù°xº¿ºæ]”¸¼]þ£ájÕýjŠ~X¯žBYþð­´É´LçýæíZþu“ÿÇÖs{qN0%7ÎÖ“Üý3 ~²»¦†3æp!€vîµe°fâ5Cy²Ã^ï­d¦iDÏ»ž»\Þݯz²WwŠgºmÌkäøùÕÃYU1j ì˜²VòÔ`$kŒéÅð°X} €¼| bø²¸ñu™S„c¦õ ç¢ˆ}lË,—"E¯À}4»&vsê÷ÁBH•,S?baæÏ@¼LKn)ó¾¡÷ @'€Çåc׿o~ÊÐß Æ}%~‘Û *¹Ä°Kãè%h˜_ä6ì›mçZMÚùµ¯Î»ÕíSOñÍ•ïs|Zú?Üåçrëï?ðξ²/|‘ó³*çÄpN)à¼Ì9AÜ#·sÉ™2Rvÿ¸ÞmVË¡=ÿ´| ?ôÝ=-îrízk˜Vž8×EvctªìCÀ. ¶jÊì4Ì.rØ~@!\_¡w÷¡·©ÅÞ~Zö÷î÷÷6‹lÛm=7ü•QœºOCˆª±ÑôÅH¼u™Þ ³»ç²\1©ŒèÕ®a†ë~€øUO-—eú#õ`qHÍÖŠYq}øRå×¾mÓa`\«üÔ°\ù“U¥òS4(è6¨ÃÖ Ý‡›`N»ä¬q^;=¿¿ûÝ\>Ü«Úú{‹’N„òÃ-Ït¬WÏüªvF; ¤(·+ ø ºÑÚó.ûVåfñÐ5ËMÿ©XÜÞn–ÝXoèn7 ßG\u¿zXlï׫ŒFx#ü7Dè)’"…1U‰! ‘†U”§m(¦¹ <*ÅœrzLj£Lfúða(¨Õ9ÌÒ%‚b¼ª|CÀ7 ?µ– a¾‘ÛÀ·TLq-'|Çyâl»­¥>ó9ºÃ\1¡|qÐ! hX ÈmˆÌZ>ècµZo‡îÿºëß„†|; ÿ¾tºY÷ƒü0Þßö_yy¿êÿü´\|É5õ¾Ó*þíšú"{ÃÛWÉíw$”¢} Ýmo×áÏû ÚÌŽbÒ9sN 8)hUÒ‰! r€šg‚†IGnéeM£Ôœô8{Ó/ÁnîvËnÚwûTد#ÍÉ2_d7F§Ê.1ìÒ`óò¾iІÙEn=»Ò[ª¶áv÷ö]ž÷îʳçÔ°Ìù„°»’¢AΡÛÀ¹5¾.êL‡ëK¢™,±ågJoÂÄ­l¸>‰ÛŠ*•ÄPI# f…(¦¹ T¶†©†·„ÊŽ¹‡Û_8ÿîKðÂ§ŽŠ”ÆT)%†€Ra0yKÑ0¥Èm ÔhfM;|o–‹Í¤%îjáò1 ÁX&MÛžG+ãT噞iØÁ‚)EÃ<#·g­ýHIö;/oÖýªJOòÓ²?·´é7? •yæÏ¡¡^®†š<4ÓÝÏË®¹þ¡ÿËWº½¤³øðm© Ÿ‰ŸÓR9‰ïTå„NhˆÀæTІ9An'J±Ö¹ %ëUωoJCýos Vû†Úµ¯ôÈA L•×ÑÐJ¢ †­ “ |N¥b¨6’úe±½ÿÐ$‡sÁ¾ÖäS¯•Fœñ®„¸*éİNyPm™v‚†yGnñB²V6:OH_Óç61Œ›V¾–Ák<’"T;fB ËçL&/o-¥`˜`ä5Ì%ãÎÄ/èê#ûÔü¡ÿì'ïí8RC gU Ĩ²Ô@À°× †F03Š!hàn×w ú´W©§TÔ‡ï?·ò•MO›÷!^ÕÖ}´; ¾Re²G,Ì5ðé©㢵{\MùSŸ„_ö½ß/ÛüAר׼„Xªå)vµZN ˵|BE¹–S0È<ô¨·¾ wRïQ¿÷A—Ãw¾ôAw’I}J»"1U:‰! “†ÐIÀ0Èk ³å¬ñ‘Χí¢[öÿ)ŽbÃ`·¯Çé~_ñÅ'×OsLóSê§•ç—ZëL ËÍó$Ì`Š™¢a^‘ÛÀ«i˜Ž›Á×_ú!Ö—cN›añ@¿úyF}[­î£¨í„¥òŒš.ƒ$”cÎ5ñ£¿Ö·»n–%»ÍCzèÁ,È5ò)} íZ®¦WöÊÃ&‹u:hMÂÝ:}vÄk.Xk•©Ýœ”ìðFs¸Ž{ž»(«rkRwQt6rÞÊPkI5¿Ë~Žå‹?ö«ï” ‹1¬òO ÿ”’ùÂNÇ?*òœüÁœγ%þ÷s½ýx¿Æõ·ÕLoœ;f„ä/%¹êØø®Užˆ!à‰†nžñ¼ã‰yBÎFžt·IGžÒÒY)Åb×£Z>e)¾%_Ê­HX|é*aÄFc8ï@u„ "aÈÙH˜âÌ*버Á“¹€¶F2¯u êǨÇ@TI$†€D׉¨H"r6’(ý(´mMŽÄ0˜YF1…Jg˜jÅo^éŠDÅ—­E Q4v¢P‘(äl$J4¬m†{D=-7ÃÆáCÈò£L)ÄËN8;Æ:¾~•:b¨£Ñ,PG€ŠÔ!g#u¼ ýT;Pws?ä“íÉܦ)#×Mæ‹ÂhV;{²{½ÇàÇxT¹$†€KÞù„OÇ%*r‰œ%.µs¡Ï© \ yf\¦xÔ¸¤†e.'áÍsIJ\Bg#—ÖÿÒÅõ¡OG0nä·w)cÜåçò®þpôC‰×rhvädS•áÑLb.m–ߦH/ð4²ÛÚЉ=›§x%öfw®èÎ,Ü æ‹éÞf&"h™t^Ó)š% v×Ô0#ƒ}¸ìmÉ NQÈ×(ÓúŽp¬ç'{Ä6ÝMÉ…õ™†ÉsºQ­Xÿcüª 1-¥£ÐÄ "÷ÈÙȽnCßz£Þ/îVë'r]²¸ì¶’n6ëM6ʼnoÐñ:¯Kùˆ!ªÒK ½4â"_µ P‘^äl¤W™Ðÿæóä?“Œ4ÑÅÞ×Ü¢ë“ÃT„m_èÇ"™1 U2‰! “ÆW¨,™¨H&r6’)ï€kŽÈœŸv_ôl“p¯šÐ§~ÃHEŒN•Yb˜¥Á.0K€ŠÌ"g#³¢[8¦àý&Ñẳ”lên³xÌ7Â’sóÊá¡*»Ä°K.³÷¨È.r6²~pÃ1<»»méõ}1÷” yó5?Ÿ“#W1|Uê‰! ž²Q ž©GÎFêÕ¬ÎQ_MN.NmÚö|—ÕSøªÔC@=eƒç©'@EꑳD½r2ô¿M¾Öï¹–ªe¼ä)ý?ïþþÏæâÖ—ãÏïüPË~ñc(ãN^<¾ó/eüKõ}x÷ý»ÿË™ð®)༰~ç£#ö ÛíûÈÞÄj7gØÑ BÂhÏáÊ} TÒ!¦6éÐÊpÓ›8P‡ñ©£éN ;î?î~¡y»2ŸHF£ú„RŠ ÑÁCaœÃå·†ki$0ÈYX+ÂàÅ(°øÔÑFÀ&… ݤ„­fBHq´F¼J [ËŒ”ÓÎÎQLëA¶øñ†n~Í~bQÓäu±¦Q\æp@Ó¨¨iHBÒ´oKü°M¨éøÔÑ4M¦'…Åš>R GMÃFMÓö™¬ÃBÃ.wpVfùjf%h|p%@œÃJ@€Š•²–*æ~t{h:Zñ@  %Åà8ÅõŠåOJ7QjÒq;?ôæ·Ø©WõøÒXÓ 83°òFS4¢!éY5aÈ~èˆ,>u4E@ éIa±¦TÂQÔ°„QÕ´€sYOÿ†£;/æ¨@Qá$Xâ(Ts8 rTT9ä%É\6L ~è€/>u4™@ sZØåf³Z…ºËãRJw™_n™VÍ)œ, D …s×õÚ¬ÐPQh»$4îÂüƒ;Phñ©£ ¡ÑÂ.Âö?Ýøÿñ~~³Þmï³‰ë´ —¢¨S‰ å®|êEyK"kÂYr«Y|êh"#€@d´°Ëÿí7Ìñ>ŸRרá»ÏöôÂRžæ4vÓ`U¡ØÍáÀІU‰Šª’β6^iüõ_ÿõ/ù.pôÕLP¦K Nø…‚Šx×p^Nc<ˆÓr~û_^K›—1L;ËVƈW)cH’Õ´vZƯþ훯B$ÿ=w€P1ób®R(íã£ï ÷ñÁàÌá²y‡4¥ˆ‘DmmÕ·Ïu|àh¢&€@Ô´œUQ©Œ£¨a“¨iGQÇ4¨zq—OXÑ- ÿ /5Êôí`£ Ã0‡+D¥@Eý˜'ý†d]FÉÃ>õé©c}ê)`ùS?)ìÝr›«dJÙ£o€«”ÎW1«[;-ÝÓv±}:`MÆ[{¬w·9\þºVM‰Gz‡$%½{¶|{qàø)=u4½@ wZ؇õ|6*œa–­|¯R>ÿ2œ)™”o–àô“¬.|aÝ‹;±Nß …iN€Š‡œ$û–D ~à„kzêh'€@à´°PàG*ß(pX¾$pZ¾b“^hϕԧҠ“``½£¨Íáò¹5%éR”ô®´ÿü6μ¦§Ž¦wôN õ~¤òz‡åKz§åÛ­>n–4æÖw–š——~„¾97 Ñ4æ¨(nÈG·ÔabåÀm>é©£‰›qÓÂzqYôÙkbúÑÍ}á ìî»føIi¡!ÁªB±›Ã•×(PQU¨¤*¡B¿ëÀMé©£©ŠUÑÂ>†ùµ ]m™1­;áµ,.Â9ø ¢¸ _I\<ä?;´û9u7?moCzÞðã«çN …+=$w/| – Þ®<´¡@EYA¦’¬ü÷Í«õó[ÝøÀÑZ]Z]ZÎïÿôßß w‡})i8ã¼q'uÌjX§‹û0rs¸ìÝèšÆ© ²”ÔdBDÇl¤âSGk¤ h¤haŸ¶›n¿Ý³'ïZfEÓžÔ n§PüæpåÞ!** ’•”¥CŽÆ¶=PYñ©£)‹eÑÂ×ncî2’(£Ûu—¿ÿ2ì9Ý´‚±é!ÑÂ- 뮘nŒâõ)LzS!¤9p›Gzêhz#€@o´°Û ­Oqø¼¦L[¦¥;åé?%ܰ¡pÎáÊS)¨(4È]šI.Õ¡ýúøÔÑ„FÐha‡dŰ>þtÈÖ¢Í) ŽD …uWÞULŠ‚ƒ&ÁñvóÐ çôÔÑGàha§‚{îÉ?Ðà!('˜pÆË sWNêGŠ2ƒÌ%™5!«§8p›Azêh2#€@f´°?<öô©ëî–õEÍŒà/}’‚k El:ÿ¨¨%HOÔR¸êÚ>ó«úá{Þ>ü”™‚m™¦é3¿°8Ñ–"YS5,«`BLþ*©:U`C2Q§ª*ˆûßóùʺ‰§æUæ¨+²#WeÖ)Ö P‘uäld½ YGóUSã:ä¦ã–Ÿonº½*ñ£àP¡² ÁL‘uài$=$’fè£îcÿõ&{Z_2-¬}•¹ECv«Æ5f Ia•.Ú]SÃù*Ý ®rˆùâ `rÏk†ÑhVqº–]¥K ˆµ7Më‘§ûp…ÓAÃbåMÓz$t:Ãë‘•7%Õ:Á•s²×Þ²«¡ûΦ—)•T†~¯í§I¾)Ý©ÌåB0¤³~ —ÉÑíqœuoqÿÜF^p¦¬}†Œˆ!Q´*/kS ¢Œ³QD¼ WÅI*‘n€¿éfú¡M.÷Õn‡­±Ý¿å’†ki_Oz®£*¿ÄðKC®²C7 Tä9ùmüÐ]i·Ÿ:¥§ña7ìú'—j¯ó¶û4ñ·ªo—œÑ'<•˜T%—ri¼EöR^ T$9Kä†û¯Úá`²zzsÕoºt—·½¼É_ÇìÂ¥ÏgÛ9á«1OìÊÄS.ò¼˜íÈSb^ùYço¬ÏYÇׯ¬£«Ðg`eÖ³7¯ÿ .endstream endobj 499 0 obj << /Type /Page /Contents 500 0 R /Resources 498 0 R /MediaBox [0 0 612 792] /Parent 387 0 R /Annots [ 502 0 R 503 0 R 504 0 R 505 0 R 506 0 R 507 0 R 508 0 R 509 0 R 513 0 R 514 0 R 515 0 R 516 0 R 517 0 R 518 0 R 519 0 R 520 0 R 521 0 R 522 0 R 523 0 R 524 0 R 525 0 R 526 0 R 527 0 R 528 0 R 529 0 R 530 0 R 531 0 R 532 0 R 533 0 R 534 0 R 535 0 R 536 0 R 537 0 R 538 0 R 539 0 R 540 0 R 541 0 R 542 0 R 543 0 R 544 0 R 545 0 R 546 0 R 547 0 R 548 0 R 549 0 R 550 0 R 551 0 R 552 0 R 553 0 R 554 0 R 555 0 R 556 0 R 557 0 R 558 0 R 559 0 R 560 0 R 561 0 R 562 0 R 563 0 R 564 0 R 565 0 R 566 0 R 567 0 R 568 0 R 569 0 R 570 0 R 571 0 R 572 0 R 573 0 R 574 0 R 575 0 R 576 0 R 577 0 R 578 0 R 579 0 R 580 0 R 581 0 R 582 0 R 583 0 R 584 0 R 585 0 R 586 0 R 587 0 R 588 0 R 589 0 R 590 0 R 591 0 R 592 0 R 593 0 R 594 0 R 595 0 R 596 0 R 597 0 R 598 0 R 599 0 R 600 0 R 601 0 R 602 0 R 603 0 R 604 0 R 605 0 R 606 0 R 607 0 R 608 0 R 609 0 R 610 0 R 611 0 R 612 0 R 613 0 R 614 0 R 615 0 R 616 0 R 617 0 R 618 0 R 619 0 R 620 0 R ] >> endobj 502 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 684.1345 297.0286 690.3611] /Subtype /Link /A << /S /GoTo /D (8) >> >> endobj 503 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 671.8568 297.0286 679.8269] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 504 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 661.3225 297.0286 669.2926] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 505 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 650.7883 297.0286 658.7584] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 506 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 640.2541 297.0286 648.2242] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 507 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 629.7198 297.0286 637.6899] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 508 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 619.1856 297.0286 627.1557] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 509 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 574.8088 297.0286 582.7789] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 513 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 564.2745 297.0286 571.7963] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 514 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 555.4837 297.0286 561.7104] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 515 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 544.9495 297.0286 551.1761] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 516 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 534.4153 297.0286 540.6419] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 517 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 522.1376 297.0286 530.1077] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 518 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 513.3468 297.0286 519.5734] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 519 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 501.0691 297.0286 509.0392] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 520 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 490.5348 297.0286 498.505] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 521 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 480.0006 297.0286 487.9707] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 522 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 469.4664 297.0286 477.4365] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 523 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 458.9321 282.1816 466.9022] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 524 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 458.9321 297.0286 466.9022] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 525 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 450.1413 297.0286 456.368] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 526 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 439.6071 297.0286 445.8338] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 527 0 obj << /Type /Annot /Border [0 0 0] /Rect [258.1192 427.3294 267.3345 435.2995] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 528 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 427.3294 282.1816 435.2995] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 529 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 427.3294 297.0286 435.2995] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 530 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 418.5386 297.0286 424.7653] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 531 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 406.2609 297.0286 414.231] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 532 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 395.7267 297.0286 403.6968] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 533 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 385.1924 297.0286 393.1626] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 534 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 374.6582 297.0286 382.6283] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 535 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 364.124 297.0286 372.0941] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 536 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 353.5897 297.0286 361.5598] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 537 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 343.0555 297.0286 351.0256] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 538 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 332.5212 297.0286 340.4914] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 539 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 321.987 297.0286 329.9571] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 540 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 313.1962 297.0286 319.4229] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 541 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 300.9185 297.0286 308.8886] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 542 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 290.3843 297.0286 298.3544] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 543 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 279.8501 297.0286 287.8202] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 544 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 269.3158 297.0286 277.2859] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 545 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 258.7816 297.0286 266.5244] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 546 0 obj << /Type /Annot /Border [0 0 0] /Rect [258.1192 248.2473 267.3345 256.2175] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 547 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 248.2473 282.1816 256.2175] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 548 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 248.2473 297.0286 256.2175] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 549 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 237.7131 297.0286 245.6832] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 550 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 228.9223 297.0286 235.149] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 551 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 216.6446 297.0286 224.6147] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 552 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 206.1104 297.0286 214.0805] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 553 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 195.5761 297.0286 203.5463] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 554 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 185.0419 297.0286 192.5637] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 555 0 obj << /Type /Annot /Border [0 0 0] /Rect [277.5739 174.5077 282.1816 182.4778] /Subtype /Link /A << /S /GoTo /D (7) >> >> endobj 556 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 174.5077 297.0286 182.4778] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 557 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 163.9734 297.0286 171.9435] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 558 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 153.4392 297.0286 161.4093] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 559 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 142.9049 297.0286 150.6477] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 560 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 100.2716 297.0286 106.4982] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 561 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 87.9939 297.0286 95.964] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 562 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 77.4596 297.0286 85.4298] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 563 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 682.391 522 690.3611] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 564 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 671.8196 522 679.7897] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 565 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 661.2482 522 669.2184] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 566 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 650.6769 522 658.647] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 567 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 640.1055 522 648.0756] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 568 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 629.5341 522 637.5042] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 569 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 618.9627 522 626.9328] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 570 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 610.1348 522 616.3614] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 571 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 599.5634 522 605.7901] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 572 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 587.2486 522 595.2187] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 573 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 578.4206 522 584.6473] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 574 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 567.8492 522 574.0759] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 575 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 555.5344 522 563.5045] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 576 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 544.963 522 552.9331] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 577 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 534.3916 522 542.3617] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 578 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 523.8203 522 531.7904] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 579 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 513.2489 522 521.219] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 580 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 504.4209 522 510.6476] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 581 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 492.1061 522 500.0762] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 582 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 481.5347 522 489.5048] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 583 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 470.9633 522 478.9334] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 584 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 460.3919 522 468.3621] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 585 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 449.8206 522 457.7907] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 586 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 439.2492 522 447.2193] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 587 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 430.4212 522 436.6479] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 588 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 417.6083 522 426.5746] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 589 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 409.2785 522 415.5051] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 590 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 398.7071 522 404.8341] /Subtype /Link /A << /S /GoTo /D (7) >> >> endobj 591 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 386.3922 522 394.3624] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 592 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 375.8209 522 383.791] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 593 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 365.2495 522 373.2196] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 594 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 354.6781 522 362.6482] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 595 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 344.1067 522 352.0768] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 596 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 333.5353 522 341.5054] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 597 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 324.7074 522 330.9341] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 598 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 312.3926 522 320.3627] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 599 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 301.8212 522 309.7913] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 600 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 291.2498 507.153 299.1203] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 601 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 291.2498 522 299.1203] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 602 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 282.4219 522 288.6485] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 603 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 270.107 522 277.9775] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 604 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 261.2791 522 267.5057] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 605 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 248.9643 522 256.9344] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 606 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 240.1363 522 246.363] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 607 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 227.8215 522 235.7916] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 608 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 216.752 522 225.7183] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 609 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 206.6787 522 214.6488] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 610 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 197.8508 522 204.0774] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 611 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 187.2794 522 193.5061] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 612 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 176.708 522 182.9347] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 613 0 obj << /Type /Annot /Border [0 0 0] /Rect [483.0906 164.3932 492.306 172.3633] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 614 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 164.3932 507.153 172.3633] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 615 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 164.3932 522 172.3633] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 616 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 121.4886 522 127.267] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 617 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 110.9173 522 117.1439] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 618 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 100.3459 522 106.5725] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 619 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 89.7745 522 96.0011] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 620 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 79.2031 522 85.4298] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 501 0 obj << /D [499 0 R /XYZ 90 720 null] >> endobj 498 0 obj << /Font << /F51 6 0 R /F2 418 0 R /F38 421 0 R /F72 9 0 R /F31 512 0 R >> /ProcSet [ /PDF /Text ] >> endobj 623 0 obj << /Length 6249 /Filter /FlateDecode >> stream xÚí]]wÜ6’}÷¯ð£tN!¾G'–Í:rÖVœ³;;m©%õ«å‘Zë™ýõ‹" ²Ø Ý&ÑGŸ†®ÙçÔƒÙ…Ñ÷Ïè>Ý1V$„ãüS„#4špÊ-n+æ´à$áum ´¿Cm±JH ø±\>Ú)¹,¿1?E~‘!Á/N71ØÆh4¿”[à×T¬R¾éá½>߇ïÞoúæ¡ëέ鯈ÿxñ׿U/ÏCyQ1é ùâa<üýú…`ÖÀ4LýÏÏ/>¼øÏ>Ä7Ãx£¹°L;í†q¾zýúý„úáÃ(Êðаíxª0#^!N«™\ã|{üá4Q °.ø¥fŽšM œÊÏ®0“ŒÑhSnAàÊ3¡ŒÚAàñŠ©Žðã8_½þéød_h©3BO`Ä+DhTxx 1Œ0'mÉ”³z@–:J-t*[c¸’Ð-tÊ-]:¦”4;=^1•Ð!tç«·oßA¤ß§Ä®œ˜,Æ®£‘Ìy¾ã›CÎÕÁ«Ð½9~ ±½N_æ¥|(ÂÏjµžÖ8•¦1\IãÖ8å4DdTewÐx¼b*#•Â1\á ŒFkŸr Ú¯ «¤æ;h?^1•ö¡}'©ý‰ÂëµOÆ×iÇ÷öø$£}+ŸŽòQ^håS Õ”ÐhåSnƒò…×LH!¶W~wÅDÊÇxyå⤔?Uxòéø¢òñ}8:…Dþz\?§:ë‚iØ{ððk §zœRõdòÆp…iGŒFªžt ªwŠ)áw˜•鮘JõP=Ž“TýDáõª'ãëTãûpüßGééFk¹x2w|œZûT Çp…;>F£µO¹í[ÉŒ0zíÇ+¦Ò>Â#´ãÄ£ÂAˆZ2m+5YŒ¯¤6Ì»J ƒ|iüxaÖI…y›_럞ֿ;IÔ‡Œr ܸ!ä7Ùâ1\f\W¤1¹ÀM»ÁÑ Ü¥ÆöÅI{Ý„+¬w–Û'åŠÓæ„Üa†©»bªâDxDqâ8k0‘f¬ž,ºˆWOqØ€)†áþzü}nJ ®´}:'”ZÿTÇp¥ŽB£õO¹ýkXœ¬v˜„ꮘJÿÐ?Žóx¼ , 3ÖN\ WNU¬rf#¸7°Sâ]Žœ$4Ó•ÒO§P–è" Ò9†+B£‹€r Enc¢= m»h/˜ªz8¢PDLY§*²Nþ(²}½lö654 ½8!ø#ß–-ƒ>YtI•j Ç¢K€ð  +¦Â(s‡ˆWLU(g»”üã1ŠbÞz>YŒ¯¤v×myòît¼üçƒ7è5M_Ä+Äç$¤Úãûþ]3NâoŽH=«<3^ü!óÇÙºB­¢ ‹jþ®TZ®-Ê-9äb‡=wÝSÂ#Š Çyò.½˜¤fÕÓÚ°žÕÊ­;*½c¸’î­;Ê-è®rÌU~—‰§xÅTºCx„îpœ©û¥‚‹‚è¦ /ââ ½Fi¥Æ·]÷Þyÿ÷Äá|Њ§7†+)¡ÑЧÜÅsïXU™fsº+&R<ÆË+~'¥ø©ÂëOÇ?ˆ/µ3U2¡õtÙ‹x…ðL•­†áýxôêçôÞ%äò «0W~¸õdù‘iÃÊ£‘åGº…ò žE%wHwWLU~(?'Y~…×—_W~8¾w‰ò „ø@ÃTáE¼Bx¶bº2zÞwx6~ ¯ÜCÝ@ˆ[K—•–1\a!F£Ër åf SÕ{¨âS[GÔ ’,µibë+ ®+4܇ÓC§ëM»ïá‡q¤aøl*ã§Š4ÂÑ‘ TJEZ(9ûÇ,¯d«ªo]TD³G`…µz„EWá Êh¦½Û¥¢âS•Â#j ǹ¹>š Óp"¿œ,ÔˆWˆUÃa Æúæèäûäª 4_›ÇÕYCͧ…Nåi W’:B£µN¹±kŬ×;ÌJuWL%v„GˆǹµØ' µ;k'vëÛ㟎“ïÌÁÖ<ÔW‡â¶Ü`r ™™1\a F#w±ÐnGpô.–RcûZ¦½nÂW™?G§Ôؾ–)·PËJ2ïÅ3}ÝSÕ2Â#jÇù¡éÆŒ;Z¡w楘.ƈWR&•Pà ›å‘÷u6ù9UÎðšæŸÿfIV٨ɴ²©ÜŒáJc„F+›r Ê–2T²ßá-×”ðeã8OkѼu@*\ObÄ+Äôo$—ÿK®öqØŽ,ÔS;µ燮*‘c¸R_ ¡ÑU@¹…*¤±ËÄZ¼bª*@xDà8Eå×™Žš h%ÝdqF¼B Ð'ÖRÍŽJt{?˜QIVÛ¨Á´¶©ÌŒáJÚFh´¶)· m΃xä;»+¦Ò6Â#´ãüµŽð—·ãDŒb¾‡Xk<ÞÔJ&õSÙk‘å=æ­È;2$xÇ4p—ç¡Ñ¼SnïÎ3oD´ÃÁh‹U}lñòf•<»Z0-äs;ºº „˜È’]^˜â [„EŠ`Ó§…‘P-§rB?Ãþ@®^ž(RÅ"5ñ8¼ úìLTíËgóe} Þâ¼¹-ÜÀ­àëõÚc¿,ÏàwÍ){ëÙÅbuVßIDs_™_.ÏfG%CøÓmcV_~Uÿ¦EJôùmxvWÐãF 5O-žZƄ܈ìûØÝ ŽˆÃ¥ïÛZˆÇk`B;ëùÒðåzo“lܯÎm¿,Q*B_Ôi]ÁAõííý:Þõ/› Àj è鸯©9ƒ¿$iq:<ùÍèiœ%"6¦H2$ˆÀ¹É€²DPÎz"à5ØÐo‰øG*ð‰ÿ\oš¿ù òžÏ˜â¢Êc#C‚tLEæ¾€²´SÎ:Þµ×̸ö“R7¡gÝö«ëO»Ü,kº× ýÝÐe}ÕŠáþ.v™¿‚ô¯ïš×ýõ›æÑÝéë¿\ܤ&T`9_Op&yŽ£®%ްaž£AÚDòæ‹r‘ÎzŽÂp£rí ‡pä{*†Áæû}÷ê·uÁ»å y`ÆÒ%Œ²ò œõò°Š)Ûo\Ë}§iðYø&€o*9õ]€0Ô¿÷óƒú4DÏWLa‘~dHÐÉÜP–~ÊYO?œ”lùûxÂêk}ë^®×‹ꨥúÝáG^=¢»H–Ï6'E:{;‚M”àñ¾ŠšÌ&Ë%á©§RÃÇ‹´ÙàòîËü¬ýñjÞ>_Û¾W[Ë5«9Ê á˜Qâae™ŠM.R… ®p3d! ,[”³ž.%˜1•èèš}ú<_¥& Uż6öÙ} Oy˼´¦OUšæÎn† G™Ãeh®,ãZ¼¦¨nÍh§#°ä~Å^tK‘ I§#¸ô©[µ  ­¬M9ë-«´² Ïã—>ávr}sû¯Ì¥4ϱ×ÓU¤Tãì§'t0P–êMg™1]q&Mû!ñŠ+b—ggÉaãN‹ý¸ã7>þ”ƒ›‹+Oýcü„:«ún‘œ0Â@9 ‘Î:…®)ÓZ4óË—çŸÒ£Ò  ½<~³±ÓQ3+Œ|ZçötÄ ÙE†»8á"9ìRÎzv…dZhÙ]¬š  @æ7íµÛ›OŸu¶ÓF_—qäU‚k‡¥=¦iŠ,­15EZ‘!A+δHî¨Á@YZ)g=­Á«U3êú¡ÞLç7}ËúQ«eÙ¿·©½Ã›aÀq´Ú3a5FûáÕ!çúàãQ|V¬.ØU;ýDW«ï&óMb¡þŒN]VB¨ù´„¨<á ! ¬„HR: ….²äMïð‡E¬ø£nO{}XÞÞ¬®ý>÷‡Î„Ž÷üS³ôÇm|—y+¸_¡ÿž^ÂõÖòßm 76«ÈHoG‚r”ᣇÉÒAxêØž3[µ¯¤…ûôÕÍÝz5¿nûP÷«3\õ#ºIx½]5¹Ø ÿóÇÕ9¢º—˜Â†yª ”ÉY ”#‹tÖ³îD¼R"²õeyþÛ‰‚5ÿ¨]VŠŒ"C‚Qœä £(Ë(å¬gÔ†nw.2Ú‘ØÜÏÚYøíüv½8O¿|¥¤}†£YË$0Üe0Ç~k7Æ ö7á É!ÆÉ’OùêÉ祊äßïËê/f¥XÎÈ(gœäL9# ,£›Î2+R„Î'ÓRŸ1I¬\4WóÕe×w C¢K˜Á˜_§Æº<Ô¹7Oò­¾ž,Hãï¢ ;‚ùÖ(ÿª‚ÉòNxêI¯‚ã1 E‘!A Îiz§ÊH9ë Ô°y¨}~{/:ÝÁU=àÎsÈ™õf1ËaÌC‘CdHpˆÓšáe9¤œõªŠYíÛþÕòòj»·BWW<œâúÃÜf³XT2$€IQ*©”Uå¬W€¬`k«iмëÕv¬ê5Âùi²øW»=ÿ@wA{•ÓOííÝ.WEž‘!Á3N½L󌀲¨Ó3“R$„â§çÀ0P–PÊYOh~ /p4„Ba~m·äÜ´¼BûKßÀ¹övo‰‹¹,ê:ÀÔdúÑ(«ÊY§øê‹”Vu°¾ijúSýïâr™|áO1#xö³%]K³%Ø0?[2`%¹¾qr }õ ppº`s×ù>{ös;]R¯Ø_®BÒ¯Žc ,ù”³žüPòF(×’ßì ]Λ·0þo>ZŸ¯ÚÅó»Åú¾—¿˜G«fÛØyò}c8½öÏ[•ÉrÛ_äÜátf¸C@Yî(g=w<Ü®y»Ä½lÎ4]͉ƒ .Ýy-ͯáýšÔâ™ ãŸÌÀ=öÆb¢Š;dHtîpÞ“oÞ`œ,Ç”¯žã 6d·'%Ÿœ¶Å—íÖi¦uûn][Ž1{ÅêF†Duc22=;”ežrÖ1ï•a^nq;‡yõõàŽ|vsŸíÏÁ7!•~|æÜ1'¥#]þœ`îs (êüÊã&}zÝÆ^²¤ÇM°zFÊ¥[hŸ´§N®6dI>”ë*.þÌÏÏowø`°åàPÈú•²Ûû/ëüë\„~¦1îá¼›\b Ùå™ÂùKŸZ‚`z¦þþ¹œendstream endobj 622 0 obj << /Type /Page /Contents 623 0 R /Resources 621 0 R /MediaBox [0 0 612 792] /Parent 734 0 R /Annots [ 625 0 R 626 0 R 627 0 R 628 0 R 629 0 R 630 0 R 631 0 R 632 0 R 633 0 R 634 0 R 635 0 R 636 0 R 637 0 R 638 0 R 639 0 R 640 0 R 641 0 R 642 0 R 643 0 R 644 0 R 645 0 R 646 0 R 647 0 R 648 0 R 649 0 R 650 0 R 651 0 R 652 0 R 653 0 R 654 0 R 655 0 R 656 0 R 657 0 R 658 0 R 659 0 R 660 0 R 661 0 R 662 0 R 663 0 R 664 0 R 665 0 R 666 0 R 667 0 R 668 0 R 669 0 R 670 0 R 671 0 R 672 0 R 673 0 R 674 0 R 675 0 R 676 0 R 677 0 R 678 0 R 679 0 R 680 0 R 681 0 R 682 0 R 683 0 R 684 0 R 685 0 R 686 0 R 687 0 R 688 0 R 689 0 R 690 0 R 691 0 R 692 0 R 693 0 R 694 0 R 695 0 R 696 0 R 697 0 R 698 0 R 699 0 R 700 0 R 701 0 R 702 0 R 703 0 R 704 0 R 705 0 R 706 0 R 707 0 R 708 0 R 709 0 R 710 0 R 711 0 R 712 0 R 713 0 R 714 0 R 715 0 R 716 0 R 717 0 R 718 0 R 719 0 R 720 0 R 721 0 R 722 0 R 723 0 R 724 0 R 725 0 R 726 0 R 727 0 R 728 0 R 729 0 R 730 0 R 731 0 R 732 0 R 733 0 R ] >> endobj 625 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 684.1345 297.0286 690.3611] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 626 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 673.3316 297.0286 679.5583] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 627 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 662.5288 297.0286 668.7554] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 628 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 651.7259 297.0286 657.9526] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 629 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 640.9231 297.0286 647.1498] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 630 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 630.1203 297.0286 636.3469] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 631 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 619.3174 297.0286 625.5441] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 632 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 608.5146 297.0286 614.7412] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 633 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 597.7118 297.0286 603.9384] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 634 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 586.9089 297.0286 593.1356] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 635 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 576.1061 297.0286 582.3327] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 636 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 565.3032 297.0286 571.5299] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 637 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 554.5004 297.0286 560.727] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 638 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 543.6976 297.0286 549.9242] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 639 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 532.8947 297.0286 539.1214] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 640 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 522.0919 297.0286 528.3185] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 641 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 511.289 297.0286 517.5157] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 642 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 500.4862 297.0286 506.7128] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 643 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 489.6834 297.0286 495.91] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 644 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 478.8805 297.0286 485.1072] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 645 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 468.0777 297.0286 474.3043] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 646 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 455.5314 297.0286 463.5015] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 647 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 444.7285 297.0286 452.6986] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 648 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 435.6691 297.0286 441.8958] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 649 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 423.1229 297.0286 430.6446] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 650 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 414.0635 297.0286 420.2901] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 651 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 401.5172 282.1816 409.4873] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 652 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 401.5172 297.0286 409.4873] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 653 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 390.7143 282.1816 398.6844] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 654 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 390.7143 297.0286 398.6844] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 655 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 381.6549 297.0286 387.8816] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 656 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 370.8521 297.0286 377.0788] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 657 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 360.0493 297.0286 366.1763] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 658 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 349.2464 297.0286 355.3734] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 659 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 338.4436 297.0286 344.5706] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 660 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 327.6407 297.0286 333.7677] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 661 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 316.8379 297.0286 322.9649] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 662 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 306.0351 297.0286 312.1621] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 663 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 295.2322 297.0286 301.3592] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 664 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 284.4294 297.0286 290.5564] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 665 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 271.8831 282.1816 279.7536] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 666 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 271.8831 297.0286 279.7536] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 667 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 262.8237 297.0286 268.9507] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 668 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 252.0209 297.0286 258.1479] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 669 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 241.218 297.0286 247.345] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 670 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 230.4152 297.0286 236.5422] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 671 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 219.6123 297.0286 225.7393] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 672 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 208.8095 297.0286 214.9365] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 673 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 198.0067 297.0286 204.1337] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 674 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 187.2038 297.0286 193.3308] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 675 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 176.401 297.0286 182.528] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 676 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 165.5981 297.0286 171.7251] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 677 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 153.0518 282.1816 160.9223] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 678 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 153.0518 297.0286 160.9223] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 679 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 143.9925 297.0286 150.1195] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 680 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 133.1896 297.0286 139.3166] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 681 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 122.3868 297.0286 128.5138] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 682 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 111.5839 297.0286 117.7109] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 683 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 99.0376 297.0286 106.7804] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 684 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 89.9783 297.0286 95.9776] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 685 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 668.1817 522 676.1518] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 686 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 657.5762 522 665.5463] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 687 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 646.9708 522 654.9409] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 688 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 638.1089 522 644.3355] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 689 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 625.76 522 633.7301] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 690 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 615.1546 522 623.1247] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 691 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 604.051 522 613.0174] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 692 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 593.9438 522 601.9139] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 693 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 585.0818 522 591.3085] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 694 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 574.4764 522 580.703] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 695 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 563.871 522 570.0976] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 696 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 551.5221 522 559.4922] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 697 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 540.9167 507.153 548.8868] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 698 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 540.9167 522 548.8868] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 699 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 530.3113 522 538.2814] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 700 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 485.4149 522 492.9366] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 701 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 474.8095 522 482.7796] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 702 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 464.204 522 472.1742] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 703 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 453.5986 522 461.5687] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 704 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 442.9932 522 450.9633] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 705 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 432.3878 522 440.3579] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 706 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 421.7824 522 429.7525] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 707 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 411.177 522 419.1471] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 708 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 400.5716 522 408.5417] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 709 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 389.9661 522 397.9363] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 710 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 379.3607 522 387.3308] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 711 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 368.7553 522 376.7254] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 712 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 358.1499 522 366.12] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 713 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 313.2535 522 321.2236] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 714 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 304.3916 522 310.5186] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 715 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 292.0427 522 300.0128] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 716 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 281.4373 522 289.4074] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 717 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 270.8318 522 278.802] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 718 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 261.9699 522 268.1965] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 719 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 251.3645 522 257.5911] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 720 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 239.0156 522 246.9857] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 721 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 228.4102 522 236.3803] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 722 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 217.8048 522 225.7749] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 723 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 208.9428 522 215.1695] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 724 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 196.5939 522 204.5641] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 725 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 185.9885 522 193.9586] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 726 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 142.8356 522 149.0622] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 727 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 132.2302 522 138.2295] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 728 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 119.8813 522 127.8514] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 729 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 109.2759 522 117.246] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 730 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 98.6705 522 106.6406] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 731 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 88.0651 507.153 95.8079] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 732 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 88.0651 522 95.8079] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 733 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 77.4596 522 85.4298] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 624 0 obj << /D [622 0 R /XYZ 90 720 null] >> endobj 621 0 obj << /Font << /F51 6 0 R /F2 418 0 R /F38 421 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 737 0 obj << /Length 5838 /Filter /FlateDecode >> stream xÚíYsÇ‘Çßù)ð8ˆÐ”ë>e™Þ L+a7ÂáõÃXbf°sˆ’>ýVuuueOWeQm3°#lHfvçïßuì‚úÿ² G/ŒÄIc.®W/hÿãw/Xÿ§¹·˜C“?_½øÓ_»`”8êØÅÕÛ‘“«›Ì”¼œ æÿ3ûËjñ𰹜s;»ö?bvuiÅì°ßl/Ùì~ñpùÏ«¯_¼¼Â)Î[L¦OÄ/,qZËþy´•„ ©ºç¹__úØ/·kp.¤˜-·[ÿþ|Öýî° ÿû¦{Ðå6<ÔŸþ*,pi‘ÔjÿÁ!¹œ3Ãÿãm“Å?ÿî(¯Üb™à91>qb÷kÜÁn 'žº iafÖB¹ÏôV`:ØáaX#ˆæšWÀ®–+ŸÙfûKüûî¡ûë>²¾ÞxÕm·‡Çý}÷ãu4Ô?жÿFÔUVé]›¬€! ¦Ž‹:+à g…… ¬´ ŒÙ.Þ«o¯^þ’þ­GðåëãàLR eÿñ.ÿïÅ?þI/nü3|ý‚a5»xˆ0'.V/81Zêþ¯/~|ñŸùwsàoòˆL ¢Œs£ýæå7ß…çüáÒªÙß'Ïé“)-Uë9“;ü9%ÖQ1zοøå%w³¯^t,8áVЇŒ«úÍï„Ëy÷‰³ð6)h²/\»HÌ ]ʼn¦ÎŒ‹™Ÿ.•™¥¢f· 2Ù{9ÇÒdíÿt[¡y$ŸNÕñAŒ /Ès¢*“ÝN)OÜ…\ =•–O¦ez¶Ä9Ù5ÂNÜ…°_ÔÝxÙ¬h<ê±»NÓ¬®éÆËfQcaƒª¥_Ê$Tõ66Ïn×AÊõzQ1Ÿ*¥Ÿ¸Œó?Ÿ0áDrêr*+RHvsh8•ÂÄ]׎ª+8Õ€E JŒ('`3j(ܼ nbçïb~Òµ§vñ¯ËRƒÙÿÑIw 攩æ7 ‘o&žó:ià '… ¤9#Ôz(iß!Zo"Tÿ[í{(Q5š¨PLŸV]6°I©j¢†j˜yŽ|ÔÀŽ Pû>¹2Úô îÿ¾dÌ·_¿úˤ˱”³ü/þ`36ù›C‡Óv¬ï´sÆÜøAc·à‡ Ìï~(5d%‘J¹SÕH®9,³Sw-Ío¸æ°°AsÔw—}§=/»Xš¼µ›Ö7pÀ¥ÐªPÄp*O¿UQåŸò×ä þÆxÃùca=e¯(ñcji°-¨¡Â_:â»éâlZ•5 ilÉÖe0¢‚ÈzCe€† 20ŽPÅúV†ï*/ö÷±•(f×›Ã: SìËcå¸:EþUÔ)UMÔÀA 3Ïê Jè G}Öð &‰aä0ÂV”XÃc!óu¤ Ÿ†8BY¯¿ÿ=¬û!“ýb[RT¡ŽaçÖ·lt1•ÐÄjΛ]LhXïbV!Ǻ®à ×ÉqÔ©N¨&ÚªñoM¼ëú–©Öxì&Üìz¹Û•$£‰0ÒûpD*¤§¬M{VØÕ‹”dÔ˜Ó¾P¡`1½Jd„Ó:ŽìþíÕëéÜóÿ^)™-ÿ`o%ù›C‡ÓÞ Ó¾åãÕ;zÀïcG%(õ«—?þX.Ìô‰ThUµ¼árÃNBïÃðð/åé!m¹9ßé¡!Í"<ät< 7\XØ -½òúe{ütÙ­·Þ!«ŽÑŽés,êSæšä!B‚¶NxÃÉcay%ˆcÖ÷×Ëõ®ÔÏä–(Áå™ö3Wµ’Û¬€!R-@VHµœáÚÀ¢mHA$U}3 õýÿ¼‹åB±(añ =ûˆ©·2ä°Õù†õÎÏ ·ÕÎô†v~ð°wxç§õ²¹0Ä£»ëô^pn½l<6^pba%Á³Ùü²RûqGŒÕæ¹`ü€ê2e¸©`ˆ(CP@o¸B°°A!œa­E׌v3­ÿ‡2y{ØÏ%ưص6d§I"ta²1ºÀN è2FlØç3¥ë[À‰ìn¹–X¯K[I”o(Q«Î±5œØ0Dy ƒîÐ.,leDžZ<·åÝŠ$îë0Ü^XR/‰pÊ>9úU¦)'M¦Àa ȘÀÎ ë™ò°-OË1ÒÝ~±¿ßÅ90ý±+o¥V¨³_ô˜Øâìêø! æªô/>3°·”¥ìþaýv»\ÞL>î·Ì¸ƩLÈ RVšD!‚&ù¢¡7*6PÕŽXiR5};_ܬú½ÅÙqË­|žK ¥°)`ˆH‘õIVè —6H@9"„*êù›Åͼ+ǽ ¡H_–ª•>‡¥Uî)oMîÀá1`Ü7œ;6p—–XÁìׇív—­Ï‡Fùª„^â‹{{Rè«”û,5!g;„1H9†8û #1`a‰ï¦™ðò!-cyì>îåM´4'VàWA§l5IC5L>ÆxÃacam"Ë\“¿[oBWû}±&÷wIŸ×¹I ¥°)`ˆHÁ$¼áÀ 0_0Óþ¸› õfjrßDï>÷òn4Ǹ~Ô5ÑC=$¡ÞpôXØ€žjbœ…äCÇl¾ó ¸â¶vF”µ§½f?変4Û!DA‚1 ÙΉéq2§ ·.WÝaeW^¡¯Ï·KÖÀÅ– a]#(ˆ 7ThØ «ˆ±,Wéûmh¼—† _>XÆŸ…PBJdSÀä‚ xÃ…€… B0ŠpÓ¡òºÛŠõÓ=c4œHa²ñÝ3Öû›C‡…=c’pÆÕø_]½ìޏøòÒêÙÕ«ïâ1xÅAæSðT[[”“ƒ.J@³8uWÔM« 7tQvâ_”ÐzÙüáQÝ5Vhµ^6GXØðiï>ì;JÆí;‘ï>cõ;=±¶„:õѸw×xÞЂ¤ÒŽŸ÷«î ÿËWRß^•*)屿“÷6ªò/ŒËËÌÔ]ãœè —76È[y )=´ÃB‰‡Øóë–O ‡Ôlãîƒ}¥DÖœï°îĦ€!"ÈDÔWBo¸°°AR#­¬‰ C7·íÂ&Èî‡ï»á“ÊÁvOê8Ï*Ú”š&Z`ˆ …™F&ë 7-6  §‰IÊkh׋UmœGQßÓÐüìÇy†6%  @"È>~è —6H€ûª[ôgß”$—Ê¥ÃDºSN‹ 嬯¾u§6?ä§É"|aºe}ô†óžŒÎEµ ó6­Es]3댫ð”Ħ€!"ÈY:½á"ÀÂPFŒ¯ç“nêNñ/oa;î>O»ßįÿæ¾Ê»ÒörÆwìsY‹Ue˜rÐd †0¥Cà gˆ…õ Ï2–¿!ŒKæÒaêqå\iPÏ÷Ä”´â,æ_SÂZ¼]7Ì>«¯v¾PØXLÏÚR¢Mur7é?Ã@wÓ-x^VÖS1GŸ !e³%`WD#eUÀ*„ã˜ãƒF„ÿ³3LŽïˆù¦vܧ.–G«Åõv³û"hFvË3F'Š,†ûŠ;fŒòozZG+_?+ÃÕŽ8®j…Â`7‡†1LÝuÅ‚*ÝÄÕnbBƒe „åW¬Ÿ-Z-ºM-ÃÑ%¡`¸[Æ?Ç áqpqË?5ÜäL­ “ÚŽ‹œ«çÞn œÝuWs1?UÌX¬ŒYZߢÇ<> ¨¸ñW‹³=`êwi#%¸© `ˆhòrEm?Um`±²6„%ŒöµÏ±6âˆìa}Zï•Æûç@=у‚3œ”°&k`ˆ°†ù/³~ª¬±X™57DQ¡ê¬a9ßüw‹þððÛͺïÞÇ…ZaÉõa¯‰Fom“¾Q¢ä'¸î*W¨é¥›õ30Dêg˜Ãé&ÅpT†ËÀ˜&¶_гZlßµOî–¾*¶îÜàÍ´ú6Ùg;= 1 îÈg7UðH¤ÌjÂ×GàãÈùj˜!4¹Ù&ž×‚_å1¾·þôÖ2d)5M¤Àa 3ÍÊå/pT¥Š°*N2q$>ž xsŸŽhÜ#pßÊ㊟Ñy;Ÿ!e-ÜаŽ{D`Ú×,¡£n4XÆm•/ŒûÃ}úƒ ñÌÛÊP‹`–?µŒ²ØT0D¡”û×ÐQUX°¬#‰4ýöWphñ·¸C5··‹ãâ”hîäç9.žsœ^»‰ "È`Ëe4tTE†ËÈ´ ¶•=&v³ S]ëãz¶r ¢³ÊžöHÊU«'ìê!˜øbã x©"FeÂJ®•."Žó˜‹wÅü“wšG[Jç+ŒÎÙ)CìæÐp’ì©»ò,‡¢†0%FQKp{3<èÄYq¡h.Vð7¥tâ®|to§àÆ[vÆ‚e KNtºIª¨áûU_Lt´6îÄuœ2ÔÔ10Dt >½¥}p†ê :qÖÐ1þ¦@ÇhЉ»ò)lŽoÙé –u,8¡Jš¢Žû~mÚæ?9²¾ëwg•–ÚJ”+Ìç¹$°Ê2å£É",az+-'à¨Ê –YrF¤ì˜°ÜnÞÄÃñWý€â}:^ë—n™ç~Ù÷ƒ±áf¦|«[„]ýÕü§whæ"ù‡)™®®îòUóËù‹ø¥pÅüï·‹õnq=¹+KdÔkù'˜ªêé›…:0D u˜±žTgh¡Ž8kêø›!¢A'îêc—­·ì„ˆËB¤”pÑߣ“NŒM-‡ÉƒÍ¶Ÿ[¾9t#šå‹­uüDW yj2†c˜vVn€GUÆX°±´ŽhѲŠKüJyØòéN³,µ%\ “Q)–’ÝN‹¥‰»ò“4†HåFQ 0“Y#è±³b±$­ ÔÑö›&»FЉ»r«:\Q(Ž¢–Þ´7k=vV~ÓT7´Þt¨jAÝUz‡}íÐxÓ¡ªAƒNœáUMãMs1„¸ë†ØE©j½%ç`¹ ·ârcFÅÐý±i똽†ìî6‡RSÇƺ'»}(g?%¤ "0a~e±3Ua«¬I”Ò†3âÊ·ÈšÄØ¢^/V=àÍÛ~¹ÂÐ[ÜÃ…è`qÃæÖ[Œw,øÞÉ¢ÓFqÄ=ì>¦ê3q—",ædí~ 4D°'«útTÅŽËй Š«Ø6]/ûÛGæÛå¡x-… §‰Pû¼Â¡G•²×$ òF¥ôŽªä±`™¼ê8;ëMê‘‚ŽÁcù¸m.Œ8ÃÉð!_MÖÀa Ó_î0@GUÖX°ÌšúæWIBïÛnJÃwB­¹}^„Šé¡ÏiSÙQT^×ÜTµ€D¤ #†:=ÒB_9w5óòö‡vw?ùŧ5¸C–Zt¡aï(é²8 Õ£Á2aË£’÷„×ËÛj¤ UÏK°”Ã&`ˆð‡Hdq(:ªòÇ‚eþ†éú›<†›QÞnëþöe¥Ô×¾Ô†ŸÅzò&åªÉ"œaêËå8tTåŒËœ•#Ö 9æ û\wËÅ#ŽÜ0"•'ºR&QI‰jB†d˜÷ dਠ –!KG¸5n 9ÝŽó¦pQÜ›®Ú_û° FŸ1M˜þô¥~\zù&8`ˆ€ƒ¹äÅîtT‡Ëà„ ÷´ª1¸aK÷bÛÿä \‡jçw83+‰¥OpV¦Ê8å©É"ŒaÚy¹¦ŽªŒ±`™1·„š~Ù\7“{X„ñïå6}ÝM¾=øån¸×ÈÎîºÓ:oÓõ(qÁúÄVY”öö„-Gê_;2VE–^»‰ "È`Ëë$ £*2,XFÆÂ‰õÌàÈâˆ&èìì—}bVX4\š¸×^:ê3»Ê¨Ê2å£É",az+,£*Ëã`•!knuˆÃ}×ÜF߃ۇÍw§¼öŠ—Œm×åÎ|g×0-O´³ÎUFµÇ¯¡a]ƒU}:ªi – ™ÿ¡s¾æ™¯Î9jò†_˜ò _à¨Ê –ù†‹átPFÜ–ƒ ®ÂM3.Ûý±£Msèpúx¾®ñÒ4ãÇ[þWJ–*ßÐfôyWÿ‡oo€ùG÷7  ¦îBþ‹£íÐOU³¨(ÍJêÕáXS³Éî£i8D4 oÐlk÷“Ä?>哦r òˆ˜X§îÊg@v⎪âCéâ4¬?‰CÍ›ý]lÒòÙ]?0–›–V÷Jåÿ¨ÄópÏ,¥±)`ˆHRÅ­¯ÐQUX°,æÂ©p¼oyâý´~¿Æ{Ù÷0‘‘`I¨ÐæœF‚‡¤5C8dP‡€ŽªÀ±`8õ?”ÜV€Ç]ÏiKRœü­O'ÄYOÉk‚†xÈ¢<ÈUÁcÁðÌY"Â6›2ø°†'Lòƒ±ÇÇ®‹´¼¾s½ñ„øÛ£iÀ¡¡¿I@Ló°jü÷5@ÃK¶AÃ: QÎÊ€ £ 4Xd}ÏRLKâm—Ë›´Öfùæp;:¾w8Ño}[ª¬$*TO÷$‘”˜&Ól‡ YfÅýÀM()ó4†0®õèO]3zù¾|ñçF?÷ýÞÞ×VoÖ{{#LÅc& Ÿª"°XYZÅÙôOW& oZ·Ÿ;¥Ì‰·ž?Í”æ‡ ‘/&»<öUÉ«Œ/3¡ˆ2öܾo.‰~Ö¼ïî]–‹-èóle©pF4—í†4D¤’¬êSÐQU*X°,ÆeIý\RÚ}7œT2š[ÚÇ»v¿¯ïʨ Ÿy‹¼Z¨§¤4 u`ˆê0ÇåOø©òÄbež”Éú-›÷ýüìt?ƒo§ÝN÷3„Ö[i?C¸ÃMiuÚ«m†Ô5?c`ˆ|ÆDy7tTÅŽ°[G,í7qæÀÈYêYݯßn†;²°3ÿ,%Ʊ“«ÖS¢ZŒ]1Ìz¹ùÜÔc‘¾Æùʺ߇óí ë^q=õ‹®Êg±²pâè'<‹5½|‹°«3ƒ™,w¢›Ììÿ6Gìaendstream endobj 736 0 obj << /Type /Page /Contents 737 0 R /Resources 735 0 R /MediaBox [0 0 612 792] /Parent 734 0 R /Annots [ 739 0 R 740 0 R 741 0 R 742 0 R 743 0 R 744 0 R 745 0 R 746 0 R 747 0 R 748 0 R 749 0 R 750 0 R 751 0 R 752 0 R 753 0 R 754 0 R 755 0 R 756 0 R 757 0 R 758 0 R 759 0 R 760 0 R 761 0 R 762 0 R 763 0 R 764 0 R 765 0 R 766 0 R 767 0 R 768 0 R 769 0 R 770 0 R 771 0 R 772 0 R 773 0 R 774 0 R 775 0 R 776 0 R 777 0 R 778 0 R 779 0 R 780 0 R 781 0 R 782 0 R 783 0 R 784 0 R 785 0 R 786 0 R 787 0 R 788 0 R 789 0 R 790 0 R 791 0 R 792 0 R 793 0 R 794 0 R 795 0 R 796 0 R 797 0 R 798 0 R 799 0 R 800 0 R 801 0 R 802 0 R 803 0 R 804 0 R 805 0 R 806 0 R 807 0 R 808 0 R 809 0 R 810 0 R 811 0 R 812 0 R 813 0 R 814 0 R 815 0 R 816 0 R 817 0 R 818 0 R 819 0 R 820 0 R 821 0 R 822 0 R 823 0 R 824 0 R 825 0 R 826 0 R 827 0 R 828 0 R 829 0 R 830 0 R 831 0 R 832 0 R 833 0 R 834 0 R 835 0 R 836 0 R 837 0 R 838 0 R 839 0 R 840 0 R 841 0 R 842 0 R 843 0 R 844 0 R 845 0 R ] >> endobj 739 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 684.1345 297.0286 690.3611] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 740 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 671.8828 297.0286 679.8529] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 741 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 663.118 297.0286 669.245] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 742 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 650.8662 282.1816 658.8364] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 743 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 650.8662 297.0286 658.8364] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 744 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 642.1014 297.0286 648.3281] /Subtype /Link /A << /S /GoTo /D (1) >> >> endobj 745 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 631.5932 297.0286 637.8198] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 746 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 621.0849 297.0286 627.3116] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 747 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 610.5767 297.0286 616.7037] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 748 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 600.0684 297.0286 606.2951] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 749 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 589.5602 297.0286 595.7868] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 750 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 579.0519 297.0286 585.0513] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 751 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 535.1187 297.0286 542.8615] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 752 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 490.9316 297.0286 498.9017] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 753 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 482.1668 297.0286 488.2938] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 754 0 obj << /Type /Annot /Border [0 0 0] /Rect [277.5739 469.9151 282.1816 477.8852] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 755 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 469.9151 297.0286 477.8852] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 756 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 459.4068 297.0286 467.3769] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 757 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 415.2196 297.0286 423.1898] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 758 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 404.7114 282.1816 412.6815] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 759 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 404.7114 297.0286 412.6815] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 760 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 395.9466 297.0286 402.1732] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 761 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 383.6949 297.0286 391.665] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 762 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 373.1866 297.0286 381.1567] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 763 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 362.6784 297.0286 370.6485] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 764 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 353.9136 297.0286 360.1402] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 765 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 341.6619 282.1816 349.632] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 766 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 341.6619 297.0286 349.632] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 767 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 332.8971 297.0286 339.1237] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 768 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 320.6453 297.0286 328.6155] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 769 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 310.1371 297.0286 318.1072] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 770 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 299.6288 297.0286 307.5989] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 771 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 289.1206 297.0286 297.0907] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 772 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 278.6123 297.0286 286.5824] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 773 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 268.104 297.0286 276.0742] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 774 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 257.5958 297.0286 265.5659] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 775 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 247.0875 297.0286 255.0576] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 776 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 236.5793 297.0286 244.5494] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 777 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 226.071 297.0286 234.0411] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 778 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 215.5628 297.0286 223.5329] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 779 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 205.0545 297.0286 213.0246] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 780 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 194.5463 297.0286 202.5164] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 781 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 184.038 297.0286 192.0081] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 782 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 173.5297 282.1816 181.4002] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 783 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 173.5297 297.0286 181.4002] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 784 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 164.7649 297.0286 170.8919] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 785 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 152.5132 297.0286 160.4833] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 786 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 142.005 297.0286 149.9751] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 787 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 131.4967 297.0286 139.4668] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 788 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 120.9884 297.0286 128.9586] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 789 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 110.4802 297.0286 118.4503] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 790 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 99.9719 297.0286 107.942] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 791 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 89.4637 297.0286 97.4338] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 792 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 80.6989 297.0286 86.9255] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 793 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 668.1817 522 676.1518] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 794 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 657.5762 522 665.5463] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 795 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 648.7143 522 654.9409] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 796 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 638.1089 522 644.3355] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 797 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 625.76 522 633.7301] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 798 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 616.898 522 623.1247] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 799 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 604.5492 522 612.5193] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 800 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 595.6872 522 601.9139] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 801 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 583.3383 522 591.3085] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 802 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 572.7329 522 580.703] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 803 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 562.1275 522 570.0976] /Subtype /Link /A << /S /GoTo /D (8) >> >> endobj 804 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 551.5221 507.153 559.4922] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 805 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 551.5221 522 559.4922] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 806 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 540.9167 507.153 548.8868] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 807 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 540.9167 522 548.8868] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 808 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 530.3113 522 538.2814] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 809 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 519.7059 522 527.676] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 810 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 509.1004 507.153 516.8432] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 811 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 509.1004 522 516.8432] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 812 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 498.495 522 506.4652] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 813 0 obj << /Type /Annot /Border [0 0 0] /Rect [468.2436 487.8896 477.459 495.4114] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 814 0 obj << /Type /Annot /Border [0 0 0] /Rect [483.0906 487.8896 492.306 495.4114] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 815 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 487.8896 507.153 495.4114] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 816 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 487.8896 522 495.4114] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 817 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 477.2842 522 485.2543] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 818 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 432.3878 522 440.3579] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 819 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 423.5259 522 429.3042] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 820 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 411.177 522 419.1471] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 821 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 402.315 522 408.0933] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 822 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 389.9661 522 397.9363] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 823 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 381.1042 522 387.3308] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 824 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 370.4988 522 376.7254] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 825 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 358.1499 522 366.12] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 826 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 347.5445 522 355.5146] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 827 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 338.6825 522 344.9092] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 828 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 326.3337 522 334.3038] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 829 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 315.7283 522 323.6984] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 830 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 272.5753 522 278.802] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 831 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 261.9699 522 268.1965] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 832 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 251.3645 522 257.3638] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 833 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 240.7591 522 246.9857] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 834 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 230.1536 522 236.3803] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 835 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 219.5482 522 225.7749] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 836 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 208.9428 522 215.1695] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 837 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 196.5939 522 204.5641] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 838 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 185.9885 522 193.9586] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 839 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 177.1266 522 183.1259] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 840 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 164.7777 522 172.5205] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 841 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 119.8813 522 127.6241] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 842 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 109.2759 522 117.246] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 843 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 98.6705 522 106.6406] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 844 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 88.0651 522 96.0352] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 845 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 77.4596 522 85.4298] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 738 0 obj << /D [736 0 R /XYZ 90 720 null] >> endobj 735 0 obj << /Font << /F51 6 0 R /F2 418 0 R /F38 421 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 848 0 obj << /Length 5903 /Filter /FlateDecode >> stream xÚíÝs·‘ÀßõWð‘ª2‘Á7ðxI9wN•}‰%?%yX.Gä–É]z?¬8ý3À wÝ -å,rY®2¥U³{§ Ðhü¢ ÿñ ß]X)™WÖ^,Þtéãßðô§« qEþøþÍþ¬ùï˜ï<¿xÿáHÉû›¿_~³¾yË/û·Wüò_o¯¤”—›ãÏ?mÖá_–ñ_úÇý.|Øë.µ~ûÏ÷yóõûɬ¢õÅ¢Èü›‰ Ǽ1*}/ããRéá{=¾½þr¾Á*~ƒõÛð·}¿ ßBÉËÕnü¹ÞìãD–^1w¹Ÿ~évü×ýf¿ëã'7‹ýbüÓ. >.â“öñÁþðgéÀ×âV°Núø ñ[± m9öãÄ/ÂYæ¸åÁƒÃ?çLrWPp桹ºøŸ™õ–u™#³&“m6‚±’)ío“]¿Û/¶é£!¾Âχ!²6Û_F‘ëûøA—‘ã5Ú3k:õ$á‡x:¤üMH@€}& h£!Qf#$#Dù+EîïÇ¿õÛíf[q¸ë˜“ÞþvÿªâsÿJ;y« »È¬ë©öXtѤ ›´!B‡Ú$=µÂ›Cèæ‡?=}`~£†Û+f­6Ï7J6»§‰l¡·)¸@M—2ñ*èsý+ð†×ÞÑû oͼL{î¾H¾(Ñì‘&Q H…¦ˆm4QÊl$*y Þ=áõ¹ëûñÃë2´ÚáŸ+ ­aRXþ\»åñì±&q H‡„ʼnm4qÊl$.8ãÂûâÛýâz5ŒrVûøòý¥Vi¦„yæ\?ß ,;²@ÈE´Ñ@™f^FøÓwõ0éØ Àõ}þ.nÆ?°åøóWAvˆ—~üè~ì3ú«·< ßâÿ¯‡1óøf¯uúÂ1©ýÿggòÌþhò‚Oè^j ´Ñ<)³‘g×ÞN}2Ïõâ!1M]û:CÏ4ÿ"f4A!ô(…h£RfBí|@œ²Û~1¹OóΞOØúa‚:MO‡ÁUmDDHÿeõؼéá[ð  ïÈ—D µ‘ðH³žõ®I/Ömj4±;³ »¡%.nsJkW!¦=óöùÎh?…~ö^“>$èCJâô6š>e6Ò7.D‡áÇôûaüs…´4L®Îm0õÄ`ÈÎl$‚²Q Êl íB°èô*Þn®ï‡ÿPkò2|I¯ük T!;²@È…  Êl eC (“a|‘÷ã˜ìj•^ç9Gr¿¹±2ª—‹ý]-F\òËivI)$BKâ5´ÑH)³ih°<ªÒÛíâaÄ·|‡dµ•­Y§•{ùm…žÖ„ è78t †N™Ð… A!9„>ŒêVëÛ:oá=cÞÙ_MÞ@à ÝÏ5Îh£ySf#onB<ˆ´bµ¿ S±äå= __Þµ ÈNl$‚2 ‚S³V\pŤ2"…ršy§Æ9äßFþð»uW\2ïC×%~:Œ»ýj³®F‹ ÝÂë¿,Êòàê'dS¡ ,“Tc¤µ‘ÁBš¡b8S.¥û~: ù¶eœüý˜–Oâ1…k ª©u'?ÓØ˜ÑL‰Î§"A‘å® à<(fê¢ñQTFÇÄ©Õy"9“¡Ÿ,~ßì@¶‹jY.μÛxú¯£ ·…qíL–j I 6:˜(³1”:Ü6 N =ïÂ?Z9I%?½ùû?»‹›`õ/o:&áãW`ÜË‹‡7‚Yf9ã_ïß¼{ó7P«—´]u³ï×ë…±üè›­ÖÆJ©Ìåã}%¢…ešË3œY} ¥Z(f1Òý3eÈ\È Æ]耮Zf1Úæ©²hó+¼ÉÑYZiòDYcô×xÌÒÜ›¡µIoBkÔã«b»“1 9S jÅ÷öµ›~òoòq+>   GÈ”B#j#C„4c$ÌœNµ®9F†qÞ]_í÷<"†ç ¡2:B(«1B¬” mcá¨ô»Öˆ~>Š×ãBáXXõUZ‚«c5rªý8üB5-ÌUøfÚ|îNmÀùñš  zKàs6¨ÆC™xŒ ød¦s´Ø^k¾. [Ükó}Jd$Ï6£Èq0ñ‹¢‹Ž Âf fp:ÕžFÅÕró[g­:N‡¡´9£\ Ê>;° ô!b%j£ùSfc(â#ÕànûåâþhóG%­¦RÊð×~ ŠìÔfPA"( #bö µÑAA™A!eš.¿É—‡íXR·Y×W|Ư‰ÞZ$dO6#‘ÁóP ”Ù B0§RfyÛ§ɼ¬lã¾qóÞ~•V–µE&ÖÊg,(ßìŸ&_ Hð…îÄÛh£ùRf#_.˜T>¿ÿ§¼ýf{4xK寷‹\ƒùŽëÅm•°gyF½J6{¦Id¡£1_Úh²”ÙH¶ã|*çÝöûÃv«377 3V‘é½|¾ôb…N™ž¡—å® àœÞL2*7–ɸmj«ÑËr ³3uõÌcΉ¶vʰÒVgêáFN‹¶vJ²Òfgêè4këaK»¤­žªkN·¶´KÊlh—ÂóÐn­%ÚåÐÃî·ñmº>º_ÄEöêj™‰õ”üyÔ¼OÞBqtGž$’äP‰Ž4ÑÅ-ØÊx€ŽÝ•-%÷}}žÜi~öÓäÉuMô@@I3"¨FO™èmWºÇš¬mÚ : ‘òî¡}Ìiþsœ}­¥†7‰³þ ·:Lžk’‚y‚X÷€Úhò”ÙH>Œ‰œJUÔ'䯖ÃÉ,±ñß6ú«™uÖ½Ðm““š úœ‚ ´ÑOÍÎjW„ðÌvv¬px׬]Ù]o«‡¢øXAçζ»ÏãeÁC¸sÙ}9|ð…œG,]äЛ´yªŒx7sw“&O• ‰W64st“6O•ÑCîÆc–ÆMš-(7ÏìP’)n_Hõ ÖO¾iuÂPï…\ÍÚ Cmd?L›©£{âÖÃN]1mu¦9§$÷Ÿ­‡zcÚìLÝ·vjµ «§ê†Mex—ÜzةՒfc«u*´ê´Š1¶Úíϱ­¦ƒ3ƽ€ÃþA?ì37¤ÄÈM}¸½­oEª4­yV‡*MÞhÒ‚Mè\‰/!@m4MÊl¤ie9§5‹‘fZH¥sÏëeÌa-¦CwbYAc)!„3FÿîÅà(¹üäMr@ Éñ|ÔF“£ÌFrF2Ñ¥5‰L.®à­o‡´#»IkyO(5Š)åù%8r™ÝäÅVÕÄ«öŽ à™-¨ŒÊj -B¤x-šÎ0Dëøù¦8'pÙ‘Í8‚D@.DetPVc¨ðêì¬=‰ƒÃ#xëNýÒa»Æ´z™ã꩛Ύjöú@èõ¡ß©^h£ASf#hÉC ¤ÜùîÎ…«·Ù½÷Ô#!{² @ˆF#7 ŽÊlŒÁC¤¤\úîn±Í'n§ÛÅrU–$?®ö)\â±N7×È<Œ^#ðì‡&G Hp„nD× ´Ñ)³‘cÜ4Ù¥tùîn@–O“>Œçp^Õö­4ÓÞÉ×S.ºìÉf$A" ªEmt$Pfc$t]ˆ”t>LèÛãÁ”ûx­À&þñc:yg³E{«Û8)«7Î]§^ZÆsòP“0$C‡+üÐD¨&L™ „]\¦’ž<$²óI¥ t¯BY‡çx†Û­1¼Ù=-º@‡ }Íñl6ÐE¢¥lÆË@|/9F6-Z,ûÍÃb¿ZÖ‹k;%^L“Í3¡ì˜Ö¼ ÈáÓ*èeüP ŠDJ™”\1o¹:¾%äÝ7ÿý??üµ^F¯1¯#mxŸ sV§LëÞ–I޾@e®®ÞkÇí2+[†ktHc¼.¤ëDÆÿÍwïkøe¬yÝPMFAöd3 €  @”±F²Î¤Ù0½Æ]ãi9©·“ªü¯dX-J¼¬Ú”tòVt‘#8×#˜‹”2a©@Ö‚iÉ]nêï#篿ÿÿ¶>ùòÚžûä«pÊÞkR‚vá¡à)c…¼âÌ{«AûþwoÙ’C¡(¿,·l=.n{d‹”z†÷‰ T³gšT A:šû*U ¥J+T%gʤû¤vãÆØ}./Ùné/Ø%?ñÊ:þ"³á…GvQ/$ðB YÅ ¡x)c¯è˜ÒëÒÇö¹=¬×y\eÕ+ ýŒ8»C ¨ä»&ö"GP T½M5(sÂRAÎ;&§"ÞÍa»Li’å¸ãý¦š$#¯ó;÷EŸ}Ød øɼhp ¡ø)cí=s¦33þ7}\à^¯ÆÒþ͸õª¾Âéµ{Ù}úä¤`(ˆ>òy0T„&ÀÎ3)LzeïðTRpÏiuƒŽµçpEÅŒº íFÈâ9Œz’»‚‚ê§ê¢;]:ЃB§lè6Àó‚gè§çÈñpÚ»¾DƒŠ›*«<¹xÛÀsªgA›qöJ³A¢C'Ë:Q %J+DcB§í8€è°dÕïáÅÒÕ=—N»³­H*IJ›‰€L¯P„e¬€¶Ì irÄÓÛÀªçhéϹÏnkvâ@èÄ!…z“zPâ”­B< ³¹óªŸN#ÏG®$Pâµ<©Þü³C›ÍÍòáõæ¡Á@+Á Ï´æD0”ƒi6Øv€ÐÓhõª[PÚÙcMÚ@  ÔólPJ›2Vh‹x7E7&Þ½ÿßõû¯OmÊxW—EúÓŽýÎê® ¾ùwÔœuB¸“ïøõ×ñ;~7ûŠÖ0_@Ÿë;f}/i=3ñ, £/ù§Á?„&óÝûœäXÈõÜ›Çé°®êÑ"ñ, £?½í ñ ˆŽWêÉçêê;¶†xŠÐx%Ý<Å+×L»¼š·ßÞë'¨*~F›Á?¥óÊm$‚ò™2P„e¬Cï;yÜr|pÚ¸2®ãñ>õBk'X§”y!µ;…DvN,$ÀB_ÏÏÇÀE(XÊØVy@U°yUì‹ØoÒñ/µªïX˜øèçŸU˜¼Ò" q¢GNæÕ)T„%¢N2ïrõd!Z? /ô߯›×«hžÐÌ'Ç6ƒA9Õ„ "4((c%(¬Œ[ÓÆ§_ÆýÃ,e%—)Ïü¾~pb‘ãKc¿Z{¼¶¢}……Œ§uêl‰óç0P³Î⫽Yî Î#d¦®z1…î,ã'FkA’ÄZ6O”UOV(±ÛxÐÒH£3uCʼ:m=åÐ(c¥!pÇt˜]ÖÃ<íªoqö(_¯ã;Ž…ìÏf,A" UºBEh,PÆJ,tŽua>1vŠC®âûoS±éX|¸«û~t˜óœÅâ Ê=û®ÉÜ!Šz"T„r§ŒMÜ¥·LÙnÌÚíû]ÜÅŸ¶Ýõ󣼫Çú“1ÅI&/µI  ¾HrätS õ`€I[°3ÌK=¾QÆ›ša"<ÝÚ1.r÷uôïi ï:×/^¢''f­‡“,qpel«}<í·‡Öà¦gj58(ˆ7¸#‰ê:T„ò ŒÖ0Õq x\å5ŠDfœd-W¤³4Rð°[¯–2-Þ~ÙµF(Òì–&R H …^–Õä.T„"¥Œ¤F3g¬Hwõ{päë†FdW6ÃaɈj®*BÀ2V „¤”cbj¿LJYÑGgÄ##µ/-£;ù¥ÉL¡›‘¦ ¡L)c…©R̦¶Ž‘¶;éZm-3þÙoàAI'o5A9‚3p=‚¹¨A)– d©˜0*½’cN>,˜ðÞ »ú†,á¼z-ôN̲'›‰€`æ§z1¡A@+Q $³²ÓXÀí•@àŒû³=ö‡ìÓf<A" "$€"4(c%¸ HÀâa|ܬõ²B¡…9ŸÃ £ì¶&r H ‡ä@Šœ2Vdz¨pâÃ]®””=ô¯×vRÉyMîEŽÀH Ô‹:aibÏùà"Õ(Aß}쫤…Vò QO>k±†‚8ì#õ2q¨ÃM+¼Ã,K{™_óCRk3‚¾^¥ä¶;WKÞñþ|3Ý“óšà ²ÕL7T„‚§Œð6N¯½¬€ß݇hÔ’6q×®Õ¯I**²g›Q‰¨€ êµP”±¦cZ¤Þ`{¼ù¯ìkaÓM×;d^ÿì·¢|“šx‹A8¼^%Ô l K­Šw“vî˜íQM¸C±z²†5¬ë^j¶fòO“+$ÀBw#oq EK+l¥gJ§zÝÀv½[,§qùæ ºØx܃~ö×J+o™—Ö‡ÔaNrWPpæß¹:¤™¦"¨Œª¸!ΔÑ7'aK©Ã7©¶žr[ÊX [>"A¶«||ò~“Ö ¶}ÎoûŸ‡ÙÍamßbïƒöç(Óì—&S H0…nÕT„2=5†Tõò0×*å† ªzG‰Ã*õ¢óu¼xò9¸¹&-çŽowõ»¼6úeŸï¯„Á¯á.‘äðÀÈBøÂPƒ…e©Ä„pâ ˜ñõMŸ6V}è×Ë´Œ;^ †ÆÓ Z¼p´ÙGM¶@€ ]^Oé@E(^ÊXá«SK-z ÆF§G'ÞonëæùÞ@…Í^i‚Qèäú:¨%J+D%gΪq¸®[7ω˛!%“1¹xqìÇSqÍ" .Rö&–-×FÅ‚³Ž»ß/—‹ÒËhÒ‚=èPY§¡ô(c…^pªT©®õSè•+Ýe}RÃ5ëÔï¿Î†RÌžhR‚EèX„"P„R¤Œмc®Óî×S,×ýÄÍ$·ÃÐ*·^§AV­vLüž;IP€Ù M€@}ŠŠP€”±0Þb¹ÁîóM‡ýêèvÍj^[JÿB “ŸšŒ Áº]VËú¡"”1elb¯‘©°õ°;Œd†ôcº9܃jóþ_Ãñ8ùÒÜ>}<Þ»z_®Ô]€ƒ.«ÅþšI£øìøüÄ-X@gÝW¥5)ÊÒ ^òûù5R2¼/ù”ã_²:ú¢šµ°GßíÛoÿ믥ïŽÇ¾€½€›Ç¡z¹2‚v̈/æÄj,tèû`JèP>›)Ã’Õ»`þaYÞ#endstream endobj 847 0 obj << /Type /Page /Contents 848 0 R /Resources 846 0 R /MediaBox [0 0 612 792] /Parent 734 0 R /Annots [ 850 0 R 851 0 R 852 0 R 853 0 R 854 0 R 855 0 R 856 0 R 857 0 R 858 0 R 859 0 R 860 0 R 861 0 R 862 0 R 863 0 R 864 0 R 865 0 R 866 0 R 867 0 R 868 0 R 869 0 R 870 0 R 871 0 R 872 0 R 873 0 R 874 0 R 875 0 R 876 0 R 877 0 R 878 0 R 879 0 R 880 0 R 881 0 R 882 0 R 883 0 R 884 0 R 885 0 R 886 0 R 887 0 R 888 0 R 889 0 R 890 0 R 891 0 R 892 0 R 893 0 R 894 0 R 895 0 R 896 0 R 897 0 R 898 0 R 899 0 R 900 0 R 901 0 R 902 0 R 903 0 R 904 0 R 905 0 R 906 0 R 907 0 R 908 0 R 909 0 R 910 0 R 911 0 R 912 0 R 913 0 R 914 0 R 915 0 R 916 0 R 917 0 R 918 0 R 919 0 R 920 0 R 921 0 R 922 0 R 923 0 R 924 0 R 925 0 R 926 0 R 927 0 R 928 0 R 929 0 R 930 0 R 931 0 R 932 0 R 933 0 R 934 0 R 935 0 R 936 0 R 937 0 R 938 0 R 939 0 R 940 0 R 941 0 R 942 0 R 943 0 R 944 0 R 945 0 R 946 0 R 947 0 R 948 0 R 949 0 R 950 0 R 951 0 R 952 0 R 953 0 R 954 0 R 955 0 R 956 0 R 957 0 R 958 0 R 959 0 R ] >> endobj 850 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 682.391 297.0286 690.3611] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 851 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 671.8903 297.0286 679.8604] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 852 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 661.3895 297.0286 669.3596] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 853 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 650.8887 297.0286 658.8589] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 854 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 640.388 297.0286 648.3581] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 855 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 629.8872 297.0286 637.63] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 856 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 619.3865 297.0286 627.3566] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 857 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 608.8857 297.0286 616.8558] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 858 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 598.3849 297.0286 606.3551] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 859 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 587.8842 297.0286 595.8543] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 860 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 577.3834 297.0286 585.1262] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 861 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 566.8827 297.0286 574.6255] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 862 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 556.3819 297.0286 564.352] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 863 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 545.8812 297.0286 553.8513] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 864 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 535.3804 297.0286 542.9022] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 865 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 524.8796 297.0286 532.6224] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 866 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 514.3789 297.0286 522.349] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 867 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 470.2465 297.0286 477.9893] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 868 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 459.7457 297.0286 467.7158] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 869 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 417.3568 297.0286 423.1351] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 870 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 405.1125 282.1816 413.0827] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 871 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 405.1125 297.0286 413.0827] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 872 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 396.3552 297.0286 402.5819] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 873 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 385.8545 297.0286 392.0811] /Subtype /Link /A << /S /GoTo /D (7) >> >> endobj 874 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 373.6103 297.0286 381.5804] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 875 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 364.853 297.0286 371.0796] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 876 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 352.6087 297.0286 360.5789] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 877 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 343.8515 297.0286 350.0781] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 878 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 333.3507 297.0286 339.35] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 879 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 321.1065 297.0286 329.0766] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 880 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 310.6057 297.0286 318.5758] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 881 0 obj << /Type /Annot /Border [0 0 0] /Rect [258.1192 300.105 267.3345 308.0751] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 882 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 300.105 282.1816 308.0751] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 883 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 300.105 297.0286 308.0751] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 884 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 291.3477 297.0286 297.5743] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 885 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 280.8469 297.0286 287.0735] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 886 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 270.3461 297.0286 276.5728] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 887 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 258.1019 297.0286 266.072] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 888 0 obj << /Type /Annot /Border [0 0 0] /Rect [258.1192 213.9695 267.3345 221.9396] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 889 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 213.9695 282.1816 221.9396] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 890 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 213.9695 297.0286 221.9396] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 891 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 203.4687 297.0286 211.4389] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 892 0 obj << /Type /Annot /Border [0 0 0] /Rect [258.1192 192.968 267.3345 200.4898] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 893 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.9662 192.968 282.1816 200.4898] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 894 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 192.968 297.0286 200.4898] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 895 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 182.4672 297.0286 190.4373] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 896 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 171.9665 297.0286 179.9366] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 897 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 161.4657 297.0286 169.4358] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 898 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 150.965 297.0286 158.9351] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 899 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 140.4642 297.0286 148.4343] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 900 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 129.9634 297.0286 137.9336] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 901 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 119.4627 297.0286 127.4328] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 902 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 108.9619 297.0286 116.932] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 903 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 98.4612 297.0286 106.4313] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 904 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 87.9604 297.0286 95.9305] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 905 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 77.4596 297.0286 85.4298] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 906 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 684.1345 522 690.2615] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 907 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 673.6002 522 679.7272] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 908 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 661.3225 522 669.2926] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 909 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 652.5318 522 658.6588] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 910 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 640.2541 522 648.2242] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 911 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 629.7198 522 637.6899] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 912 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 619.1856 522 627.1557] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 913 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 610.3948 522 616.6214] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 914 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 599.8606 522 606.0872] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 915 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 587.5829 522 595.553] /Subtype /Link /A << /S /GoTo /D (8) >> >> endobj 916 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 577.0486 522 585.0187] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 917 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 566.5144 522 574.2572] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 918 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 555.9802 522 563.723] /Subtype /Link /A << /S /GoTo /D (8) >> >> endobj 919 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 547.1894 522 553.1887] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 920 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 534.9117 522 542.8818] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 921 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 524.3774 522 532.3475] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 922 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 513.8432 522 521.8133] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 923 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 503.309 522 511.0518] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 924 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 492.7747 522 500.7448] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 925 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 482.2405 522 489.9833] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 926 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 471.7062 522 479.6763] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 927 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.5453 427.3294 507.153 435.2995] /Subtype /Link /A << /S /GoTo /D (7) >> >> endobj 928 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 427.3294 522 435.2995] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 929 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 416.7952 522 424.7653] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 930 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 406.2609 522 414.231] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 931 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 395.7267 522 403.6968] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 932 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 385.1924 522 393.1626] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 933 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 374.6582 522 382.6283] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 934 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 365.8674 522 372.0941] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 935 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 353.5897 522 361.5598] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 936 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 343.0555 522 351.0256] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 937 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 332.5212 522 340.4914] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 938 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 323.7305 522 329.9571] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 939 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 313.1962 522 319.4229] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 940 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 302.662 522 308.8886] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 941 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 290.3843 522 298.3544] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 942 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 279.8501 522 287.8202] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 943 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 271.0593 522 277.2859] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 944 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 258.7816 522 266.7517] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 945 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 248.2473 522 256.2175] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 946 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.9376 237.7131 507.153 245.4559] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 947 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 237.7131 522 245.4559] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 948 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 227.1789 522 235.149] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 949 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 216.6446 522 224.6147] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 950 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 206.1104 522 214.0805] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 951 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 161.7336 522 169.7037] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 952 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 152.9428 522 159.1694] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 953 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 140.6651 522 148.6352] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 954 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 130.1308 522 138.101] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 955 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 119.5966 522 127.5667] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 956 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 109.0624 522 117.0325] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 957 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 98.5281 522 106.4982] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 958 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 87.9939 522 95.964] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 959 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 77.4596 522 85.4298] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 849 0 obj << /D [847 0 R /XYZ 90 720 null] >> endobj 846 0 obj << /Font << /F51 6 0 R /F2 418 0 R /F38 421 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 962 0 obj << /Length 1510 /Filter /FlateDecode >> stream xÚåšYGÇßùó’i÷}<æX?XJ¢ìâDŠãv™–Ù à•ýé]=S0Ý=qEÚÅ–Eƒ‹ªžúýû¨nXFá/ËÍŒÄIc²»‡m>þkÄšÖ,¦ØäûÙèõÅ2F‰£Že³û'³Åû±Ò“©`ðgüãÃ|³)&SnÇwð™ãÙÄŠña_”6^Ï7“³·£«Ù1œâ|¨CÞ¤ß#žYâ´–M´•„ ©ªþ¼»¹:Ã(˜Ke;Cpô÷èýš- èÛ%Âj–=ùæDö0âÄh©›·›ÑÍè×®SGSì°×3Æ8JéÓþ]_M¦l<{wýs¯›JÁûϺÙúè¦ÒÄpîN»ùÓwîÆ?\O€æ/¾Ç7€Tòñ]±½'+ßãâq¿.¶þ1^¿31Ðdºá]øºa‰Þûð,3Üq"9u'™„UÿÔr´K?qß]%ä~TC(·ú$j@£G»tT/T#ü«Îa—û¼–S?8|kQg¸joëöÆ·‹åŸ”ÉM^'ýq¾‡/¬Y·–Xãþ}Ò¿ê…û÷ÎÓm ±Lð.KÈ­Ýö!÷Üù´§Œ¼¥)§ÂzÊZθm(×<—5Ðy q‘ß–˼¬?|òëýª~·xðoa*­Ø7ÓiŸ6ãŠ@õÿóŽrkŸ{2LpÃiä‰Ñ‰¼¥¹¥Âzn fSÅklûõ¦¦â§ÁOÍÐ+‹e9ÀÏÒö|ÆÞ?‰Òn²5»³K°F© Ô¯4éDLZrÂK>ìª1¸„™6àVŒPc_$î¯ñm"E€ *À\„ŽËyKë Ö A0b•q!|ôûŸ¼¬äÞë(K³îk!J¿ÍÞ }d˜ a§¼¥éŸ‡5šF’O«¼lfú}Që㶪òå:T?jJ”„õÒ¶ ’&™ÖšpeED'G»)6ìé¤ïΧS‡®œ°ŸØ•S2V' %ˆÕ²ïç†fÁ_Í·Ëö\Z½Ô•/s½ Î‰±Rw©‹Qoì¦Ø0@ýÜO§tAìÈQ{*X‡]úu›°—‡ív]Ÿõ‹ñ®9Á‡±ÿZü9l1´y‘‹Ç¥MÕ fd˜ÀŒ3ÁŒE1§‚u˜¹#ÔhVcö”‹ÃfÑ\}zªÍfà©Þëïóz¶Ï˲(C×sŽ0Åõ³½Ÿë ´ydŠ Lqš92EŽ¢LSÁ:¦ 6ö–7LpÕ)…µºzËwøôÿd%?½ \|CnžÃb…Û&h.2LÀÅùæ49ŠÂ=Ù«)ãë6ˆëÃý1¸Wûœ—ÅîUøì\øW?n¨Gû}hþÖÐ|öç¼1(e‰ñ×ËC:À†q­ª=¨ì(¦ƒd°NPÑ !ëRáó®ùµÊn•׈,¡°ÚñK;³?§@9Ô"PžßÚM±a~Ï]xKN ,Œ§ACü³¡˜gÎ|ÈWq•> endobj 964 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.4209 682.391 297.0286 690.3611] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 965 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 671.9302 297.0286 679.9003] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 966 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 661.4694 297.0286 669.4395] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 967 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 651.0085 297.0286 658.9787] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 968 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 640.5477 297.0286 648.5178] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 969 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 630.0869 297.0286 638.057] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 970 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 587.9895 297.0286 594.2161] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 971 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 577.5287 297.0286 583.7553] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 972 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 565.3244 297.0286 573.2945] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 973 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 554.8636 297.0286 562.8337] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 974 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 544.4027 297.0286 552.3728] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 975 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.8132 533.9419 297.0286 541.912] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 976 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.3923 664.5148 522 672.4849] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 977 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 652.1208 522 660.0909] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 978 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 639.7267 522 647.6968] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 979 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 629.0761 522 635.3028] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 980 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 614.9386 522 622.9087] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 981 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 556.985 522 564.9551] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 982 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.5453 544.5909 507.153 552.561] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 983 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 544.5909 522 552.561] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 984 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.7846 532.1969 522 540.167] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 963 0 obj << /D [961 0 R /XYZ 90 720 null] >> endobj 960 0 obj << /Font << /F51 6 0 R /F2 418 0 R /F38 421 0 R /F72 9 0 R >> /ProcSet [ /PDF /Text ] >> endobj 987 0 obj << /Length 2900 /Filter /FlateDecode >> stream xÚå\ÛrÛH}ÏWèQª)õ²¯$;—ÙJ&©ÄÙ­­Ý} mEVE]ÿ~ÑW‚Vw3sÉ&öÔTE& Îi4€††Î øÎêbVrNjQ–³‹Ý“ÂÝþü„º¿– ±Ä"ÏΞüí…¤3Zº¨éììÓLÒŠÔª.Ug—ÿžoÿ=ûû“çgA•dlʘ9¶V²- £RhkðT%åB;g‹šÏ›óí‚ÎW‹%/å¼ýd_OàV»_p6ïWðBç=Ü8èeu Â…bZ'|GAI!5*OAŸß¬­ž7ÍV_o[¸dó {óõæ¼Ów›îÎj_ TÖ„3!@µÖH@T©ÑK»ùÏþ‘ä³{  ðKÍ >S‚“¢ª„F¾©yŒ rK,às¬Pû‡Ù•ÅÈd„,ZdÊš& 0µ,êÊÙYRÊ4zá®1Þ9¾´úâZæÎ<ß;4ûKú…¡ÆþL‰œè‹vinö{uˆ1ƒ³šP©Ž˜‘t¼ÿü“ŽG‚YÇc‡ð¨ã‘¦¤ãóÖÀñ²¬ç”;Ì9þT{fu¸èŒ‹®½§ÜÂÕnñ¾XÔb¾jz}ë¦[î!ñªÕ úÖ^¡ÖþýÒèõ×WVVõlI%D”‚™OòÁH7 Á¾7€^Æ’%¡ôá­ào¤b„ƒƒ¦hˆär,ôbÚ·2FB¤'ÅÁû¦ÆÛ- .fRú’Ù]‰Š¢Ð b•afghíŸ?ïÍ.¡©Ñl·úŸ÷Wnwçø5wB܇] •°5±"Æšò«aø¾7ÿˆ–#òîG¤Øãä–X0‚é±Â4¦$òÖƒ T.|@Hqz¹êû&ËÚ’äCßt½å‰(æÞí¨c)O®îSh¡÷ž‹* _“ÕŠEIn8ïNRcË2¥¢Äô$y‘5hAk¢¤ßàw¼xÖ˜è±p/,Þ§+s6½ë…ÎÌ~œ0‰*¼ž-*>_u»ƒo4©^èG7p½¿Ðï;ÄØÂlT¥ø1cNuï¼IØ‘`wŒFiJ"Ÿ·FáqU•õLŠÈ¢ð› ÛÊKöþ½Ê›­…ö¿¹k»»Ið]Ri‰o¼FÌ= @Ä%ûÁ(ÄÞ;o{$˜Å£ÇiJbŸ·°5gäý~KUÌoZ+X±ÍV‚^çwáp}£Áõb w[Í~Ø4Øü<óùSŸ‚¼ÑɈIRàáŽ}dãi'‡’¤P²ú“É‘B×¹g ÛA,‡,òuÃuÐ’B5kLJrQ„Öµå"lñûU×lC(ÖËM¯#²-JÆC–XÖDHö¨·w^“¾ïàÚ!¼Ü Æ(q¤ÐôE”HU’ysª$…¨”c†LUñÜÎÜ:¹òËóB¿é³£Í¿tàool!ªùóN¿§]wÍ.â%©€È?0g’ð>œ¤ÌRƒBY”HU’÷Íõ0/¡@pMîz¨÷ æ}k_ßù†B»6›>€hîßÚŽÐêT\­¾ª…ÈTM¤¢õn@ÁÂI¥ 9|¹,Nn‰c5ý‘Bßj‹WfX]šû&«“Q)›m"I˜N³³ wíÁ/.³b¿è­òr(Û„uا·«ãìëõf?ÄóŸ÷ŸôâìvIßcë>qU þ½hrzWM.B$˜]„Ø÷4Ž4R•D:o. ]T„«Ê­ÄdnRæFgJ[—|Û4êRãÚ…4éðµ¨ÒZU¨ÛÏI²Á»s’ H0ËŒO‚ HU’ ysž ¼–„Qו÷ÉÕ vØrþY/éýz\d»ôüb(¿Ÿj>¬ov®\cõ¼?¤º1…Tòq¤k)Fx—NÉåø€¢Ñ> R”bCÞV CÅ ¾)¹cÃ8yïuÀ÷\h\BÖvCdá‚?Ÿ{^<×O»¶K’Ar^=r2x—N² fé€1Jð©J"o.0BU¤†/êá“v» l %tenáþ¥Ý/½>YÒ©˜Ûüß·7¦€ß¯â,¨)p>$$á÷þ›„ fáÇ€Ð2 ?R•„?o.À/%)úÊ¡?taæäqÜ…e£‡\OgŠ¡•ßíCoˆ .Û°í˜ËU¢)§U•xˆ%›wá$¹,þ-Ù‘¢$úY[|Áˆ¢ÒïåÄqßéÆ÷5ç.k4¨—³<ñ“UQÿÕNü’ÌñþŸ¤ÌrÊD”¬&B <*GŸ‡P&Ú|÷ÎûNWØÈˆPúmã§Ÿ¢„‚ ‹)ú—áS’H‰I"!Á,‘0´,Z¢`UI"åÍ"Aôç”׎Hõ1‘NwÍV•AÅâúÿ ôiœÈê\7×kWÌFR¡ùÂyBê½9I$˜%†'A¤*I†¼¹pfÄ ¹gž ¡Uuª³Ìf½o^ŒNL_±õãtîÏ ocTžD9Â$5ýÆ'@Á·þËN‚…³`aï±xõ€T%ÁÊ› `±º e*€å»Mgº‡Ð5¶É€ ËSŸ]èF‚É&uUaïCÓiåJ‹7«é'§?X%fEÙƒ8Ï÷ŸMaŽs˜@ˆcŽU¥0Ÿ07`^*Rén»Çœ§èp8œÍ/õ¿ït©µÃcVôíMŒUwÛmúpÎë ñ0@Œ¢Ôî›ò ‰§÷Ç$žH0‹'v0‹–€XUϼ¹O¹?¥CÀã5¼?l›Qçø½5çq¾AxyéÏy¡FpìæÉÆ–ˆí½2ЄCz}Tl› ñQOÈÖ¿kÌ+ ›ÿÚ“°!Á,lØ,:[U%aË›óI“‘ú(Éç¿7ýv›âÙU¿Í¥ßP›ÆžÄ.¤š7[Es()9ýQʺ$ÞÞa“x#Á,ÞÞHUï¼¹€7/‰³è„Ò<ÞÛÞÌžûÜéÕ|ë‡ïÜ"öÝýjþEGòÎÌS™xe1‰‡^N kú~UXpï±IÀ‘`p ‹Ù`UIÀóæàLX¿:ÀYhιB'àiR˜‘ÛìG«úêsÛªëàùvÜzc¶ág^Þ&Ï6»(¼,ÿOéqðÁ$„H0 áÈ©ÑöV•„0o.@H)æ*ÄhŸ(=gÿz­ •fßdÚ«¯Ûõ *P³í­†¾¿6ÿÆ»í’T¸Ûž$‚÷ä$`–#h¢s1XU’ysž´63!xû ë:Ãjº™mråêÛþj˜‡5¼xµñG®Fàìªéý¤#š|eÞ²5Ó’ÑRI¡ËïÃŒ‚3§¸€s\£m›bU).™;š‘¢ª‚Œ\ÙÄ^àßyíb?œühV¹Þ£ÍC(‹xa'ÌÜ[Û±¨]t*ªÐ‰¤¤ßûgY©¡ªà©¡*,˜ª¹—'‡ª°º$–÷M&ÖµdD0E‰äd~kÚO)?Ýšjù¨G…“¸ýÆH¹™èD¼¯iùØÂ}ðëäG‚Ù%ŽâqZ UIZäÍZ€YVº€"BO,u°öñ9J -ï0ÃnS´µù‘Ä.N†‚PÉÅ#=j^$Ì’ÃÄ£}3¬*Iм¹@ ¦ ‰/™#Îm͵1CÍ{:‰ºwÛ$êH0‹ú‡h €U%QÏ› ¨SFêRùBüÖ Tí ƒ¸æ‡PígSØ%úe…„:MÒGíyNâ³ø‰þï°ª$þysÿº&“~'øPf˜v> endobj 992 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.9303 640.2989 450 653.051] /Subtype /Link /A << /S /GoTo /D (1) >> >> endobj 993 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.9303 607.9203 450 620.6725] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 994 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.9303 562.391 450 572.3537] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 995 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.5454 543.8315 450 553.5285] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 996 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.5454 530.6808 450 540.3778] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 997 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.5454 517.5301 450 527.2271] /Subtype /Link /A << /S /GoTo /D (8) >> >> endobj 998 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.5454 504.3795 450 514.0764] /Subtype /Link /A << /S /GoTo /D (8) >> >> endobj 999 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.5454 491.2288 450 500.9257] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 1000 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 478.0781 450 487.775] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 1001 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 464.9274 450 474.6244] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 1002 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.8605 435.1682 450 447.9203] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 1003 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 419.3982 450 429.0951] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 1004 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 406.2475 450 415.9444] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 1005 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 393.0968 450 402.7938] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1006 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 379.9461 450 389.6431] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1007 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 368.9166 450 376.4924] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1008 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 353.6447 450 363.3417] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 1009 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 340.4941 450 350.191] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1010 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 327.3434 450 337.0403] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 1011 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 314.1927 450 323.8897] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 1012 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 301.042 450 310.739] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 1013 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 287.8913 450 297.5883] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 1014 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 274.7407 450 284.3164] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 1015 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 261.59 450 271.2869] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 1016 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 248.4393 450 258.1363] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 1017 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 235.2886 450 244.9856] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 1018 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 222.1379 450 231.8349] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 1019 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 208.9872 450 218.6842] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 1020 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 195.8366 450 205.5335] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 1021 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.8605 166.0773 450 178.8295] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1022 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 150.3073 450 160.0043] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1023 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 137.1566 450 146.8536] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1024 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 126.1272 450 133.7029] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 1025 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 110.8553 450 120.5522] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1026 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 97.7046 450 107.4016] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 988 0 obj << /D [986 0 R /XYZ 90 720 null] >> endobj 985 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F91 991 0 R /F54 56 0 R /F52 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1029 0 obj << /Length 722 /Filter /FlateDecode >> stream xÚÍVÉnÛ0½û+t¤b¸S¼Öi =ˆom^äF¨%²4ß!E9t´¸.| Xäp43š÷ÈGøÑÈHsŽÐ:Ú3âÍ¿gÔðHB—OËÙ݃¤%ØC£åî,Èrûåyœp*¥D÷Åj¿¯â„¥h6ÎÑ2N9ziª:¦(_íãŸË¯³ÏËS:ÉØ¥‚¬K¿"Í"*0ŠuA„kî*’qB)“hQî ŠêÂþ¯šÜ>ªJÓ¹?nž³vðä¬/õÆÍšÃœ3´ÍlåwЀ -“K%j³bxU©³‡2^Z{×#ßž*"ß>šu¸å Q'¿$tèV? ­^Ø׽䒜åȺôSžS†ø‰HŽ¥1-H˜BJBºÏ~*JK‘&wðsª}²–A™CG»"Ðʾ±õÞÍ3L¼›³ö`©êbåb:øª (Æ ÖBÓøô?v;cvƒ ”zêÙêÞ- üè…s˜âƒ{:× í”`!R¿'1ópÉʬ†³ÀÁ4¯Š ´¶àïsøob¦Ñk·h!ÞXT³º<H!‡N%ÿ þñ *t ½È…Àq’ !B#lBÒa:݉Jcf´ò|àž‹ãѺÝöÛ{Q@I4láv:HJÓ’¢ÝÖíøÑÚÁ!·<ùÕÚÚ³|³tZ×+{n¼ŒbI@U>"wF9Ð5ñ"ÇI„¨Œp 5Ê÷éz­xŠQí¥Ay‰n·ðrûTí:¥>zyv³v> endobj 1031 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.8605 710.0373 450 720] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 1032 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 693.599 450 701.1747] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 1033 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 678.3271 450 688.0241] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 1034 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.0909 665.1764 450 674.8734] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 1035 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.8605 638.2067 450 648.1694] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 1036 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.8605 603.0386 450 615.7908] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 1030 0 obj << /D [1028 0 R /XYZ 90 720 null] >> endobj 1027 0 obj << /Font << /F51 6 0 R /F72 9 0 R /F91 991 0 R /F54 56 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1037 0 obj << /S /GoTo /D (Top) >> endobj 1039 0 obj (Debug Malloc Library) endobj 1040 0 obj << /S /GoTo /D (Copying) >> endobj 1042 0 obj (Library Copying and Licensing Conditions) endobj 1043 0 obj << /S /GoTo /D (Overview) >> endobj 1045 0 obj (Description of Features and How to Get Started) endobj 1046 0 obj << /S /GoTo /D (Installation) >> endobj 1048 0 obj (How to Install the Library) endobj 1049 0 obj << /S /GoTo /D (Getting Started) >> endobj 1051 0 obj (Getting Started with the Library) endobj 1052 0 obj << /S /GoTo /D (Allocation Basics) >> endobj 1054 0 obj (Basic Description of Terms and Functions) endobj 1055 0 obj << /S /GoTo /D (Basic Definitions) >> endobj 1057 0 obj (General Memory Terms and Concepts) endobj 1058 0 obj << /S /GoTo /D (Malloc Functions) >> endobj 1060 0 obj (Functionality Supported by All Malloc Libraries) endobj 1061 0 obj << /S /GoTo /D (Features) >> endobj 1063 0 obj (General Features of the Library) endobj 1064 0 obj << /S /GoTo /D (How It Works) >> endobj 1066 0 obj (How the Library Checks Your Program) endobj 1067 0 obj << /S /GoTo /D (Programming) >> endobj 1069 0 obj (How to Program with the Library) endobj 1070 0 obj << /S /GoTo /D (Allocation Macros) >> endobj 1072 0 obj (Macros Providing File and Line Information) endobj 1073 0 obj << /S /GoTo /D (Return Address) >> endobj 1075 0 obj (Getting Caller Address Information) endobj 1076 0 obj << /S /GoTo /D (Argument Checking) >> endobj 1078 0 obj (Checking of Function Arguments) endobj 1079 0 obj << /S /GoTo /D (Dumping Core) >> endobj 1081 0 obj (Generating a Core File on Errors) endobj 1082 0 obj << /S /GoTo /D (Extensions) >> endobj 1084 0 obj (Additional Non-standard Routines) endobj 1085 0 obj << /S /GoTo /D (Error Codes) >> endobj 1087 0 obj (Description of the Internal Error Codes) endobj 1088 0 obj << /S /GoTo /D (Disabling the Library) >> endobj 1090 0 obj (How to Disable the library) endobj 1091 0 obj << /S /GoTo /D (Using With C++) >> endobj 1093 0 obj (Using the Library with C++) endobj 1094 0 obj << /S /GoTo /D (Using With a Debugger) >> endobj 1096 0 obj (Using Dmalloc With a Debugger) endobj 1097 0 obj << /S /GoTo /D (General Errors) >> endobj 1099 0 obj (Diagnosing General Problems with a Debugger) endobj 1100 0 obj << /S /GoTo /D (Memory Leaks) >> endobj 1102 0 obj (Tracking Down Non-Freed Memory) endobj 1103 0 obj << /S /GoTo /D (Fence-Post Overruns) >> endobj 1105 0 obj (Diagnosing Fence-Post Overwritten Memory) endobj 1106 0 obj << /S /GoTo /D (Translate Return Addresses) >> endobj 1108 0 obj (Translating Return Addresses into Code Locations) endobj 1109 0 obj << /S /GoTo /D (Using With Threads) >> endobj 1111 0 obj (Using the Library with a Thread Package) endobj 1112 0 obj << /S /GoTo /D (Using With Cygwin) >> endobj 1114 0 obj (Using the library with Cygwin environment.) endobj 1115 0 obj << /S /GoTo /D (Debugging A Server) >> endobj 1117 0 obj (Debugging Memory in a Server or Cgi-Bin Process) endobj 1118 0 obj << /S /GoTo /D (Logfile Details) >> endobj 1120 0 obj (Explanation of the Logfile Output) endobj 1121 0 obj << /S /GoTo /D (Other Hints) >> endobj 1123 0 obj (Various Other Hints That May Help) endobj 1124 0 obj << /S /GoTo /D (Dmalloc Program) >> endobj 1126 0 obj (Dmalloc Utility Program) endobj 1127 0 obj << /S /GoTo /D (Shell Alias) >> endobj 1129 0 obj (Using a Shell Alias with the Utility) endobj 1130 0 obj << /S /GoTo /D (Utility Usage) >> endobj 1132 0 obj (How to Use the Dmalloc Program) endobj 1133 0 obj << /S /GoTo /D (Environment Variable) >> endobj 1135 0 obj (Environment Variable Name and Features) endobj 1136 0 obj << /S /GoTo /D (Debug Tokens) >> endobj 1138 0 obj (Description of the Debugging Tokens) endobj 1139 0 obj << /S /GoTo /D (RC File) >> endobj 1141 0 obj (Format of the Runtime Configuration File) endobj 1142 0 obj << /S /GoTo /D (Source Code) >> endobj 1144 0 obj (Information on the Source Code) endobj 1145 0 obj << /S /GoTo /D (Definitions) >> endobj 1147 0 obj (Definition of Terms and other Information) endobj 1148 0 obj << /S /GoTo /D (Compatibility) >> endobj 1150 0 obj (General Compatibility Concerns) endobj 1151 0 obj << /S /GoTo /D (Portability) >> endobj 1153 0 obj (Issues Important for Porting the Library) endobj 1154 0 obj << /S /GoTo /D (Troubleshooting) >> endobj 1156 0 obj (Some Solutions to Common Problems) endobj 1157 0 obj << /S /GoTo /D (Index of Concepts) >> endobj 1159 0 obj (Index of Concepts) endobj 990 0 obj << /Length1 753 /Length2 987 /Length3 532 /Length 1529 /Filter /FlateDecode >> stream xÚí’{XLiÇ×–bÚ²F„—©HæÚL—ÉJŤ©H+vOç¼S§fÎÉiºLIûT“ÜV˜A"¹On¢(—¢‹¬M“K!””6Úl6öÖ³ü¹û×>{Î?ç÷{¿ï÷ýœïﵜäãÇvÁÈ`(! ›Ïá‹›·ë>ð9<†¥¥N³¾£#¸D…¾àÛ‹…vb[ZÜÈ%…‡„*ÀT7ë‘=p‘C Gx#ŠP(§=PDüH‡ %¸ÈdÀw`G$ð…‘Š†‡Áç G †àƒ;ÀäAHI`ÿ®EE|XІT$ ¦ÒÖ€FÄHB¦”2¸óIú,H“üPŸšK¢d²ùˆ|Àþ}NŸ)9.S¾×òˆ(¤€7‰AŠøTßá¹’²ÏòP 2u!Bd°ùBOø®GJðXˆùà 4HY$ìCû”ƒNo‚»hŸ·¯»Í_ƒ\öApBᯌ€€÷Q?Xó?ÖtL –ò8<ŸÒeŸ7‡@I 'B€@dŠB” ú Ñ•ÄóN`0ÀXš™Ë!H½ÐÉ$)I1æ*´Üz8$6Ðg|þ+®®dl<[àØm,°{‘0áoB4Š¢ ¡¼,t j)Nga,DÚzuJ ÛZ˜zhÕœ½×s‡ZGšk¤T•¨Njœ8í÷œLnREµþpB·±Ê8 Ïû:£cÞ.&5›º¬¼ïÇU5_1i½g»Ÿþs´=hù—Y—ËFÈ3×<ÑNl‰(²yÞÈêiŠ.šïÕÆ·Ï6ëX«{èV}ÿ‹Uá‰ÕÍZƒmëQcYV±×OpqkSúµ¾gîä^R»¯‚´½ÇôÖ¬ìîð;†ÇuYÞ_ÌK– [׃΂)5Æ`KZvÓƒ¸ ÝÛ²qq¦¯ft®Á¤èǬD¼Áscç‰P¤.…Ò/±©7sá¾íxkšÿLp8Ft¶&öd`cös®iŒ§pªtx8â·ÍV&Ë WYtMUµìØ?d.·í*°ÓËîÕ|ñ;­1"VŸrð——õ€w©JyÃÚòaC’2kŠ~¹uTŽºë÷…3½“OÍŽÐRÏ ƒnŸLJíþuçåz¢_ïæ³)$gç>ËÓ÷%]¸¾ÞÆž]àèqůP†!íéÓªg”„‰jÆI_œõÞP:¥Æ9 #HYX·Zíà®a^Àb(ͦwjGnÚS9Œø Ýâú**¾aüHsIûŽýÎ2Mðn}Ù²õª´õi©ÕVzwn¼©zŽZø«Ûf>5É}­glääâì+OŒ)9k%nêG÷ôÚ%^ÑÙo‡èŒ)nYg]a• /ÃQ+9êß·ç±´áKûzšÏWó »} ™^íœ×{4«·Ë z™6«ïw\¢:¸ÑÓtÝŒýj1ÛÍ ÄM;1‘lžïûzÒèt’,v*ÙW™“ÏÛn.Ë8o}çÒ™¼™»7´ëdVˆïG‹óRb¦×öµ=í*mla¶–„²Y‰o»-¯”ú˜zÈõóh `&¨ Ã÷aÜ=oçž8¡™ZV=É(àÑ­yï0Ç@Wß“h=Ñp‹[ãÊÌÉŒÍiÇ*® u;OÒ¨zycA°ih¯»ûӟפçTvZ›žê?m0+«‡¹!wåÖòåù91±5:­(O”Ôp(Ýè嫯ՙþgªã<}.¬ÍîH'/ÞÑwš ÛóPõí/Eø/…Çܾ¿ÝÄaZíÁ xפnËaªSmŒ‹Ó¤s=ã}#ã¬ýuUÔÍ5:Oš%é¥}š¾‚*¦kµ8³Ä㡳²%¹ïË´i{|Âf Ù¶žUÕÖ;¶¨=wü˜s,ý!ÿQs-+ÏÕ$ñœKË véë:lóšZÇI]T\ª»É²tñ]ÃÖósŒ%%³÷í*9:$·d1%†·:¬$ƧuíFNžPËû‡ãƒÿ„*ƒ¥ åÎøÈ> endobj 989 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /UOSMRG+CMBXTI10 /ItalicAngle -14.04 /StemV 107 /XHeight 444 /FontBBox [-29 -250 1274 754] /Flags 4 /CharSet (/period) /FontFile 990 0 R >> endobj 1161 0 obj [356 ] endobj 1160 0 obj << /Type /Encoding /Differences [ 0 /.notdef 46/period 47/.notdef] >> endobj 511 0 obj << /Length1 736 /Length2 1029 /Length3 532 /Length 1570 /Filter /FlateDecode >> stream xÚí’{8TiǵÑÈ¥È&—ÞrÉŒs4¦vÝ’‘D¦‹eš9ÃÉÌ9œ9#QÏvsÉ3•­´Z)•—¨G=›.’ÔPT›É¢VV7¤=´í>«?wÿÚgÏùçü~¿ïû}?çû¾6 ‚W;x °0C Èò>œÐP&€éæ†úòØ@L&¼¤ÑÀ™ 7†›‡3ƒb|°8ŽDÇÀ·:!r^bGø<pxD ,&=ø<Xñ˜9/‘„L¬€Xã °À‘A@€ð °ŽFPŠÓÐrTˆ÷m4îÓ(Æ%$°#!©€D`¨H°â„‘{Á$É¿5Õœ-‰‚xâ û‰>óĈHö‡ÇI LãèTi8ü‘ ©xêt9Á!|/4ZúÇ"a#‰° !ø1€À¥ðdFSÈØ& œüWúû¯¶ÿxœ“³`‚¡²¸?M'Ä“5ôWM†ƒ#‰`=Ý‘N‡H!ù~úŠ˜²×2” ”¼®n€‡ã<…¼då ’ € 8À‰$¯“#Šä@F²1œ2qš à'’J&º”ÏÿÂÛKLrpÎ..À•á ܘ‹·þMÆ—â8Œ“׃LâS-DÈØ`8æSTíŸ%ßt 2£$eYQËI-Ú4ïè {ƒÎ6Ü©ÓM»¿oš¨øÚŠxZWw¤Ta¤¯ÖRÏßÛ|•‡f&XF´ªÖÔֵɧ3¾”ò;¬äös¨BF=…RYó=昙Ο~*gZë;óe¦Oó¡"y·I¶’P•Õ¼#ŸYË®?¿õ5ýlRHwƒòÝŒ7'ÇXº2ôéëñ.u>ê5‚Îk+u ^Í}4³ÈILïs–¡alÍîC£ŸqPÞ>ÛÔÖ5ÊýÇ’Æîyª¾Š0íÕËLÕÉæ¤Ÿ)Nh#¸Õµ›¶hô»½e†•'‡½Û6úÈޱKú6½¥F–á{Rë—©R-ž„Í [ÜÞvÕ/áƒÒŒþÊÿÿ ¾æá&æá±”ß½¾Pendstream endobj 512 0 obj << /Type /Font /Subtype /Type1 /Encoding 1162 0 R /FirstChar 43 /LastChar 43 /Widths 1163 0 R /BaseFont /HOHGPS+CMTT9 /FontDescriptor 510 0 R >> endobj 510 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /HOHGPS+CMTT9 /ItalicAngle 0 /StemV 74 /XHeight 431 /FontBBox [-6 -233 542 698] /Flags 4 /CharSet (/plus) /FontFile 511 0 R >> endobj 1163 0 obj [525 ] endobj 1162 0 obj << /Type /Encoding /Differences [ 0 /.notdef 43/plus 44/.notdef] >> endobj 420 0 obj << /Length1 746 /Length2 987 /Length3 532 /Length 1532 /Filter /FlateDecode >> stream xÚí’{XLiÇ%Žu‰\’Í›d‹š™3Í4•KF¡0•&·Tœæ¼3N™3{:“™M(MT¶¨ +‰..튭TŠrÉCØ´¨£]—µEè‚{Êz<›?wÿÚgÏûÏùý~ß÷û~Î÷=6V¾R1N…Ày”Šq@9¨+p—ø{¹”ÃCllÜiˆ1¥òÀè Pˆ5 €:>êÊsvå‰àN©u4¡XÃ[w»‘ˆ•&d˜ H0f T²2ŒRJF@FÇb’~=; ‡tÄ9Šœ1 *ÂíòRÉ) z߯5ê£H‡³PÀ–…´,"N©HÀ¡ázSìY%ù7 úšÏÓ¤7¦ì±ï é“1¦$HÝ_J©Ö0 ‡´ª¯t|Ï&8¡Qöz1IÈÄ* *àðïûDøýŽ9s(m¤ƒ£8ð…¬1*p"!/êoB™†¦¡ŠéýQØ4>Ôr‚ B-”!õ7(ÙôØÐ´Â¸¼õs³®2¶ Ÿž{¹\"}:§éîô‘utÑUhùÂToJ‘údáQ..Þ3/¯»)åêo™^jf—¹KjÒ"k î_q¾r¸òûøGõï«‹¦µ4X·"ÊXôí7’`”wóFwëú° 5÷ê‡|‡[?HE‚2Jí„K7$_êlžOeQõ«Çîjõ¶Þ¼òNmØí¡é.‰’¿¤Ïì̳ÓÊktwØÄúå{]<ß7D¾qñÔ– [ùÉ? ¿~Xû²²¶%6Õ{þñ½Š‘Mñƒ²¦¯:<{éú8r²§™G†eºëá9ön_r/˜êc_<0ßPW‘•›¿wç ²Na?¼ÝR\•gÎìÿLîkX<ÖË ?Uf˜´zS‘Ó‘¾:{aÆŽŒ®©™åzé#>ÕØýæ²çÜNóÒÂÔ™ð©žï¿)i2¼ðÉ`dñÛºÇRZ‰M…ó²Í™ï<‚iŒ(ß9ð¤•ùÍ,-¼>£å³ðmµòP£µYˆ×FŸ®'nT=à4.ÈÐL¶Ìü|[Ú¢†§¦Øáuå]Én¾¼êäî뉷„e¹—¢÷˜6¾I³?m[;®#óºÇ YÛ›ÕSÚF6ª†ïÇlâ̺#Õ¼ÚÒÄóe.RaUÉŽa1ж×ÈëÈò_¥‹Íg?7J$$^^ °Õ[P¾«šÈTÿ··-Ú¹Ò ŸJ“Ïœ âThîå—Ç›´V& `Ñý¾ñ.°Kò±ÿòÈK·œYåîÏÌJ—]L™ì#-6I.Ž¢ŸQ¹-¢ªñ­žùM:D 6!Òµ‡ ¤wAl‰™\½ká8“Èÿÿ  1𡔆ü çfKgendstream endobj 421 0 obj << /Type /Font /Subtype /Type1 /Encoding 1164 0 R /FirstChar 46 /LastChar 46 /Widths 1165 0 R /BaseFont /IDBOMV+CMTI9 /FontDescriptor 419 0 R >> endobj 419 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /IDBOMV+CMTI9 /ItalicAngle -14.04 /StemV 70 /XHeight 431 /FontBBox [-35 -250 1148 750] /Flags 4 /CharSet (/period) /FontFile 420 0 R >> endobj 1165 0 obj [315 ] endobj 1164 0 obj << /Type /Encoding /Differences [ 0 /.notdef 46/period 47/.notdef] >> endobj 417 0 obj << /Length1 1825 /Length2 12271 /Length3 532 /Length 13284 /Filter /FlateDecode >> stream xÚí·UX\ÍÖ¨‹kp÷ÆÝÝ]Ü »»»;Á îÜÝ!¸»„àÁ²û[ÿ^+Ùk_žsuž7¼£FÕxkÌšÕ %©’*£¨©½1PÊÞÎ…‘•‰• .¯Â `ebA ¤w¹XÚÛI¹ù¬¼¼¬QWs €•‹—“ nïàédiná §ý'‰ j t²41²È¹XmAk˜ÙTíM,.žLQ€Ê?3œ*@g “Д •`jiâ0š[Ú!0ÿã#kgfàþŸ°©«Ã¿‡Ü€NÎ ) H’R4µ·³ñ˜Í˜ìAµ€ “ÿ7¤þ{q)W#Û–õèÿ5²µ´ñüßãö¶®.@'€¼½)ÐÉî¿S5ÿ£&4µtµýïQY#KQ;s €åB–ÎR–@S%K €™‘3ð_q éK€Úö/f M %5uú=Í )YÚ¹¨y:ügÑrÿŬÔ'KÀg&VP"è÷ßéýW)I;{SK;Ðqàä99y"€Îˆ8Þ¬K;S èòef²³wM€Zâ 0³wBøça‚ž7³Ù¿bÿƒl ´üƒì ´ù²s˜€N&@;—?1^³£«=¨Ëÿjæ¿Ã, T#'  Ðì¯(ëÿŽþW2€ÙÄÞÖÖèO„Àláé`´ûâúWqK{Ó?!³‘³ÅŸ€Ù èdÿ'Ò³·þ‡9A^.îÆ9AF.NÀ¿2þi½«ÓŸÀ?M°tû+¤ë z<ÿa¬3Ðí/WУ`þ[ä©ÚYþ%š$ú‡@Äþ(Yüö$ñ‡@’üqƒ¶#õ‡@›‘þC Èü!Ð.dÿ¨úÇ?ªþéªËÿ!Pu…?ª®øâUWúC z*TOõZ¦ö‡@ÕÕÿ¨ºÆU×üC zÚÿ!^P=?ÊüsbxAžÆ4ÏäÏ1fM4ý A}þ…ÿ<ñ¿dnþ‚Ô-þBû_/ HÞê/9Yÿ… )›¿deûYAVv!ÈÊþ/Y9ü… +Ç¿dåôþsÿB•Ë_²rý AVn!ÈÊý¯dåñ‚¬<ÿB•×_²]ÿ~ÿï[PLÌÞÛtI0²^=Po¹@gÅ÷ÿH4qu] .ÿú€-öo6³ݼ@ ÐauÉÞ„?Ä*½9¬ÜO²ð{4¸˜yK‚Bcï|bðJ"¸MÉøGGº­­çÊL ä#è#÷Wç¨Nå)©Ë@Ç„/‹ïGn†G™^mZ7™òž‡dÁ§(Í wgœàŠs[å)ÚEC9Wç_•h$Ô~Àn‚õ}vûÖ—ÂÅ­%•i£Ú@ÅNª‚úű<‚#|Ó5% js&ØÏ*®•~ýÚ¾Óý¹.?ù]÷+ͤ“„]eSå‡ðYYQ8*JýïÁÑZ‘,€¹ªàz Ne\68#¬6Ç _Ò`ö gZ2BÞí’¡­S‹ô’Ko«äÀ€ÞÀ¢Hn¥˜å*©Ð¾ºÙsF«ýmþèm³ ßPk™ö0H ý¦Ç)Ãõ³²Óv^åŠ,*›‡‘RyŠÐ| ‘€tk‘ ʾöW=z¢yÑ ƒ¶é¯Íí9 ×.XƒQ\ÖrÑä¡©(x&õ<["~ä¬vmÃä_aÜ^i0ˆ×t_›(§òJEß¡‰åغ§ÔË,6MÐ2ÅžØ&Î"²úKÉ'D°^åÊŽO0·0xÊgb_€W•ço™¦ÂòÎÄL„™8‘dñw¢Øä¼cintºÙZ™?á?ÂG”«¥¸û‘’7Ѽ¼¥C’ÛˆKXì×…K–y*êe_ðÁªè2²I%ôöqüIWš+y,GƒŒ„JšÎ4¤­58p‰'®øß×5¯nç8Ôti3ÄÍrG«•5­?N$íZãìʈ'$ó6ýú }Û!+Ì!GØo߆>±ÇšQà ¤ÉMí@P®bc6`䊹tM‚–ŒH”Þç=ú™à-+€}’Ÿ«JŠ*,qD´aA¦Lä=6‹9ûÊþÝÓš¼ŒKÔû±©žÑüQBu”Ù€ò±|éaánÃXàõRÉËÙ+À,<Û«j(¡€ E‹ÞI”i´?ǽ#Qݱø枆É*îçïu×ä¾~mÒ•Íjö/ ìÖ7Ní wq¤.ïyjáÞ\˜e~¦òÔi¢ž/¿ŒÈg»÷/#—‚¾Q·+¢eÒ¼Ž>ÜLàÁ¢ÂŽ'jœªÀ—Ì%HàJÊôAÏz‰Œ#/þ))І‡4áÜcØd‹Ô(jÒIô”|wÆÁO`üõ k5a'l¡uã52y Èò~)È’w[È®‚8¥ã|Vw$ž¿Ä®ÄŒá O0S=æ5”iœŒ2xcz¢öBbgVÒ*ßýUâøÖ-Éð3äží<|ò2Îò›¨œ>•WB°ÊàTê>±ñγ3ŽÚ)Ø~çiE·}*>5°)”‘ì ®ÀÃx[@Å:^'¤Tˆ÷ô‚)#ì5„‡ˆLcwuÎØFõ[UÚè´ã¼êq´hµ]ÁÇfËí|[e+—(Že/_ŠNÇÏ¿˜‹+~aW×änûð¬Ü²wJêaBÖÿdBÕhÛŸ9¹R0ëÁÖôˆ™cå´µÀT??ˆ:³%. S¥Ã OýU“[ðŠÌy_Š3Ü­gºãQò•ô-ç })þy ÜXí>¼ ˜‡M‚Æ™Ö×Õ !Óe:O  ¤â;îó‚´X¿ê¯ ]5ô÷5"sêçÙ•€D‹8×=Ÿ”ÄØb­ºˆM“斪̠~ÓNl¤2&1 ê÷qŒ+¡½„’Áð±ýßRq³xÛ­±ÑžlÎûá/û*Ü™ª_ Ø’B°KŠ"9‘¿(óßÓj+Në·•Õ†RiÕLSPžßàŠ™C9¥r¸lŒQ}+ôÂ49wC§qXL%Ãfä÷è_w|V¼‡ å¬ ±·Tú‡>)kšl®J‚8Ðý3¿|gBöê}“(­êB®d:‚RWôÉûøW²„›aë`ÃÖgJæÆi¦w±ñ Žô¾žÜCB·ÓjDÖª@íÁïä¡QÔfQôô¯äTT:nr—É9Ô&Î~‡¨‹fø"m]}²fæBòÚW‡޶*I½á÷ÃìxÖhU¸ï;(÷F„§Î©ñÌ"ç®o<ôäc—‰Í·u!BPŽ~S¤äƒrƒF=$C(æÂg¡Så)Äî]äø¹ÞTªž =$Ad#ÍÖZGSu?r#ÝݪJZlégš\eR®x´g{¾(GÖ#Qô¤/¢J9‰kµ­¥ÒÒ=¸µ>ûs[£—4’Ý݃ã;xùÁO,šÌº*yœ¼ëëtÃòÀ2Œs܉‹d»xi7…LA; 8)“Àït94ç÷#bO±ªp‘¦§ý¢×Å:µÂe"ÕÚ.êÕË:aug|¦¶ÇþÔœÁÎËûߎv;kñImò@OR„ëú¥8t½'£7 lÙ½Sòî ¤« Ýá\J¥—ÙA½ÈŒëx1b‹=Μ'sqÅë`ͨÞËsõj˜±1À8ÅBp°ZóOėȹܺÎĉ! Üûæ¤áõy±¶…kÇϾj~×L>W¼®»·²µióѹ:%Ä‹Q!:¥`;2…)žoÒ–5¾#~úÉ÷I ï¨Ê5Þ†œüs7ƈAƒî“0˜¤€£÷#ŽÒYË„‘žÅ'žR¸âBF¦ôf CcnK7´VhgUÞƒE gëÛ8¢vÀ˜qk;Å}êÞKæ3 @Ö1+éhc³Òyª#¬»+/Dó£åS×~ˆýÁœÃÃD”XÎ:³+ÖêÒ[èªÍ7›í'Km=`×wíW0ðõòóǯ¸¦ÚO­\„Uïñ+Êcï{þJ Ãz**dÇ2BaY¯9ULp4|åJ©‘, ´™nÖ[¬þ®£ŽTpÇÄ‹H^‰v«ó'¾Ý&6&#Á7Î:Q\Pc°¬¶<ö,«U…Æû™45àvÃ1©ÑizFXÄpªu¬¡™ÇíøTŠ`¦Ã±w}rÜVÖߊ²O×ë‹ÒÌú¤„3iõLSvmàå5Ì<ò{̾ùu•ËÇú³¦sAÕüìγ£ŠŒŽÏÞ¼„tøQ‚ µé•#¡£zW} ¹0—NÁTåDå…»E_ï¶%àòlv£Sý¦¯JomË„KâÑU!46H 6[8#{½ThÆ|6ºUÅÁO›Œ±¤a¿ï4T·Òÿc~ñeXí@¥Í©âN-Òùnòf(Ëék჉-ÍØB¦½{ÞFll ÌAj^X)õòôˆ7¶´ßÌsÓœeé­Ux)^õŒà‹Üù™o¡² Ï8MrÊÙžÌÏi;~œ„×Ôþ­Ÿ›Šgå¼I¾éÎurõ—óñÐ9•¡kZjB×U/)gägˆ¯k>j,I~8¨Æ3‡.Î}¸xÌ@nxBÃ_£å-Ãk›ÎÓÕõPÂ\8;rŽäË}Zd'¥ß†Ñc‚G?cÅh*_X çÌÉãPÕäè…dg A×@:œˆ\jN1%s‚ûò}åÆCpÆp»ìpëüÇ-†é„Ú# ÂȘ‰øfèq7?´’â¢)ÏAíuª½ ÿr¡Åœ Â/4!1JßÐ\WŸ3ÅIí‹m»mÔÏ!ë´âÆÊ;³«Ú£,{óê¶ÌVù¶»i¸"P0Xú~&ÿT-ÛêMà "T§­[]*¾h °‹% †o‹¶ÿ»Ø!ìgÏš;ü°a€ã⮥˜,>Q¡Q4 !>°=÷»ÙìP€ÈDæu†¾‡µÒË9%Y(¨©%ã§êsÕ kwZÎ[ƒeäήä7Œ)XXš‹uYmëœ[F\‘4ÑvÛ5ûÄÌCˆæîµéjh”pž€rÈo¯*%"Àú@ÕÓ®HR$G´Í›Á0 EAÃcŒ…åuØç—>ühÇ‘£”1ëqP@–ʡĨ\-ÒÈÌáÖŸu\zÊßÃЊ=¶Ù8Ò•}VW[¾æe¸€VíÂŽ5ë/þýgŒ?ûÛ8­$ÝŒz †îïêÙ¯í'QGìËv™^O[n˽±o{KÙ oú¶QÏüu+‹T‰üîmúN¦µ`ùô+¼ý¥–Ä Á°øäüÞ›N¿åY.üC¡.r¨Œ¿FzP.kåë»)5›n†.4.J†fæ^8Æ%¤¥‰K—¼'4 8dñ½; ÈaK›½|ÏVÑ™ÕÒ•J›/g–šÒ¢.©&¥uÔHðÃpC¾w —¨^<åš"z¸+^‹A* rá›Vmø`9öƒâœ+6@\90”¿ÒÀ]Âõš˜uß#𳍙ÀŽAziÌÄB/«¾¡ÑFà" ?Ævi¯ž“0¬N½ò'I6ÉŽ(qz»s\ÃûUÑèyG+xX>s|[ó¤¤o?üØ>wa’¸Ör£M+”,¿†á ´Y'fŸ_üêË Š+·™¯&qJ£}„{º$€€So¥3>Ä“cU;QÿEÖ“YÃE#&yÖ¨wÞ4O¾Iza™Ë6Þ";d…ñçÌ]ù2Ô$îTœLLÕŽNR9¢ó×" 2«´S”OÐ×góÀg!@ëfƒÈ[Låù-ËH¦ëU^ºÙѨ™·õ†p |#Þw±_$_‘A•µ|¦±÷ˇ“L·ECjã7‘%|Zö1W{yÜæyÈg4ïGÆÌ,Å_Û¯aû¥¤ÃT J,“Î…ÄHßRD(†¯qqÙpôB…—gÛÁ\?…K3?VlÛ>'G½Xp…ºeZ?œ¯U|æð¶'õô4‹¾-ËÚê0qÚ;ð»ìÃ";â °/!ÿ,ä í6û·Ë,”‹~éºïæm|eVÅêo-JU|n"À>QC}Zú@©œzþqàû¸DuG‡å˜Qð§2kÆùïñSoPz2g¾A›h1›ƒýrÜ´Û-i ä-ŸzC?}r˜L :›>I¢áäï>‹›>Ê q2P)Nº@¨„ìø˜8ß™T55;‰e(„S,î,vp/á‘`2tÉ:õo>‡~îåÇu9gæýúÉŽ ›…i5ûx6_SãH5Ý YøÔ=_é!"/|8“FóÔËû®ô-Obà äÕ¯¢™˜S~8ŠÔ šÞT¢4ÝÛg^ºm ³Oîî?«µ.¼]"f˜BŽÑ2÷|=•ÍѸ=uÓ½ú"‰"ñ‚æPÜCkð=ö‹[ýxlË0–ú¤uÖ¬òåfÏ{¬36®×ðÝûYÿTBnZ£§¬¹X³™É/™v⥫æù -ƒ…åJW!©…ýƒã°^„}ˆÁ›u¿p£N2/ •…ž¸F4hœ u`JïË‚Â'›º··“isÊËKÆ&kÌò°ëo»P•¤ªYô¢²úk9†v:÷ô1n£C ºùÄi³_qJ³%)_®ü BÚ_êú»¶&`N¶û#eߨOÃ~óIÑqú©ð~ÏxFô?&¹-÷ç eÁß¼Hq(Øy¥&ÊÛ°Hì¸k#Dªx ÃÆ2”:ß&é'§"ä|< VwÝ/”Qu¢ø}Áœ`}2õHÇ›e‡i?7‹1DX¬ƒh™DK¢áö•#ÅãÁ•é‹›CÖ¾ìªíDéeÎâHþ7üŠeM´*gX­Ñ¼“i«œ/©@Ö’…œŽÉ£&®’W7Ãb»[[ÀàªßÃhfµŠ@Æ»gãЊvXò+«’&"þŠ®³ v¾ÖVkR¹d°&ÒÇZ‚VQzA’\ç¼bÃ_æ+S¿Ã'ý$²&ÜÖy}©¤Ž—¼Ìæ9b#èuaiS2ïöz±s¯Ï5/9ó zÈV€ ¾Œr)k½&c!mV604 -ÃB.c%X]øÒT|~,”C«g¶x“9Có’6ÝYVRž ÷¹Ï]ÓœYòµ“B¦ÈÜÞè¸sKŽA0ëø!ßÒ§¡o]3¬³æ$ßlòfDùÎuköe5ø ç˜ñþs<8IµX"UÖBW -sŠ:%'ÈÈ9nNæ*á‰BÞ—Q Uäêó7ˆ_Þ¹zôCQ…Û3kKE]-ìªÄ.vÍÒ"À*ó§òÏïWäç_Œœå˜wi‹MúkÂzEaîgP¤0æÈtÜKn§òºg ؈ V~o߯¶ Í–ó?U´•°´Ï®°r©j‹g!MŠÖ’ÒÑ1nêA–èÅ‹#Á…¿Ð$„#&Ò¡pc¼à( LÝ”õBDm¾l{ì=É' 9ŽY…wÖ¾ßÍŠ¢NïÓ³ÿpâûæ9ÀÚjžÝ¾½Ãϼ#)áV¸ :WÆ™ù-Ì+Ÿu²Ö‹LïCìòS Ô¾½íQþ µ¢ u6e¾[ì25®o™Ý´(I½¢ÝУ%9ijáïß5+¿å¡ÏY‰ Ó#îQ7¡xÑVÖSä]Táui¿hœ<Ä êt¼‚›Üc •Z*'îSò|÷ÊW¯ ]XÑÞ_£õÂÐnÜï_Ž.k°–ó$×Öó©©ÏCMŽžÑ½Ïh$ãR ¯ ŒOÂ?¶‰ŒÁ °¼Æ.X{qÄè—˜jÀç•>O_œMÉ:I¨n/êœFŠdß)t/»$”$_öú¶OƒÇ÷4V¥*£+p¼¨ŸL‰ÄjrRÆH½'­ V­ü®Zür•`û{ åæ‘½Êò£Fš®ÉK˜A_V–Ùª3'xU­W™öîÖ5·v?ëû‚ëC]ÃãÆù"øsë^GxLÅðvP!Åè†ÑÍÉjL¢?ê¢Yšd¶šƒ[|V/¶‚§×FKêÛq>á“ jêéý̆j‹½ÉÙ{ú`ûú§·6xçÜ ’§[¼/d¯1g¹Äý;iøØpOJ|mt×ryÞt—Xáœñ R[êí9ÉóßÍbÞçJsW:Š_„P±dýÒÁBýE©0ç[ŸæñãfArls<"{¿W Ó¨;#˜çgîéVJ›c¾k¶MuõÁÕ ¼GßÀH5ê‰/•° (‘(fÀ\ºOŒlÅ7FÞ®£{w®Ò½k£uíºÕ·©[µ®üJd?š`9­%ð>=ä=ÛM<àÇe‘BêÊZ×<“TÓL̈:Ɖôþ8zÓúábéÆi?Ý¡§ÀbŒ›ÅWJôù¥jI.¡’¼Îê´‘”³ßy¯Ss3×ÏÒ8þrËÀÚLQ»!{©ÌFDZ»+&ë ðkìgj½äŒ”þ`ÐVQî¸È:L°¸‰&Š7ŸGûé7êÔt")µÇ«3™Eå}ç»±ï`ØDzhɰ£th¤JƒŒ§ió…j®U*±´ò>þ„ W“ühýV´T\“'×c·QÕµ#ËÎkÛrú9JRq$nKQ’fÿ=ÏÿA§Q‘ìÇ—9­Êž÷ÊsŠ}þj›+Ÿã»ûƒæï?Wá1Ö_Á¿žÛRÒaöMäÍ$oqä9•ågHuù.øw›¥ÌqXÔáü<§–?_N.ÐÿÚ%¹¨+ƒN~ow„Š_Ù7V+¹ír/º2×Þ*"xwÓ7NÍA¥É…r7£^ íïù˜åa>“Æ´Äß Jj{Þ—„b˸b/ù£¬\ìÙÁ1Åc ž­®­¼®îâ :[Gê"ТÖ³<—ªåê¬væ±ðX×á¦W)[˜¿²þÇ&‹ŒÜ<—¿½ðÜ¡ŠPˆüÊø"†Ý2Ý1³80X»4rúƒþ*œÝõ Ã4+ûÏ’§#îLâïÎE«ò+ñùA@ÑÈØ)&g:Œ\7µöPÞnÌCºlw&b,ߦg]-‰ä¸­j-Oç¡|öë\kj} œS+ýLc”#Ë^¹øvánò"-]Öä¤üÈ9¾Iu™Ê3kÂV†b›+òïÄŸsyé:5Îùv©JjâÖ§â€VÄgŒF529¤2t¥Ð߯«FÙO$qé;V}®FÕ¾Ïågç×Fò¶éÞêr2hua„Ç‹jh¼eÉ8Ïa —èƒr+,6ÛX™?Àw/¬j·ê }‡»([ÈÕ~°5?3rŸ+¢_r·2½c“>VjÜš´ZÖöËnb@I`€îËŒDÂþªRIȰņò£ð'âœNZRõ¹ß³-OŽ^íH‰a‰ªåq½_ÇþÇÅx¿¼Ý=wh¦™#z¢Òú>žA¬zA’YéÉÒ€bùâá’Ÿqÿ² v‚¾–C|3uÛZTI|[õÊ-uL¯žþ·#«7=c¶Nú×fk#A-à*fxfeúßñqõª/jæ¿¥×òçüVƒµFngW\½”«[¯[™I5c(C~…AÙ† 8ÇCÁè\³‰—ž¿:=ó°@EK}µŽkñ %7‰ª®d˜•V,‚Ý¥M~X¿Ñ)F'J5Qs“X+žr:C±SS1¡ìÖ ÅÁMÞÆ.V|HµÌ:ó7v&« í¡M²çë¶ñWÛø…­ü& é\ƒñGBAnê>[ÚM¿‹Ñ;bp@»7þZ \ôP‹…POY@0C¨\äšâ0XX…U†Ã˜Š¿y9€ÚB¦º®À ùm¼¼÷Ðq¿.áRöx5 M–„ÏXæ ÇÆü^ ^¢yz„ëÄðÓõûejÒÏJQò±R“ñ«¤@À“[÷;JnÚ=§±ÊvFus¿£B‡ADøJŒ4óˆ2 dðCËÎ%H+^Cäˆ]åt_F¿‡s>x'«Ž…©õ“Ä‹IeQYR6yL@þYi ·&P:5 wˆ‰òy"b^KgŒÂü±Ò-¶0QIý›²t@¯DyäÄlXöªef'šåwIc_gVÜ ¤ÑÆ”ÅÃBœðb[{‡{ŸUäÀ‡‘Ð¥*œÜmãŽÉr`¨$í"¶7Ï¡ÛÍ“âHW~úÂÌ×+ì%ŠLNóžm<1tŒP°'ºÍMš€ Ý×óÃi‰|ÍESÿ2yßv¿E%y›PB{ö³YÏ-Ûê… ¡  )•„8a+9”Ï:¯§lu>&K89ÞP]ðäÔŠÌ‚©ÒHœ˜5ÝØ"9_PIo›CêÖ GÃ=·Fðö›[5½ÝnŸH¤Ô Ú.É zÜ›Çì·2™ìÓ,g¢÷¨‚hÊÚgˆ3Þ®Y)…ª=”±e,&ðVüP°x9Ñ_¬nwyË»2—c¨P9†$¡®g ®¨¦m+Q#/;šú*9æa¿-v-¡e×ÿÌ"+GÂAû¶b>‚Câ0ò…•Gâ´Ñ/‚dÝ¿HnIœ»gHO®Àû <êªdÞPJìÐ Êp¥©ùƒä¦dEçÉ›Jˆs°šCd—5­[ç£ß@Œ•à@£æWʼn‰+_éÆâÆ"Ù1±X°à‘£NËTS”!¯j~ë‹øåz¥¨=N—Æ‘ì1®€·}ÎK´ÇãÞ’Ú•Ãûéß“¡"# }‡¼¢ØW94`ŸcïWà´:d‰Ä]âý‹LwiÖÅSÓC_c5ÇeØ›?î|ÏˆÄÆ¯€, Œ 4­£G’»ÒÏ Üõ·vsÑÏ)ï[A}ø©7-a/³êm’mùä½f`6¾¼!ÏWlÙÈ™Ë{‘4#ìËT)—+« 7>h±Éþ"Óõ,}ÅŠc¸U ÞÌY˜1s4cÙ­.·ºàЬT|' Ô–ª06ú ú§CpüZÀVHT5äû¸‰œoD’(î¨ õœøÑÉ3÷Ѳã`8:«rxkK4<¥¼ TªÎÄ)›}3ÙxÍ‹kçuè™sÌÑ5ƒ6f<Ñ%\HïtHÑœPK¿ ©,ÎgîHÇåÎÔ¯’œnýž ɯ!c÷ÀÖ¶åö4ü5C«_ª2ʉæ s8ö…ø¹Îu_ñÒpÕŠ¢íy3Ö9Íãaa¬§¿ëPw=Y@#%Ž`Ÿ, ^½¤£ÑO sCv07郚H¤rXÂEE¹3‘K/úéÉÉ x®¿Ø=Ø‹gÊœ¯qªBòòEÌ”\Ù­‹‰œxdk¥÷B4ÿ‚_~ºo¢‘´›V³"×JèR3[Êß‘K v’_ ãÀ£3ã˦YIR¼ôÆqhãœSRüì¹1šÄ'†ÏÎE±Ô„ Æn›¢¦Mõ˜Iq’a¢ýNÒ'ý²c ¶Ê<ï^„¯I(ŸÊÝ&]OâŒÞ÷– 1>K‘I¤&²›Åà°˜˜øÍҶ練y–™™ú»K-çQb!>9VÚu«dp–I7¿'gg!D‘ÖÀ§ž§C]ÊÒl#|ÄPzñ&Ú'1˜ô×÷~ãÅ6ЗOhêdYÑUŒ°”@îC_мPµ<³)¾u³ž¾fÊßJc½ˆ.ϤsÅê¡,l°0?)ÛLC¦ºo• Ô[©ºës’Õü<1àÍûô2_hÇÍöövÈRЖ£¿òäô‘5_ñ|;ÐÉc¬ÀÛÍìæ1Ôâ†}s`×ó"ô>dw‡‘Í ©™äÉèi0ŠÀ½ðJwÉ0“¡’9œáó‚ìsäOinwÄ£ŠÛŠV¤ô¯:bZÍèEýÅêS&WgÅcFh®B7ˤÑëæÄš_ ©ø¿[¡nû¾òÑ¥ßÀ|ƒ¾ùà7ÞQ°˜‚qryU¤;/Mµ«mJ5®*Ü”n–N/ÔºõW$õàžBÀ;ÛýíÝôY“ýÃ;8ÖÈéÚa±^òWî¯5<\¾ 0Œ§˜%vÚÄfÝ!þNKS˵ad“*4Ü-yoÅA)¶\âëÐwŽÇñ;i¿¬8¤Æ§‰ûäцþWõƒ4iN<ÄÇɵۨÇ܃@º•¬Óœ^ÌvÌra;äO‡‡JzÃowÚŒ<éHÌ€a_:,]“b¨v3² ×ÍMT Ü5ü9ϯÑsú'‹Y^{8õ±dÛ|”ð<|v¸§o0†säÌì(m/(Ùþ„Ý wÆËÂÿöê²·ô2¸›z¾ÈîåêXÐM“Üâ §x Ûð£ÀbÚׯ[3 !u«Ã~ÒêZ9ƒÜUÔ„5RI¹ÝEÉ‚$6´Ö­ejøÆõ.èB á{“¶hAÍ™Zm@²³ðj €‰tDíÅf3ÛÁeðIYÒÖÁxeq6W­{·Ò©¦Þ²°däÊg~8üaìí(E3¿«âP·Reéusb°Pƒm„õWÌÌœHÍÆ8Ò–ùõMôIõ|gÈ„ÉÐ8†nZ™±WüM»`k §ƒéÄ ;ʼ¢ð[~-I\¤žÚöÖg7G^/7¸VQóþBøµJ %éDz‰è*PFµån™Êaxh«¦®S’‘å[±\T/ੳîT骇´nô~¹óbQSÍÑSBW~Ãûn›ÒCªŽ@‡š0¿©;ظð‚}›Q…ÞÐ2Vjô܆üPéÖìÜD CÜaµ9¡óL¥¹Äb¢Ë\úvþ˜¤z!R\щ¤™J¸2qVGöW¾WY‰ A’[x´Þ,·Òv`TÓ85fòäÑ,}“ ó6ï>®D{þ–®ÆÈO‰˜–ÅcC—p ʸƒé ÞEäôÔHyÏ\GÏXÔ)}éäsC‹ÒW.âPŒ7ÉG¶Ëw™c$j”Øþ¾Ë»Ù! n¥~guîN:sGkM\ú,Dè‚}kÜœ·|/¼–qÞ¦ŸçS8%¡Âêû{xÝTϦm „ïPé¤3Öô´ømâ7ÑÓ¶ßã+ëù‹ <ݽfÚ:Ù”Ùâ8Ã÷f‘’Ü“^KÈ™}Ž?ðqä!?¡GëŠ_ùl®:=wPé÷†¥kX{ ”!=R/pL‰d§ßåb½H4“Û? йÇ&Fã1îÑ@1 ˜ :Uèj\rŠ ‡—úÚ¼q“-2¼††‘ÆxLò+Ä+K‚G®‰çÞê§¶5êøÀaæ?5:ÿ¼÷NxQ.ä¼ÿ×ÁÄ¢G•Š4!z WÔ½©ô³}<¬9ݼ$:—baKkS|xÇÞgHÆI‹L@¬%õ¤)ËÂg§±ÃTÄ–KNµpiT…]0ù‡jݼú.WʯKò:ŧ“¥_#<ÐÙv¿H¸àùÛè/¬¡ † Ô«î [ÙLÀc¯¬ƒ‘KæR­ˆã}ƒÿ ñ@xX!]qAî¬Dêƒ_m³ÛV« ¡ÂðÜþ(VUm5e‰:w·3]YAVôí×fÐCż àŒ†¾ó™ßã¶æªþkûæ@x†Œö®´Ð ÕТî;3æ¦Í–¦ÓLI-FX ~Ük£Žãëgb¥kØÂ :¶í¤oÍ+ÏUh¤FÑz%Ç=÷02òD¬YQ« 6m#Q8&q1<_%Û^Y(Þ禲Ë R¥ž˜™—_±M‡qñw¢Í4¦ ëÇ2{â÷4ÜR[uÖ“Æ1ÙÄÈŸy Ò¾þBþ]IvšYþ¤Y‡Àè >^8îwX°.Ÿ{ß%³q¸Ë0M Ž!,°“wÈë²mú,š>'sQÌ‚¼ÿD>9j§®lJ2`‘ãÔ¸ïûðdXjW3ÅØúÒÔ3@8ÑÿPŸù›r¾»Ga‡· ™ oYÍÎ%+›•lyf¤Qåjˆ;ÃÅ/”o夈†nh³ÊΞaý—dÎ%ë+ªÀgÞ‘‰SKÍìÈÑûÆåˆä/ÕPÎLYµwZˆÞèÞSq㣧¡£ÌÆ•óõ»ô)6íÑ‘BC{êôOytª‹Š%%ý”7÷ï(Xsï»»œyÇGnKõÏi;5²¬¸X­½Ë®è„A™·]ñKbYåX†Í² Ó¬!«ÅÌ΀Ÿ—£Ç}"g±JÝs0½µùè£Æhà uóó õ¼wœá>p  Žq {Í]oOn_—X7Û‚¶Îü_B.Ú«7¹~ý¾žÇ_éÚGY¼Œ‰kÑãpœ*©ÇTå`#^‹¬*ÃÎîö™ÿþ>ö4${¸û.;'CG@K)sgí ]æ'l],ÞßÁ1g¶bV3-ïš²ºòX>»òt‹,QÈÔü]ÝGåÍÌ!-0Aú”¢,³Sž wYºØÃ…£•8‹¡šhˆ8§ƒUð™E6T˜äâÝÈÉòYã>ª·¬´RŸŒ2#‰¯sBõ©›ßу÷x¿V\:9u*Ôj:ö%·ªÁ¾lÖÞõk'o¾*uù`ß/ °J—]M‘¬`=Ð÷¸ª\XYS’»É~"9›{zk©Ç –žœ¨‹èß´ÅÛ¬÷¹K½UN)óøŽŒnÇT—YsÀ¼ÿÁ~†à._×)ÚäVÌ›…åê0‘@iz‘e}ðÜ¥<ˆØ o²,¯êžxIc´Ãt©Ë°Z£÷Šáz˜H”R KÄ(¼ÒÄðPñûšŸu¢Éô.†¼›Ó÷®y'ö;»éF£2{HÓè(2ÑÛ(¼¥dNÞÆíz6éu`çž=+òÊ.; FÍSùòÖ84Å:ߙأ‡ÊzÅ”Å-©¯r n–‰OÃ(í–9 Ýú(.Õ 8gkß¡± E°SXÖT8KÅŠ¯-Uxs•[Ê ‡9QÐè^;à «”Uö/5ž³æÈqP¹Ò3¿rJC‘½A¶¤¥(J Ü$‡*He65«^Æ5 ]2êHì$*ÛðËÀðé Õ“èëÉM*ÿ¾)J26`]ÔÙ°†ácK—ß ‹Ùc{‡#1£´|^TÅœor.ÿrK¿Ð›Ç6.o¾fë%‹\œÚ˜RcqEp­*™jkrGÒ9E¼‘õ܈÷û(|Ù¶.›øü P¶{7±Ü#C¦Êì]ÿÝ2>ÍG´t²£³ÃÕuU)ìaî÷‡IVÈÉ¡pÙ|Y#Ž–Ãëê½²¯)æåŒ{îÀ7ÕÇHËpõæÖ~AñµQñ„™rN›XxIˆ‹€Iù”£¬Y¦‰wt¼‘{>h[c *ÆTÏ­=k¾ópNԑݰ$ŽVÆÃÇz:RIç^Yr±Á‚à®`‰[ÆFëéŠçeik±3}Ÿø8p{ÀàB‰0ÞÊã¨ë»9,ó‚7šÕfv{VßÝR`FIwÞ›V8”Æ æù´òÖÚí~À»­ßÃãJí|ü„8-5M@4!$A)xÅܱFX®.H“æ1Ñê§7”¼ƱwÌ–p`ý¢¾ÆëÔŒ}; 0 Ùüêª.8ìYé-”O¢·è;xã»hÝ'ê(–x'»¨ßíZèHÃïÔix¹(ŒN ¾_y&ÞÇém­×.µLr’ÚŠ=R§€!Là~ 7 x_ƒü˜o•Cî¹W¼%¨rz;Vûeðsç¶bÕ‡O†n®l\ ¯h/WmQÉ3½ásúÆ`Äá[v¾Ùwð¾«oÁ“‰*ƒÒ¾o³&»rh©R§ú£exC‚ŠšðŽi`#òS¿EL¢‘fáàJEÛ¨ÁDÃãõI0PJc \³ñ„·&^`°\Z™…‹–öâbà ¨^kD?ÃÞ?e3³nVIÚcð/O_»¼E“˜Krh1Ÿ@vÃH±]/úµZwE®äºïž[ß?C uGÓÓa·åº}Ü#“K»í8»Ó§ž²ZóTÌ›`ùøƒðÿ/ðÿ‰Ll€FN.ö¶FNÖÿ EC¥àendstream endobj 418 0 obj << /Type /Font /Subtype /Type1 /Encoding 1166 0 R /FirstChar 11 /LastChar 123 /Widths 1167 0 R /BaseFont /DWVPTU+CMR9 /FontDescriptor 416 0 R >> endobj 416 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /DWVPTU+CMR9 /ItalicAngle 0 /StemV 74 /XHeight 431 /FontBBox [-39 -250 1036 750] /Flags 4 /CharSet (/ff/fi/fl/percent/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/R/S/T/U/V/W/Y/Z/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash) /FontFile 417 0 R >> endobj 1167 0 obj [600 571 571 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 856 0 285 400 400 0 0 285 343 285 514 514 514 514 514 514 514 514 514 514 514 0 0 0 0 0 0 0 771 728 742 785 699 671 806 771 371 0 799 642 942 771 799 699 0 756 571 742 771 771 1056 0 771 628 0 0 0 0 0 0 514 571 457 571 457 314 514 571 285 314 542 285 856 571 514 571 542 402 405 400 571 542 742 542 542 457 514 ] endobj 1166 0 obj << /Type /Encoding /Differences [ 0 /.notdef 11/ff/fi/fl 14/.notdef 37/percent 38/.notdef 39/quoteright/parenleft/parenright 42/.notdef 44/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine 58/.notdef 65/A/B/C/D/E/F/G/H/I 74/.notdef 75/K/L/M/N/O/P 81/.notdef 82/R/S/T/U/V/W 88/.notdef 89/Y/Z 91/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash 124/.notdef] >> endobj 225 0 obj << /Length1 739 /Length2 1042 /Length3 532 /Length 1589 /Filter /FlateDecode >> stream xÚí’iTW†ET$¸´,Ú–ª—Ö !™H‰T…°ÈQ BQÆä’Œ$3a2Ámá`ATp àV‹Ú£‹€HkÈZ)ÚÊfeÑŠ HÝP¡Öö¶¿z:óg¾ï{ï{ŸyïeÚˆ=¤Ä:èCà”#â„€Ð?(áĉÃ`2…$D)ŒÀ½P âæ† p9q8»œ]L $T:“É)`'´ñ‡’˜Å?JÉ¡’ö  "$¤tNÀC¡#+Ô ª! ¥N RLBuP†á ö‘Eþë¶T£z3Š…¤š†v4¤= ¥®Ð)Œb°—ô^&ù7 ÆšûhŠå¨rÄ~4¥·æ¨SèþPJ•†‚$ð'¤ÄÇJCàk8(Å4ʱS? U`\¦€€óº…©}0-”`”D(RGÛ—Že s%`{z®Zº,Ðá NéTºŽ¨Gkä¯šŽ‡Ä´ œãÄá ´~ß|EŒÙÌ—R §o„‹+@IÕ1è«AW.`#0\ µji`¶NPô@g² D$cä®ÄZüHï¯ëV}ôtkïôóE?þvÏÅhÅÕöšüŒÐ£9}•½G켂n›´ÚŒ»{öbÖ6W¾ØG¯X•”Xh˳ |gL~²sRÛ†w2vOhkØš°>ir±CK?Q¦1Ì›|xÏÐZci]päŰQ°Ü™½Ä¬nZÕ¬ð—Q}~{ÚÔ}匂E¢‚RÝÐZ4e…ÌaÆwÑÌÙ jB³§Ez¼hûŠT×öä‡2õ¶Jñ} ‹…ái)K=%Â_¼;,»Óí~¼™ñÁ7üÎÅs{ênÞÕ?3NáFvIm.h‰ÙSOƵÛ7¤–šînÎ÷!;ž[©R³^}ò Úíxä¬%¯ê#´k³îÀ¦'Æ{"XïÅe>ͰÜiø¾è7zÿ|ne¡X–4ûº!Íj’×üE*9®»{ÚôÔ꞊#ö—-‚“¶È;øÕñ±32ú‘õÏò†ÌØs˜ó\ê§ÚXo=éÁÞ¸ò)©ük¾=ä;þ>ÓA¶yq¼a¯¶6±í%Û»"°to‚‡xÆšˆ{—;Y—› ½[|ZÛøÕìŽþ³â‡«óÄ'Oå¹'„]¹ömDÅŽŽK ¦¥¬Oìgy½¸¶qëžï«*Ów{³ÑÇM«Ê;ª[fŠ}c}µæW‡ N“›¸ŸÝÈîTñà*ÛS/œƒÏäômŒ˜°ÃW®^Ò^B,ÊÕ·5™—|êö^ÝîÓ¢èvÿw‹>Ù•jf®ªX¢¾l4¿HVX×^:~áyáÍÆÃÑ·™Ô¬É%-ò$äXu²Âê+w»­U‰w?>8aÍNWU½qËÁÛ 2c˜Y=P(– Ì»¶uç>;å5(Ò^M­}À‰žf'8êå¹H¿b Í!¸õIœ[}a¥ðÆ9\¹)Â8¦&iHi¯äó‚ôùúäûçÂâg î0‰8ô~HZe”…¨vN…ysÎð¶¸ÚFñ­‰i¶6ƒ<ÕØóÅÆeU’ôœ¼Ó,j¸®³50)©Ü[j¸Y7õÓ3èëq²ÃÉ÷ÝëÞ¬ÞÊ^±9Ó*7gjì¯ Ý“àx3íbÄ¡»+ÒA“w¢Ÿð›»ò뮚ÝÕù?È2³Ãt²¬5Ù&›c(r¿~[³n¸¿S0Óo®é‘Ó­ñ¡\[³¹V&ç ­ºbäÚǯr3ï´¬y´#7z¶û“Õ½ƒ3ùŸN²êùIçä u ×ÂL«zyÙ,[dkÓÄ*ôa¸›UÖ1»F×íÖQ—š†XÇËðòy¬é¢[Œeía­þÛ¶˜*¯÷<ôzĘâûræðêBK}C·ÜP|ñä¼)1_6™ØÛpþáÃøßà?a Q@”¤%JF3~©ï_9endstream endobj 226 0 obj << /Type /Font /Subtype /Type1 /Encoding 1168 0 R /FirstChar 43 /LastChar 43 /Widths 1169 0 R /BaseFont /BBUKLR+CMTT12 /FontDescriptor 224 0 R >> endobj 224 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /BBUKLR+CMTT12 /ItalicAngle 0 /StemV 65 /XHeight 431 /FontBBox [-1 -234 524 695] /Flags 4 /CharSet (/plus) /FontFile 225 0 R >> endobj 1169 0 obj [515 ] endobj 1168 0 obj << /Type /Encoding /Differences [ 0 /.notdef 43/plus 44/.notdef] >> endobj 103 0 obj << /Length1 769 /Length2 1155 /Length3 532 /Length 1717 /Filter /FlateDecode >> stream xÚíRkXgÁ€‚Xm¹Ô±lÉ@$Z׈"†»ˆxÁ!ÂÈd&  ‚ZµTPD+± Šˆ«ÈÊ ÔE Te„ Ht¡´RQ®‹;€î>KnõÙ™?óžó~ç;sÞ×ÊÒÇߎ/ÁCa!Ž‘v =È"€ö,š••€€!Á17ˆ„yÈå‚_!(Þ™çèÈsdÓ¬.Wˆ4œë©&g€/ƒ D a€"Ãa¥!†PÀ#0©´ø( øMˆüà(˜ˆ†%ö4$ˆ˜Ba)‚јSŽ<°0pž% ù*&¢(Sƒ2i P%8†* FczáÔ]0åä÷05[\¨@Q/H6%?ÒoxH† Ê÷¸L® aá˜Àf·n‚g̉` ¢Íf=HEÄ|LŠÂkB¢„H,,ñAHq8¡Qð4c’Ù&¨à¦-0Eîn‚@Û÷&} #”òËNuO×àj*‰¶°ìY,j¤Þ_Ûf]掉q ‚Q+áÄ ‚€”4j7¨Ê ˆ“À±K9fÚc8I¨Pva8A›(›0åc(FNQ3(øàüÛ_tuÅcãì8 `çàĸ\.àìÄÝý_}bA‰ÓëCåô¡C¨Ta8Óž´ââ•_ïL½y(ûùæËº6Ú®Ò’d¯·Tx|BÍû›g¤MgQÐXAÆâ…]Íg1æQG*ã}ï Ù™œöhR½C“±«Ì<è× ‘²WN>ÐoTqóáÐONÚÞ?t6æŸÚ|¡þ쫆þl†[À ½§–Zê-ÑÅê3_sœƒ„èFÕÁ¢?9Zú§Eæ'°U1ƧRæv4سS¥_jÛ>ˆW*LÆÎëgœÜ:¼äø"qÕ÷} IzÅÜö‡/‹ï¶¤Ýr!ÿªJà|Ûï42ÝNÿT‹ë®îÆ/SÜA­™]Øè"ªº-¾P4ÉqXpÝ!ñÄÆÒ1t0xÉÇË]=ßìZú83qa†cï+…x\ií ÚÞmœ­ÖÐ~ý¾F}…‡…¥ŒTì±;TþÒgiaèĵ©þ ûàëÜZ™¶›ßnLîÏê\g¶‹ý"¼î»jk $_“áY*|hÒÒ6rä}Ю2û^CqemÒ¼k?œðèøÉÏðxùâˆýÝ]J#­¢¥ æ ý—kKhæÖ¾¢ãç: ,Oü¨ê,G°hoõ0÷xjÿ7›côÄ Ê=åæÂ>Ó‚ëmUÙ‘7–Þ÷1Ú&i>Úøf'Ûu÷*‘¡à cÆÉ}£5O̽‡–ñ£«û˜ ní'ªÝ¨aD´óŽ1ŽHkÞv‹«g£;¿mn¹+|š—“'ÿy>g|í¼{¡Ý즟¬Ï[R—Ä ²T¯ç'ßÙ.)ýHý± [Úη8g‡‡Ý“«{üêb"Y©æ¼ÖßïÑ凤#Ü“ hž^äôÅT%Š3yÊwÍ%ž_2^y¬_Âà7Iø¢ Pœ~$dÍø—“¼¬ÛˆìyWKÒ­Ö—ž§@ń˻:›LÊÅùú©‰i5½s¼Ö9”uý“~üm£Áákî::†û{ÞDÊÖ@àÁs›ã»C‰3õ–C\zY÷Ñ3ÖÕ|±;Td·¸nl’fRçnŠÐ#èZ.…Imé4¯…þí}7Ó­b —{÷%›¨^X›œ®]x¥!Ÿ$0ájNÊŸQ£Ö±¶úbf{¸ä6—dí‚¿~ÝrùX€’;>Z;°ëŽõ«U¹ïjr/ÚݮИž6ëŠÝ6ßÍÓ‘{ÒôÜd³ž‹m@ÇÕjËgËÏ d¬³Õþ•qe£ÛØL_åAòïßè|vA[|)Bs—mÅÉÒw®§?=M?)y>Т_½×)‡V”¦ÿö•ž¬Cn|&Ûak·ú¾Î‚·1*K§¦¹CÏÿq9ÂÃ˶–iïh¶ç«È£sh‹æ|%úhNϵÕÃú+ïu^‰ ¿Q×ìXJš“Ã]¶ž£~–WÜ‚ IŒY^fTÛ§9'tàf³…Ðk/©ÍDcתæ’7ë»øG‰žMYå¢9z+?êI/\ÏÏÕj%Д•.þÜ·($ÒÐúÒþC[ò齨9µ4PÛ;·±ÝÂAaÐz XÞ¹µÏô’ à'oO 3¸ò4Ý¿¶õ†Ú(÷éç «×f4ü¥iSÓidïP„Æ<ÆúÚÿþb†—ADí_uaœãendstream endobj 104 0 obj << /Type /Font /Subtype /Type1 /Encoding 1170 0 R /FirstChar 40 /LastChar 41 /Widths 1171 0 R /BaseFont /MEDVCV+CMSS10 /FontDescriptor 102 0 R >> endobj 102 0 obj << /Ascent 694 /CapHeight 694 /Descent -194 /FontName /MEDVCV+CMSS10 /ItalicAngle 0 /StemV 78 /XHeight 444 /FontBBox [-61 -250 999 759] /Flags 4 /CharSet (/parenleft/parenright) /FontFile 103 0 R >> endobj 1171 0 obj [389 389 ] endobj 1170 0 obj << /Type /Encoding /Differences [ 0 /.notdef 40/parenleft/parenright 42/.notdef] >> endobj 80 0 obj << /Length1 750 /Length2 576 /Length3 532 /Length 1110 /Filter /FlateDecode >> stream xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž44P0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22°25çRUpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥r‘g^Z¾‚9D8¥´&U–ZT t”‚Бš @'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<8”0äs3s*¡*òs JKR‹|óSR‹òЕ†§B盚’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l ‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;|`‡è»……ù8kCã,˜™WRYª`€P æ"øÀP*ʬPˆ6Ð300*B+Í2×¼äü”̼t#S3…Ä¢¢ÄJ.` òLª 2óRR+R+€.Ö×ËË/jQM­BZ~(ZÉI? ´©% q.L89åWTëY*èZš 644S077­EQ˜\ZT”šWN+Àà€ñÓ2A˜šZ‘šÌuóZ~²uKÖômm+ë\_XŪÏùóÄÚ—7ÙD쨛™Rl:/P1½dÉ«…¶öϾ(á•l=U¸h‹d¯_OÜ—EÂk¶v-X1¡Át¿Þ`ñÊæ®i¼ÿ´Õ_y. ›1§õ‘´Õþ¢Ç³:•un~Q®?Á3/å…SÔâ}ßï]ãÒ š¤¥$e~sû]F1ñÊ»Ï/ËÚQ?ý¸mò»³·|<ċݺÔ/¦Ùq'}Iüö„+6­ìâEíÀgޝ¼xT.‘òGÀ¿gtÅÙ¥vÕG‚—U|íª“®¾~ª€]üRÇëÞ…_kü9¹öË:½{ápËñGúý îûd}dN<6Îø-uBÛošHºÁ=c¦MÏvHžÎzºq½aûÿìRKë~,KÌž³}Š¬Ë›ªÂå»m¿‡Š÷Öêyo›ù~ÉîÃÜ×v‹ Û_¹éÜÿs>§ß¶.#ßҭߦíÈè{­/þô­É™kÜ—öÉ\mü|¢Ðr¢úÿXöÑñßϾØad­j|ïÇéÖR/ü,2 p0, HÎIM,*ÉÏM,Êær„endstream endobj 81 0 obj << /Type /Font /Subtype /Type1 /Encoding 1172 0 R /FirstChar 15 /LastChar 15 /Widths 1173 0 R /BaseFont /FVVLAS+CMSY10 /FontDescriptor 79 0 R >> endobj 79 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 /FontName /FVVLAS+CMSY10 /ItalicAngle -14.035 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/bullet) /FontFile 80 0 R >> endobj 1173 0 obj [500 ] endobj 1172 0 obj << /Type /Encoding /Differences [ 0 /.notdef 15/bullet 16/.notdef] >> endobj 55 0 obj << /Length1 1179 /Length2 7270 /Length3 532 /Length 8031 /Filter /FlateDecode >> stream xÚí–eTÛë¶îÑÁÝi€¢-\ w·¢m Á Ü)îV¼h¡¸+Nq·ÅÝÝ)ÚËZçìÝu÷ùxï§;n’ÿß|çûÌ'sÎŒZ5M6qˆ TÆæÄb %•µäAœ@;'§€A;YÚÁ¤ÀNP! HP (5yzxúñò ø @I;{w¸¥¹…Y’å¯$~ ¸-ni †•ÁNPÛ' S° PÓÎÔêäη±jüuèu„Â] v„Xš:M æ–0Ç_žäafv@þÿ Cœíÿuä…;>™2ÿm“ødb³qB f»§jÐ'/ÿ7lý§¸Œ³ Øö/ù¿;õ?ÎÁ¶–6îÿagkïì…•í P8ì?Su¡ÿeN ±t¶ýÏSy'°¥©8ÌÜ dñ°sòüWÜÒQÆÒ Q³t2µšm¡Ç¡0È:yêßß>8d¤u$µe^þ÷hÿ>T[œ´Üí¡@Î?Ù3è?5 né4à|ê2è)ñéý¯'£ÿ(& 3µƒXÂÌ\¼|@0v<-Ññ=A@Kꄺ=9æ`‡Ù9=]>uÆhfü5WÃÌò¯ØßÈÃä°š”äß!^ ‡©ÍÓÐÿáãrˆÿ!A ‡ô¿‰äýCÜ@ù?ô¤¤ò‡žî©þ›8jèÉ•Æârhý!~ ‡î¿éiµ8Àè©‚Ézª`úoq>•€üŸœBÿOVÍÿOßÑòø$ló|R¶ýƒO³å€ýŸ”íþOöáÿÀ'eÇàSÇþOÊ®ëIÙíø¤ìþ7þÏ“°sódñqÙ¸x9ÿ*Ëäôþß2Máp(ÌéïŸõÓâþ‹Í,Ÿv uƒšf§íL…­’ë‚‹|¤sÇŠQY©R ‡ZƒjR…Ù÷—„ &áõ£ZPš3ü |+˼¤CÅ2ˆï y¸W¯§&GÐ ~/6KNš&ڱ龡1R_VO®mFØöìó ûú—Çsô—Ë.­¨J» þÏä‡á(E?§Î}¬}‡Wf1S ô›I£¬&¥D¨ÎÎrìàí¬]®Ýì—>RôKÂÇYòŽÅ ëìTÁˆ,eä©T‘{ N7³Õaè“õóÙ·™‚r¿+k¶qiÙû]¦ÕRgT°ù :ñ¨­&¬P ùchø$Ñ2VúK´j\ÙüÇ&K{/8j>£ä¶)PN?;X µ¦? R #ïüØádºÁœ4+ÜÀq€ŒjWsÝNòø;EMæ Š½|nlNþÒŸ${æ‘óæÄà„ä²vˆ ˆ–tôL+Q‚£Q»u·m6EF9Å£k‚¿ý6Ÿ]{Ä“ß?W±ƒ]dT{¶â4S+Zò›1éÁŽoaQPÉ‹ UþÎO7ÉlN[²pvÌt¡sTt-–`ÀÜ¥Ý뀱ò°òÍýxȳú;3jTNieìéžn€‡€sÏà¯WËsÖçb¾ßÛáKý® “»8¼Ì¬¤(H¼0ýôÙ’@«FÀÆÛÆx -ª&ˆFuæ”2·-&y|túx cYÀ>0“½W ÿ3D€Uب IÃK޶ö¬ŸAk—sÝ€­m8Å/-ºÿ>w);XÚ˾´Rgÿ÷…rû—¦IíU#ÈD­1ªVÙæ ð…œçøÓ›Ù=Ëkå©ÕÑ#‰ùS{VÂj§¦©TØ^Jb-?¿¥új”h¨<Ø[s¾F9½²cIäÒºÕš+ß™t ñ&ožˆN«u©ÜCÿàð€€ùþ§ðkÝk­f´ýþ6gJï—\Ò©àú®ÊÙH VüÖ‘k;•{œ£0¸¨Í¡æºy”#·)Û‰EùÉ£÷® ð\ž`~^gÒ¯÷\E~{«/<½w„…7lÏ‚R~Ûä'‚˜$Y“|T'©ßOo¢¦½½Õ†sƹÕz‘˜Žö·0YJµì1膫Р¯îIÍ'j^°/Ž –k°Rw,hˆ¡À”Ötãë‘:B9 k‡¶wêrr惫öBEå(÷jßÐÎ6%l»a}q-+&É4+ñF«ÁgºŸIŒjl‘•b—K‚¼Ô¼æ™ö‰à“;³¤[¯R–+å{ÃǵßHå&~h±ÖV‡bP‰£M¬£&ég¿ 7/¯TŽ3*ûþMA“‚ÚœµøÙî5°1T< `:~“Ûúk~øy:‚ðÏÀ, a¥€ïš_ b¿ß¬»Ë馶s (ó/?OÛ \œÄÞ']ïlEîí|]«¬óŠWÆ^ÞÝSg­XòÈ:R,9Ü;A߯͊`ºíVä÷6‚n+¢Uõ@o£Ûöµîª|baÙ­úPàŸÎ·!9Ù†H„Y5Aßî05¸ä•°j!7fË+c:ïA‚Œäb;'Mæ²-_â–¿‚¹Üà?¾büžÈñ©šBq#Ûyn xàñ.t¨¡„‡-Hºûæé`çÈ®fXˆi²•.Ëan”%¶gdÇ3wdÑc£15H°ÐX8<ê!–¦O=DóQ¨ ¹¦‰ÉÍÎ#|þjÚ÷£hßï6oðc ›1ʶ6…Tš¾N4¬¼ÚI§[î.uô±×„þme·}ØÅ kn¦xOIXzë¼ÀðÌ åž ~ŽÑ›ß”Êš³Ã> ×ó¹; ´‰b¶’}ÐÍñЉ5ª°ø“]æx²¡SÎ!úŸÐJK},©-x (®ÇïÜ E_Ô$6ixsÕ ^F+^JßPòS`ʱÕÕÆ¡1DŸ¸^¾ô¹3~“9ó Ë Ú^†Ç–饈ݵÍw؉é4:KIŸ3¡%&.“=5é¥}ÓïS nž¢WZ;ÿ#ráôƘÅWþð‹©aõµçͤ§Ú,Y¢?cw$_m]"l\j)È n…¬5Y I™0¥2DôÐUg?‚õãÛ÷œ©=øj扫]œ_Ò$7`†NœæŒ¡¡JGáßÔ+r›%á…m¤Žãî´3 ¼³“\¨9ÝÔÀèÄ`/÷í ¦£ù1Äæ ¸´”í•U_äUfmj6._’]gT°@_¸½Sá‘J¾·ö¹96yJš©hHcSDAl¼£ý«ç»ù"—`€× ‚…ž_5HtùízE2W í£ñâÀB{êÖú³çÑü¾ƒ2ƒÅS/TxïúE±äx´i°ì•‰ËE¢ 1K®]ra–mƒîöp¢»©á¯ä…×_ž·LÒÛg3÷6ß‹8úg •OaiÝὸ½†FÀÎ%p -½çËÊ `;ª«Ž<êÔÖÏ^žç±Á¹ÝÒº—¤×Ío½âÄ©›=ƒeM+,ðVÍlÈs'´9“ìßv\zfdÿZðöìKG¡³Ÿ" Áv¹WûI÷¶‰pêM[·ÙU”HÛÊé]<êL1úbÝ#ÁrEäªó+nN^ÔVŠvˆ¨‡bŸ¶iS,j*‰që×Ó®‰Bºªâ›øfîÓhÀÉÕ¶&"úp‘_]ÿ¬…ͳ(ëVxÚçd…|ë–øî’Hštt›Z…¬W´¢Âmž²[‚áƒß±\S÷`þbÜ¿¢Ä¾›&·iÙ87å ìøØÌäVÔ''‰g'ñjxbFC\ne®4Žâ¦Ô»0 ÉstW#K+ |†Íyš_ŸÑxoIã0²f :çD£úÑtU¥¥¨"F!r*±ðzd6<ºÇbÛÆXC  êlʪÙWöE}Š-E¦ˆnÃ:FÂüΟveâ÷2m•óê2v Ñ8Û|âû?Rð³ÈYÜð[¦ahòÕ¬ ™2"-q1ÿ–¥2ÂŒ@”y3ña3í­ÕpUùqë¼_=Ø|‹8!-Ÿ¤ß\¾e•çý©X^'ád |è+RròŒ®t–â€d܆Á9ðfë›"1Ôz#+Ò×'õ’Sc¬M»,K,ÍonU£’4švG±Û.Ånëû‰ªú„Nä[¾iA,Ã|Ë`:¾%)†ï)x ̵y­ó²¼ãK°™ëü/h°1~j–"ÝÎP†ó#LÕw½n´ËVúKKðÎZÜ.©Ë¶|C$,rÖBël}(|¬|4$ƒ`Hµmëᤡï?ñ·‡$Ù‡3ÛxD¥ñ‚•¥Ýè_up_×óÊ_ŒuQN± PŒTa) _wqD¹ÈyÐ& e‰[€€ußw‡Þ“´v`XJ0ìV«D†¢SÝî»iË¡ª:Âüîù‘ºÍµa|›å§%QÝA›Q9‘j‘2YÔM2´ŸtÓ€‹˜¢& MO©oÿ¼S ¬€FïÇÌè²óñÃ`ÁíÙ0 äš(Å…b§Û”øñ=Áßbö§¾^Dlü2 ZË;¡EًгÊHs£ÔVgË¥ýpvA¶¬èDÃk"M» EKŒ§9†yÁy?_}Ty¨²ÍÃ\Py6ðÒØ‰h+q?Ôÿ.”O±ìQü\<w×]ßÛÊú_‰÷ã²`ÐJµ0žè·êˆ~|~í9­ˆ RXïžK·wäSíaJèÝú»¡]i†Ø^#fõ8I’“—ˆwéCc…~:?_]N”†¾Ò >ñ?øN •Òø…7{Ørˆ¶OPŸ:@ÃË?ï·E¼á÷R˜[áünÃVdxߘã†iäy>Ïg™.zÖ£=„Áƹ/%2Ìûz(Ô̺ª\œ¹-ä¼nC_¸QQ¿»¹c¦¼£Âœ3 *ã^blcÎÄŽ µScȧgp%²¿á÷\2Ú·Ó8’D×þFM_úàF cŸUc(êØEÒ£jäèòš.u˜ýLÚfäkiŠc+CήMpÔôZb+‘ÇPÌ×](ì\vjÈêÀºpäZžê€ A„ó”p”Ÿ M~(̦³ý vÓ­áë œ1»Ç}’âezQ‹ð³t }Ms´ŠpE5 Z½êAþÝ=MɧXœ™rùü)ˆlŠõÈdĽ›Lâlw·¯áƒ¼_D;íΠΦŒ1ÓR>{ØŠCˆR ; ŸV æ;Û¶&÷6‘qœõ°¥˜¹áëÒknÎÎ@^~véCýP)³±tGu;š^~Më¸ËÝ…üèÞ¬E˜TOoÑ_]Q¬Šð¤>•ÛS!rËš8B˜ÆùH9žöá—™ý)½h «]>È~8­WkÙõJÔÛ‘áò˜Døªérð¹s»£‹5ø F×±8¢WùÜE|è´é¼<½i&Uqž à%›Ó.ÿ€^%-Ž2Üÿ…[[%8«øõ¡|wãùÜ‚§œ“ñAæ7uÖ!?}t=ŸÀgEb©jªÓù2 Bie¬7óÕ w&6Òboª¿ssêì"¯«iˆÞ’ºD¸Ù¹´Îå~]¤D—¡]BigLŸºùð™ìáÊ$Z®Pv^ø¹9HE éâvU¢íø¶ñ½ÆÉp/hªµàz˜Pž“áñŽgÓ@k4\{€F÷SÞÀ4þ~ –|M‹½©CuQ´ˆ_Øä˱ue¢°ÊØ\Z¿W<~m¤möŽB…½Ãì`ɸæë–U‚6êIº7 Ÿ7Ù?U½á=ÒéyÕÁ¾VCÙnJ¯˜“+˹Lº€½zÁõîuæÞÚäIDÃZìF}ÜÆú‚à‹L¼ºJ_Þpg£_ɳ|]~ññ*]}?n]…×@¿_&Í:ª¹'e Y„Â6µ€”çÒ-òžQ—j•,Uè d çSxÎ4Ç:°”ô²¦¯dùÑ v­Æ„~8ÀèAŒ†»Ú³¸u^ö½Õ>¿Ú,cFžo Àgù_Ã}ZZ¾º6\l˜ü óAþ) ¹S“ CÀ, tqã”4Ø$®˜úDU ùÍ0Ò_† ô,õèNøeÑIP“°Õ¢Æ¥“á•€7ž;ŸC~é_esæÎÐX¾zv´&¿ÜÉüÑõ&••t‚*Zœi€kŽG{ƒµ&Ñ`PQ»'Ü&aáĨW®Í–pæy¥èaÜ 7Z¢T˨ÚíNýhŸ”Õ°b¤1A_É’E>¹Â‘ÊRŸ#@êó)‰^¡8L^’Mî!²ØØŸ6¹g׳L÷Ž·À¤ ëCo«— 6vðó‡ŒA°úЋ$V€o“?#î|:êvåõœa3w‡]ç6‹ÈýìŠ,xµ‹?ònà¸ãÎ3$VÓìaXíA€=€@Er5mžt™¿2í Œ¹xð»‡å{Î’ Ø7ü™PjØWnÕTC¼ÑcüHÒYn§>iŒîßñּ͈ŒÕ¢Ëv ¼æª@©‘Pù;¢$nŠÑD¨I¼m¥R®¯éUÙÈZ¡âuˆœYdgˆÊN¿ïé»ð„0K,-ÜÚ:÷ mà~.u hp(û;@ËH¨‹ížÜB5€;L: »=³jÇpü1Rmª¹iƶù«çAÎwò—3ñ¡”J9I_SØ7ï#(öÂG±ÝRÈ•¦üõé'¥uÜ对ÛLñNÅLí¸R€ê4¢lŲ¹£¡í¼¥%ѤG+y˜—4¯z¤¿Ñõƒ m2At4‚ö‘ºe›8—îXun­dü‘ü›Òþ ì{ÅAá½4óÁ„ê½Y%éçÏôBíÍè|w²^Øò`JõÂF"åØÈ4 "»Ó ƒRÞoªbS"R+q•fÜ$ˆŽSÔÌ{QöE‰8F9"Czc ¤Ü?È l»täË_K’iÊ¡µî#ØpÏkè°e(›HQ‡ª?gL™5Ëb×H%Å^ZÒ>ðáJdrh¯üÐ3OVÈŠ¨(¢ÍÁhW,hÒ í­Á×*ÛÿžP!<Çýj@F^äœq,Qu¦°õ*›6YÚë¢ÞðâAMWÃÅRS|‘5nÊ'”«Ì/ù`?ë,´¨ð«™(ÜØåòZWŽÊU-㵟®ðWóڻȔ ðýcSLz$Ú^‚›0òâ8z`{³BÒ¤Üy‚š6FóïZ‡þ4”Aãn÷˜m/¥,Öïè8±.q=¬Õ¡=7CAûÆžW"¥ªÑØ—4fµäL÷[î¸w1‹Û«É€.~6= ¸KÞž›•1¨‰p èH”»\ ra & ;Ù»`úQ‰ÅÓ§Î/Ç…¤+\ØLjt{HHr\Þz‚ÄgȔޞr<† –½M—t2̯Ýe?vé0C²O,xgœm½00ô9ººÁžÈŪVÚðUz›ÉÒ7ǹ‰‰ª]áwÆLj¼7ÉWß cYÚæ2³K,o»92®Å²>#4ÎÈ™§6ã/t,= ,¼ÚDöTmlÐj&ú¢’½YI”èX,è/G™oršÆAcðô‹ñ¡Ô³O|¨í‘QÉù ²‘s©qó„²({ňúF“ÒÓGÔHàFÑyÈÃä­T)D}sØ:Á©¤Urÿ±KSZx–Ý~Í;eєߚù*6D»èòÓnë4_‹ÁñŒ¨Mó%ï{ÜŸ\TGïüY8Årâ&§%yD Þ´=÷ž3O?ûÒœð~¶y©Ì‚OÇ`!tX@z½æŽ2î…œ8³ã0¼8]ç! f ƒ—÷,Ñhy˜rG+ªý3 fjJA¿¨<óÛ‡¨4¨2üž`ZAÉ~ŒÕø›_K“ ÷æàÿ v¡k=­äÀ–”TÁå …ÔƒðP%y0WUF0«Ë”>Äéq#ÑqŸq½óeè_÷˜Çq ‘܈M´®û5b(n“o»RGaÚê)¼ èpœ¹ÊøZHˆ·˜›ÈmŒ8¼R²¥|À™ Â´ÿ»:иLAf@ÉŸk K*÷ç8o@DZ—ú¤ÿvÚÙejÚ íˆã˶æ&ß=_ZIJò5;š6&4å‘Ó°p²cÜÐâs*Æ·\7ëïÓþÖàý\.á4åí<óÞ{mÅ˼~}ß8,ìYçkMˆ³§C¶«0ó[ØÆÇ•ß1L*=:œeO{"> åÈV:¯ŠhäÔ<£FŽgPâ—‹™S‰2ï<yí®dúK¹NX ¿:±UpÏÀñ»ök9‘»%-?ÙõKUºõû V-¿ Þª^[î¤KAÍÿ8@8Ã}7Øš|¦ˆæîÄÆZ!Øû]Á«-1£jD;ÐûȞŸSnyG.¯ v ô±èûä•^Óß4þ¤©Æ7gÅ,·M–¿G\¼îIäfÈO³÷ÜŠŽdæ;»-Üw°ï+ï +ôõ”<ào=Ab™ ¢„Õ½±Æ„~ ¤ VÖÀ¹1–ó+q fcÎ)Y 2^n ºË›ynn}õWg‘¨|÷º¹ y5qÑ`*ˆÖ'‹¾©zâØjÏif8 „´•)â”xÐåcpãTù¢f»Šm̨ÍôØ´EO-«}òQfÍ7!äõ4l{¼,y<ðÚßó|§pűsŸA¸2eøöóÜÿ—ÓrºÈ N$Á/IƯu/ÆÑõ· *ÑôÞú?„Óº™QwÅGŸí¡Þ’¿ýY².ßD‹v.„½ 26€áõäú&¨gǽÐC6$vx óE|C›è‘[P§!3•Mc>¾PÙðv`‰Ê¼ž‡ã lCÇÊ?0äô;­¾ª5GϦ¸1Òøyú~«åÒ±'n×ýXPÑýŒå1“}C¿wUgEMæ@XEB޹×)¿ÕÅþÏ€¡ö’É•š, ž)b·Ðb] Гÿ$Öy¿OgÙÛ~)7ØÊž w–Z‚$–,r¼¯œbͤó†)J²jÎÖƒ–š7kjWÕˆ$ûÌK‘Iß"Å*k&Êóó "³ÍV£Zi”“Að7Â,L”½ ïK]ºlž{Š<µj+*@%{M0ï/SM]Â~JÁµÌo›Cú[ èеòî?[Ž–Óülx†AÏÏtI±ì+´êow$_ˆK 5Î߇^Híj¢Ÿ4G(LFîZ‘þX`Uϧq\¸º Ø.ÿñS¼<;®L©Ñ¡úo²tÇ €Ë;æÌ[–÷Ýží®òÊ›f9ÊõÒ>¶?áx;üXlùjd4`ÝÌŽæÓÁ¸œWØYî—Åì9½u&â·­mÇŸ¿ÈËMx«•Ô:ã W4Ð[PÊOí À·€ðÏ“‘+Ô—jaéBtߪßzì¿1ƤËMëDÉeY ÖP ™r´Y&µbL”*Û†%£4Ú¬?L‹É¿¿¯ M°SW .Ÿx_bc9Æb®‘,³äöâˆTUóÝC‹’^ÇÊu.}å~ŒøïÄóGY‘¶ô‚Ê*p|¯ÂߨißâAüßÚI¨µvÔ–aØ4Ó6+_Þd§¬ y+ !&pþ¾ÿ_àÿ S(îdg †[þ|ÿõNendstream endobj 56 0 obj << /Type /Font /Subtype /Type1 /Encoding 1174 0 R /FirstChar 12 /LastChar 121 /Widths 1175 0 R /BaseFont /FEVCUF+CMTI10 /FontDescriptor 54 0 R >> endobj 54 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /FEVCUF+CMTI10 /ItalicAngle -14.04 /StemV 68 /XHeight 431 /FontBBox [-163 -250 1146 969] /Flags 4 /CharSet (/fi/period/colon/A/E/G/I/N/O/P/R/T/W/a/b/c/d/e/g/i/l/m/n/o/r/s/t/w/x/y) /FontFile 55 0 R >> endobj 1175 0 obj [562 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 307 0 0 0 0 0 0 0 0 0 0 0 307 0 0 0 0 0 0 743 0 0 0 678 0 774 0 386 0 0 0 0 743 767 678 0 729 0 716 0 0 999 0 0 0 0 0 0 0 0 0 511 460 460 511 460 0 460 0 307 0 0 256 818 562 511 0 0 422 409 332 0 0 664 464 486 ] endobj 1174 0 obj << /Type /Encoding /Differences [ 0 /.notdef 12/fi 13/.notdef 46/period 47/.notdef 58/colon 59/.notdef 65/A 66/.notdef 69/E 70/.notdef 71/G 72/.notdef 73/I 74/.notdef 78/N/O/P 81/.notdef 82/R 83/.notdef 84/T 85/.notdef 87/W 88/.notdef 97/a/b/c/d/e 102/.notdef 103/g 104/.notdef 105/i 106/.notdef 108/l/m/n/o 112/.notdef 114/r/s/t 117/.notdef 119/w/x/y 122/.notdef] >> endobj 51 0 obj << /Length1 1418 /Length2 7328 /Length3 532 /Length 8182 /Filter /FlateDecode >> stream xÚí–eX›Û¶¨ƒC(îœâî®Åµ@q NÁ¥X¡P(Vܽ8ŵ@ñâZ´xÑ"E‹¸YkŸ½Ú»ÏÏ{ç$òŽ9æoÆœ_ž0ÒjérÈØ@­ÀŠPˆ'(HN]WMO‡ÄÃÉ dd”ƒ-= yK°(ˆGD„$ãiâ…¯ ŠòóˆòóArPW_˜ƒ½ˆEîé_IB 0ÌÁÚR·ô°»ÀkX[:ƒt¡Ö`_NŒ³3Hç¯î °;æ¶áòð€l¬=@V`;ë/'eˆ-$ô¯°§ë¿—¼À0w¸ˆ.ùW´Bœ}A6`[ —Þ 7ùÿ!õŸÅ=5,]þ*ÿ_súo–.ξÿ•uqõôÃ@êP0 òŸ©à驃m<]þsUÙÃÒÙÁZbç qˆpò þ+ìà®èà¶Ñrð°¶yÀ<Á‡Á›ÿô€Oïo .U™ò lÿìßËZ–=_W0ˆûwþßÌó›ác‚9ø€Œ¹9¹¹yà‰ð÷¿?™þG;ˆ5ÔÆ¿‚ KÌÒ¿"pùó€ 6`Ø®ÌÅ zÀ·€à“y ²…€+¿ˆËÞ×Õ ù+þ¯ ˆË~^P›ß!!—»³¥»ýïˆ0ˆË ƒþˆ€¸ ð?,À âòðþ½.Àg{ø ^—-Ôö;À8xý‘7ù×Qý·µ†:CÛ Â¿€Ìo‚‹Êý&x¶ü?$¯¦ö›à™ê¿ n¯ù ÃÍt~|Ÿþ?$ïç Ÿ*ÌÝ û­ ¿ä\–¿ ÞØê7Á‹[ÿC<ÜðÉØüðÁ€ÿÀ¿¦òÂgb÷òÃë„Ë8üp §?náüÂ5\~#üBrAþ@¸ô„k¸þð¾°?Þ×ý„OÈã„kxþp ¯?®áýá?h\> \Ã÷„køýÿý!“•…úøsÀ÷sðòñá]E_þ_yÖž0âñ÷¯üIý7Û:Àm0Øl \œƒZ‹…9¦6½. T(œ,Ga)BY#ú!QÛ»ŽÌsmî¾4䮀E=©‹D€˜J3¸;¹Cõ~9ÃdŽÇkD}ו¹eå’¬•F—šÍZú%å9dæWv-ýöHg?¦aâÔrz‡ ‹e$ø™Ó/†à«ÛvÇ­?gál“ a|ÉÓ-€qR µ¸ç9è§‘0ª¼'ŽFZw•0Ûð^S€F}.„ouÞ*+e_!,:]é'Y'_Æÿˆ’{K­Ñ2šTe[8lÊÌRÿšÔ¤u{.cA1»lh8” ŒníOkIAŸ!®(ý„FüqÄgÖØeÙfïvk~ÐXàøÝ$@€³-}¼õÕiÎI)†”ºcÕd f“!ûAü­þZ~^¥áêS‰]ia`‘·¸ª…³…Æ®FYfN,#ãç° žøñg’·iW}ÄMu½r«Ö®:·ßè1èŽ^ùõÌ£A ª”¶uHED¡/2B¯9„qÃtF‡„ûÎ+º¶¬b. ì–œ ¯B¡:Žý{€¶ÀcÓêR+¯«,bÛ°”¡v?ø@òkoÐ\3¯¥Dîéû ’ÈÁïüKîh2ÔóG1àÐHyýu’˜æÃË1õ…ÇIéщÂì¤Ã Ôj‘N“¡oû}¥”˜{×Ù4ɸx¦¾ûNmePiNI8›±ÊV©ªSöûçm_ãs5曫S­”Ž*uQ½Œ½±»Pöÿ„€’VÍ;ñÚôñǯ ›¯ûgƒÊäX/ öõ’ê=Àª0kç‚®’ä'€.z[»Ã wšKeÿÔc_=¬>I*6¾Ó?µ5e&QèÈ%þ?­¹ÀŸŽÏ°˜˜f?®hÝÞWG™éµ”/ÎVciùô>©í5™q±ãÆÍZ g¿¬3O­³ì›c‘Ï\RÞ‰€4}iqŽ!¨ÈnZø Ñ𰜋Eú×ÈGÁÒ_Ã¾Ò:¶7‰f«1ÐÜä¬ábLηÜÃݺS¬ß0þQ¿û‚f<ãx) Vî6²ìú­é¬èC(o 3BÚ†ëÃ÷ÓÂÅù ýhÄ;ž ¬&­}æ%…ì÷\=@¹4³ài/g÷϶|\Àzá-ªãü¨U) RþaõÞÔó÷¬ŸâΟk¾`Þ Š­à‹Ói6x<³ßyXöãSçyƒàòM,Ùôötâyfà|ÛŒ>^,Õʬf¢†òˆ•€Þ4?é¬Q,ß0o,5ë4âpyI$bÂ{Y‘ ‹™_É ¡nÉ![ ëÅÞ=ù9LýB†™3·]åMÎQö¯]%äÀ'þ‚Ù(J·z4×Ô=qìŠøÊŸeÂí:]©»2¥¨¯8îî÷f&E%X«#ÌE¯‹4¾KÓHQßZ¢Víù¼pL!¥é½±XÑÎÍ­aEOû ™£…‰Ï£’g´0wñ2쬌HÐAÙ¾:­æ,ôôø_L.XÉUåöß}!°¤ÌŠ2¢)…b5˜dÐÕ“<Úô@Úû)ž^e[˜–½Åãxý‡Ž±Á‚´ÅìP‹²ˆ›ý¬Æä94©Æôh\zJIÓMCÞ"ŒåK—õ訣P0åŽáno£¤õ@sýíý¸6Ò#»d:ÂØ¶×ü»)عñë>uÚÒRJɤºnÖ½ÑØ4•ÚïjôÈ•Øo(V™½®èÀäš1«©ÁQ£÷ A|ykaq™Ïiútø¼xµ²®pãEGÞ „ÕÅLÄÁʳǾÒËíÚ@ÑXxm“Ò± þnœOîÐP€emCßñ #I@áÕ×µgó~.¡5§­iÛ?vW\C¡ý™ß“?eîå¹>R?ÔD SSWºÔ Ñpg.7Y³´ µªJ%eßñ£Óí6»µ‰L‹ø6eÐÝ&Ó…°{¼ê +ÔÚ*ФL=Ü[>Ã0z©Dí¬ »â<´:Du®OD±wÆz^èè+Nß¾:jE@½dÚ"éiÞî7ª®äÀtßDI¢ŒúR}yµàDQ¥Z±0¡ïàLuæídʰRhf²w§Þ¸\·A; þTˆN…NÊ%ãh©"ê[:ê#–¹y'•T©z©¤nú—6ÃÞDšºd^ì\ô>2]ìýðK/ì¾egį!âÌÝü ©+2FL££—´*ƒæìÌ@“æ­µ9Ãî}«0—/þ|žŸRXp4…us²#?p« .§„¿,èî<œõ’éò‘nßIV „lÓ ÇŒÕ#å ?Ì,®…y!kXÔPp7}¾D`h“á0°ÖWšô¢7j^ü¤7¤Ôßy\ ^Bôåyó}„Í*uƒ$ñSIUVÇœ5¡g ÉΠ¸•” 'Ârûßd_ç±#¯”`œÈ ½PUÈ C ¶’•»¹‹z­É4‡4X|BŽVòë™-SjåZmÙšzT› ³Š—½d·Òˆ_C±Éå¶s³Í/ƒT;Eb¾<š¨®ðF˜”pn(ù@y¤emvßþ¬ä™ÿPJ­³£h‡°áD þÂ\È^#æÖxkêVûôÛfšIéæ» i21,Lk¨}HÕµ¾7šc‡‘ÇFê )%Êìvr¾´EšêX%£4͸Ηi%©o€ÜR½Jgp™lÚÚOYñïû°»¸¯…yY¨d)µÐ@é4BCÛãUÂÝÑslbbœ8Nä†uàê€6Ÿå]qIé½ä‚M±FxÑ$[³˜@4™Î)sd—°?Ђ?¸>Ü|€V]†Q?k¿õƒÚ¸Gö±#}?\qãNŒšã}}ËByœ°ê‡µ«ÉïþhñŠªÚ(>‚ì±%LÅ”4‡úóO¤YÙ÷¸«z횬|ï²E\˜îÓÒd¼ ËíJi¸–rº 5…š´ÐŸÌ|§?yÛËs³—%Î Õg*à¦xHX$­y„°Ö\ìÜ 0ÙâôÐm>³»EÙ#m´„½7êí?~܇¦ÓõXXîíï _‡zÜ8¬Rš˜x:˜DDüÎneÛ¯ápÔÜôÅ c e;ë8Ìèåó»Ë m€Šeïì…™Æ#q>mrX –ŠñþYœØ Š…çÁ˜ß÷ yy¾·ŒæÌìC#ôkÎ6gMÀ÷AÙì·éÔYúÏÄYßEqöåBºq›Š­p%:v-Æ? ³›Q$½ÜI†@ª°êÍg´Áºüg6 í•ñƒ.².>=ÔÒõ‚ÅziPØÓŽà›v·ûlíƒéÅOÀHoq> -?…Øü{â»ü㼑óýû§gå}««ú¤B 3W–$Ñyë§è&>wÖK|E?z¸ZÛ_¿zþ"hû^ŸÂdŽÞB»à?»Ñ¦©RÕ>½ô’>óGÁóHÒûŠÏŠ«¸ÌÛ4~-Ë«!C¸¤@†È1>ßù¿Zê¶FZhð÷žøö9†{¤nÛ âM…Qœ–Ëwc?¡›lŸÑwÒ§L”¥kÉØ\pB¬¦HoùäÃ[×WÎ:”ø ¿û…:3Uíý÷oòÁKm}b=LˆsšKLe󺤬^Êô•I‰ZTùvs9ý_±‚u¤Û“Â,Ñ^€m|Ñ~Gu£:u•µ5V%Œm¥å/+Œ_O…ù?MÙ+­?àÅEìs0¦cËÕw.aª²8ÙiÊT[½ïîúRÕ&p;7mµÆ…O=Ï0…J ùØ­rµ7¸‰?'Z¤û8Q »"“t{J¤¿Wr’OïÉ$É£_‰…ÆK“æ™æ:K§ L‡ Z!íÏ20ƒçÖ”&)¦‹î½ù×ò³’ ¹vÇøÙÛþãO4/ŸŠÝ@ lûÏhyî(‚ß=¿j¼\µï þ̤}ÇèŽ$\ƒwEó*~Ò2–¸¤'pœïúPÊÍÓ|.ÿÞmHU5šs ðùŠ$¤´2ËDÝžŠZFfFÁˆs«DEßÒŽüù9½ôÉ¥C׉•&Þ `à†.ôN/Ç.žBÇWÖðH°NÚ»?ýz s nÂpŽŽìóŒ¶f†ÆÌ†'¾¨ᤠӷJÑdPé~{dò&hðˆÿa4«-G—襌LˆÉB:-o_\ú€|õ¯r¡J¯è¯VªÔ]Sb6ÎF2?e¤%œÜ'é1‘¼ã»ü!”öÄ'¼ÃÁ¼Ï8õ®jÈN”fHˆYû„ˆ±í]šR°Ê‰ãê‚L³â®5 sâö¾ÍΆóÒWý ¥ÍàçÕû´±Kº ¬`Œšå= Õ…£‡¤ÉgœGý¹¯ W,«Ñ(ÃÔHëL~­Oµ~¦x–Ô¦¨R»Ý5 »ùQõk÷M<Þ)èF ÇÿôH­þÆÐ³þUÜeà+‡µ©¹®anùZ“¥åÇÏUׄÞÏ™Ū~žÎsxó¾\R€šw ¡\™–ðÚ•"º Æ†áɶ*1À-5ùaB“ /û’µ¼jóJ¥\¸îŠá*?\þÊMŸ)Ûx Û ¼ôUჩ‹o°™üöœ&^-1ߢ Œ«W õï>{!ÆQ{êø1û>i A¯K‚“R¯3ò­®ã%Õ®½<Þ?N@–š†o§)ä&¹¶‘Þ$VˆŠÐìßVÞAÃEÐÓÏ0ú‡5Þ"ßDéQ‚‚/«þÆÝñÔ˜ˆÕ˜˜—†¥âÃÄ 1/J²ó]‰G?ZŠüÄ71Ÿ¼6Õz†vˆ»ZR²C^;pÅÌp9¸’ål—ÞŠ³ÂrûHá§e}!DG†«-ºªÓüù1G:?`f]Ü ¸ëoZ,2‚èÅYZHEÚuêœ5kÊne•þàv{…š¦%__Ôî7ÉÂc¢©èKˤË«8yHØ­/ÆHœm°Æ«ž—á"ô^,õùv?.nU¦ÐR{Ã,,öÚ.b* \CëîA)º‡¢íK«.ðŲ-°˜oÏ/‘‚-m]ÑŽòcUwŸŠô|'ˆÀ^1oÖR³Å™œ•Æ©¿¶â˜šÌ™”{àÚÚ˜h}±[†Ét!$y³¯Q¿õÔip`›m>R©'dßÈ}ų¹I‘÷Ü‚žÌ‹ä¥Tk2Þ19Šëóƒœ «`†Ë‚$•½’äí!ÉÂV¿"âÒ\^ zVœ(hÃÀÎi?z¯Xxq_$dž äáÔ¡èò–g »Ðö_ik¤´>$ê‚ntÎ2n&#Ä„;“Ä^cAÀ×ÒV?ƒM"¦ï´­—ó ±ºõP‘ã¯ò=\@TŽß8O"m¼ì -ÌLËÕYýDsŽzj|ôQƒ “*žá»sö¥jßzÇšû“C ç›’Ê߯TÎN…–U†´•žvãË;íµ¨”™U­›PìÕMQhL,Aêš £ ÃDcÎÆ[¦e°aS3ärò„7³“÷ó- á¢hñ”$~¦yÁ“7…JýÍ‚ófΕVT¥Zv98¨ÕQltjׂ½`Ãùùž’C ­RÀŽŒòì¿)Nü·àð7ƒ?»â>Öe´ê_Ÿ4( Û~›¶Éø””`ààÙ0³)Žœñf©aõ|ÈÙhZ1 žþ„|Ç–fÄC3¢ Ì7Núi¦¬j<·Ö´ uh¡·áÄ}¦-9K­A”òˆøeêÓä±ÏÍÞï^Wië¼[’ÙôÛø˜ïôÓœ-xû)a¯öm+›ƒ ±Ä f])´&æ7Šj]ª]÷&Ž´t3NuõŽƒ^%Úêºcâ&É/]]Ì/¨?×7Î3°ú…8Ùþ**|.ôIqÛÕ<ƒ­Î½æç$úÕdz‡hU\–UÓžCÀO’ç4)[¢éõèö/D\‚ aj¥¶ãÍ~gÎZÏt|„Ò_®wv„9Xç™óž ,즇è°Ó²$Q(gcñÖž¢g òÐÈ~˜c$:}BË|¹ÿEñ¾k61™&Ä®é,ÝH½±àÞ€Ï •ø6-Ï‘ç‹ÖíÝ÷Á ãw¦.!ºÆÚatYL@#¼Y*zäY_ëQCr°0d\ÚaîÃB²Øiì‘¿ÈÑÔË„Â9[©eÆÊV¼ð>*–þ@Ø(ÝÐ@ˆ£¢âÆyçøÔ8w+jnWÒçIî Rþ²&¿ã«(×åTåƒtj`0S&gù›ŸÝô)Øi9y¦øe¬ ¹Óe©S{ÒvÑ|ôè†*Š‹çuª¬çʉ’‹ˆ‘àݶ³øo8Š›‘é=FâçÉkãÚìEŽÑu¦Ò­’®¾¯w—‚Ó™M©|×}XQk"ðÑ¡;«ùWé^TkF¬T"üXÔE7eþ&G¶æ£,ë6¢«,Ahï³é¸Ã““e÷õ'ìŠnIVwËÇ]0+„M]:tp—®à¸lj*8ðÑ?¹§B¥tÃ)Y¯ú¢Ù}ïZ ÚcÜ”áÑ‘¾‘Rš¶‰`~›0¤"·•^è –ï-3~ï†P iƒÄä}išßàÞˈ9U=÷¾ã7÷±glgÙE]ÙBæÂ%z‚5FÂÁë`©› éscæfßfg…U•èÛÑ|·Á~;òPc(ñæ0ØßS&¿¨H~GÆ6¸¿-\"ñµquù;® *‚X3³ã|ñX7ö=h>Õ‚ÚŽ‰®1÷Ú10¹`H½Öçñ¨š¤)§,îôÞBöY°wò‡ÈZ9ÊuƒÆ}rå«@ŒŠöÖÏ0,u²¯?¶gªÚôÍ­¾ KØ(V10÷k80ß`ól, ´ ½úÆ×­cèì4îÐM;ühcz2­³=™‡¢YY ð®‚1ùžØoÎÎþ‰_™‹íñB–"0ñ§*ž"ÃEÕmψè‰^‘ÆU-S?6ÞáGÃàÒÞ©AwÃW†¦I¯:µŽîe<ÙtgçpÙµãI6R¸úÏ) %¾Z5_~3î…„àVÏò¿àŒ.ãÆ.;ž`T$o…%Yà…¶H¦XÕU韯0àM{/bïRЩ£ØG ö>ö”„6ÑË3 §È!Þ Ï!Ñ*J”4 MZLC²¬gI;h:_ $E)?ô¨XFg™°Xw!ä}` û˜Û~OòHÒàüaˆ ,m4W»¾v»Õoªm°@ÿãŸ[æk×Dø®s‘=¶ñ[Gý7×Xµ†mÇ(CYžv(k ?C™‹RˆfEFŸ×øÔÊãjžÍëÐÖ=Kš™m®–úa¼ÔZ*9Ýt\w?£¾øæBGP0ê³øíÂ~¨Þp\“‘×ØÉŸ“Œo\±¹Ï"W!!ùA÷xç„ãݦórŠÔëDÿ²ì©  +ÜØxð¼y莜ànÉ~®@‘ÌvÒMáë˜Ö&"µˆçÃXQ×4MaÚ¬’Ÿímˆ›‡¡Ø~d¤ÌK!ô‚ )Â:¯¸€(ŸK¹˜‚—«¡˜m0¯^s ÙÂ"F"Ä)uÐuÈe —@!¾i†,•¯Ñê~ÆQ¸È'/?•jÂP—Îa–ìÛ-¶Œ¡6•u“#ƒ7шÉÝÂd›„,ùšPöO)‰z¡BÊKf$JØ!bC±qh‡¬î B壮š·&ï,/äÄù°?3¶‹ž³\®A©ƒ•ü”'R?©ó)žòáñ'ˆ¼ÿ®¿Â+ž˜ºí;y‚¿t,pGx–ãíÐqq¯i5Cõdtw÷ƜИ1ù3‰¯³’e¾Uœ’çÚ²n‘]-RÛ¥F¿o(ƒ®«3œ:î0y¡öbó¤™wñûÕhò1OPó‡³j¹qdq.¹¯õj/ |7FííÝçŒÅ)%})aÝ„SÌú Í…'ýìs)ö„ø1› áòí4-Í"g8‘oÔÑlZ‰rÿâËš0{[@k—9Åå̆¥Zî)或vñý4—¢ Nã”^B¢Õ‘ÊÛÞz'µž`ÁÜE%FŒ¥þÎÇBÎF Š«î(b¶z,š;A>·•.ÛÚÃú•tÍg™[Û¶³ «1‹gŒªn8iÄ@Uv@dV¹[»—x\QˆÇ Ú+ÙÈ*Å42”™Ô°·¬Ùr¦\¤„QÈf=,j1:k• "¬nìyͯéR¢ì¡ÂQ ˜»C^bs˜¶Q­/‘Ÿ&†—¶}³¬¢÷æx?Pm†ñL^dï©UQÈ“ür.„†®\"Ç_§‹©¢ò­')2a÷òíJÍùß‘=äŸæë˜wí‰}=ŸCÑ…Ù4"ÖÃw „wç +÷²ç S/t½ñ²Q/2aùL'GT¯7ZüDzçEß/†Îjocbz§#nqC¦«@W¨zJyd&uwƒµNä€N0;Ùåh²FäA ßèù„v¥P@þEËG 4Õ w‚`U”7Ó{¹@ BeB'3m Aµx;£íW_]®‚C€™>ZŸDò¹âÑæ>ããÓŸ±¼G'qû¢·ÃG®gNL{ö¯ìîï÷xÚ–Ý£øß«´õŽ4ˆ“]1û+=ì ÅÁ^ü,J—{ºX—õZ݉¸€%ü!뀔ýÕ©#ñW¨€A<[z7¶‘Òäçž‘S6ÿ6c1ÚØ½ñ¡ç….£ÕuBëöº^Îkެ£äWÈoé9®´¿˜¼s\ÍÊ*ÄA¾½O°æ} ê‘ß\fõwSL±ÁOU/wä¥àmé%)óà–8¦-ЉóÓÊLž*‰¸è»£VÚcâUL ñèªA„¯8Kß G¿Ï-í²\·«Š6PÿÅ2üùS,+,Šiû­öÌL2OåK²óEJÙg†Ár@³É„'™¾[žÑ‡byçL“Ù½l¨~Úßx)½ìé´œºÔͱJ’‰(e—{ÓIó/£l³×&Dã[ ¤³»ÃjRãÈN¯Ûï­£7ü¿¶xÏ7µÎØ#JeYã¿c4SÝREáw«YHšaÝïaI’/}©1ýš &=QÖÍ’Ëruô"²ÔÇÔ'Vwk×I§#ÄÛ锦¼D¥»vàüÂô¬í)fJŽ¹Î§Ú õÔœ<™Ü7ªQB&·Ño¸™ÕÍÊ_vx€û´»¢ô¸$ÂÈÛE9.KeÑ£¸ ÚÉ–³U»±8ÇG~ÏõZÏW‘ÌÇP©I÷Ÿ¿ý2Ùx²À¸ªF7"û©!‹/ºÆrIÔ0‘‹x®Á´HŠWÿå•@¼þˆTƒˆ´û1ëóþD¿×þæ,;˜ÍC.Õ”b{†–d«¿˜-uÕrç  ú¹~ ±$ 4srGªO¢ h…*îMÓ†<̠雓ø:‹·^’[ÚAŠ!¥Û$õG7ª¾×àkÌp½y¦lÞoÁvãKÔ2ý Ï qõ„aEÙk8Dó0„1GHè4B—ý$¦Ì¤2¯õ&#På'ÓA.g[zÉ‹õ°Ó÷ˆHÄoŠ#ëÈ«Ûk‡ µÍ\ ŽD—ÐúôÒTÙ¸ÿ_Àÿ-ð?¢€µ3Øæu±„9ÿ³Ö;endstream endobj 52 0 obj << /Type /Font /Subtype /Type1 /Encoding 1176 0 R /FirstChar 45 /LastChar 122 /Widths 1177 0 R /BaseFont /KAYDWE+CMSLTT10 /FontDescriptor 50 0 R >> endobj 50 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /KAYDWE+CMSLTT10 /ItalicAngle -9.46 /StemV 69 /XHeight 431 /FontBBox [-20 -233 617 696] /Flags 4 /CharSet (/hyphen/period/slash/zero/one/two/three/four/five/eight/colon/A/C/D/L/M/O/R/V/underscore/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z) /FontFile 51 0 R >> endobj 1177 0 obj [525 525 525 525 525 525 525 525 525 0 0 525 0 525 0 0 0 0 0 0 525 0 525 525 0 0 0 0 0 0 0 525 525 0 525 0 0 525 0 0 0 525 0 0 0 0 0 0 0 0 525 0 525 525 525 525 525 525 525 525 525 0 525 525 525 525 525 525 0 525 525 525 525 525 525 525 525 525 ] endobj 1176 0 obj << /Type /Encoding /Differences [ 0 /.notdef 45/hyphen/period/slash/zero/one/two/three/four/five 54/.notdef 56/eight 57/.notdef 58/colon 59/.notdef 65/A 66/.notdef 67/C/D 69/.notdef 76/L/M 78/.notdef 79/O 80/.notdef 82/R 83/.notdef 86/V 87/.notdef 95/underscore 96/.notdef 97/a/b/c/d/e/f/g/h/i 106/.notdef 107/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x/y/z 123/.notdef] >> endobj 23 0 obj << /Length1 2191 /Length2 14036 /Length3 532 /Length 15228 /Filter /FlateDecode >> stream xÚí·UT\ݶp‹»»S¸»[p×à„´p((‚»…ÜÝ5@‚»»;Á]‚’¿¾}ÎÙdŸÿñÞ§ÛnQÕÇkŽ>u5è¨4´Ø$-@f@9£+;—0@ZU[›‹ÀÅÎÉ)…BG' šºÚ€eL]Â.!!n€¤ÀÍàâæå†|QèÒ '/°•µ+€QšéŸ$€¤lcnêP5uµ:@ú07µhÌm€®^ìI{{€æ?O¸4.@°;Ђ…‹ `acî 0ZÙ8¢püã¤èh üWØÂÍéšÜ`ˆ€ñ_šLˆ¤ÈÑÞ `´DáPAª!.ÿohýïÎåÜìíÕLþéþ_3õµ›:ØØ{ýwÈÁÉͨ‚,€`Çÿªü/9U …›ÃÿnUt5µ·1—t´²8ÿ+dã"g㠴аq5·¸‚Ý€ÿ -þ·dæþeÀ¡«§ªÿV‰å¿õ_¦6Ž®Ú^NÿîõŸì1×+C¦lã 0ä„Ì/$ò÷?¿ŒþW1YGs…£€›` ›z¡@¶„ø>\G  'è æ`w¹B@æÄ` £ü³¢<<H³½©Ã?ñÿ ñ8œÝ@®@ 3û× €ÃÑÍÁ쟕·r| ó8,@öö¦à׀à 6:º¾Æ„þ»ËÿÚÿæå„¤š‚Žö@Ë¿¢\ÿý_ÉÜS—ºp±{ BôìÝ\^ysƒƒékbníåd |µæåÿ—¢ Èâ5±v±7u±~8¼`Ðk2#ðß̱wõxmçƒx»Zƒe@”-An¯sÃѵ´qÿ+¢ëYé3DÖèþ—+dU9€ÿ1|UG›¿Eÿ³=诇„þéÆÁæ?£üa{ ËëdñCŒÎn¦¯ËÌ1¶úçξJóóü³x@—î¡× DTò• ’R¯”~%ˆÌ+AÌdÿM#¹W‚èÈ¿DEá• Н©®üJê*¯©®úJêj¯©®þo„T×x%H=ÍW‚ÔÓz%È2i¿¤ºÎ+Aªë¾¤ºÞ+Aªë¿¤ºÁ¿IRýÝ+AÆn65·ºþÇa€\øfðîM!žgÿç!âýç˜ÛؘۀÍÝ^Ï´DÙ r€]ÌAà×#Äÿßçò?kBÆðz~„ c0{%ÈÌÿM\œAXü…ÿl¨¿ðŸýÿB¬­þBˆ«õ_Q´ù !v!ÄÂþ/„h¼ŽŽ r¹r8þ… Ð_Ñpú !uÁá?Gî/„L‰ë_Ñpû !î!DÃã¹!ž!DÃë/„hxÿ…ÿ½†ÿ9÷\ܼÿ,ø_~Ü|ÿ÷ºÒÿ÷ëFJ äéÃÆ `ã†\Ô<\½Íéûiæn`È•êú¯W9ä•õ?liy¿ž@s”å¹HˆmÊ÷°2?Ù‚©rxfh)«ÆÏjõ]³í¨ÁKñÐöÅ#ÊÎÌëuú¿+Òq1öá÷)=žH]¢Ú>¾—;tþœ:ÿ²ïn²ŸîÝLª•®êµçD}|‚Ùú}îæ”Z}f}´,Ñ °?ëbà$OƒQFûq ªÛн¡;#„_@_.Ý^'<´Žž‡J+Õ¹,‚7ü‡V⸓Á~¶áHM,«— 67œßH¹ /ÆPæÑAÜRÙK“¶báélÄ‚?ÞËX=üˆ1"@ÕwrЙeTw§UGϵ8.·Þ­tNmiµ|íö‚š{ÚF6c'>TaDœrÑ;C¬Cׄ;–m¬TŲs­ Våä.‘½!LÏP?²¿+La(mÀöþC®<Lñ ë{(aòT‡MP£%`Tt³‡µò‡l•L·Ú)Æ»J}4_îÉ Û¤ô^pjxn:ã‘þ`O¦à©.œ:å÷uï^3æÐíòÑ=Rtù1Žñeý¢”²ó•<¶E ùaΠ•T[~„´5Ä&˜3ÍLuh“æ•íO[–(Ïž‡Qíl…ÜŽ]>£Ä¹ìˆ_DFyÁšÙ¬ŒíÎ(‚?@-î”Ò<Ûˆœx—ÅФã÷¼zÕžh¼F±s( ;ÊH¶1yE-,SævpOc¨?Ñ{æ,/êhe©G/Þ— Å18v-3û7{v{¯r(ù>jœNøÕ¡×ãFk€¾Ö½¹\8ñzüåÑE]•tŒÁ6FŠí‘”ç‡6é(;g¡ Q£ÔÔÙøfÔ0etÓeô–¹ÝMh;6Á3üWÁ½ ÓéƒtéZSûýq¶7ÆÇÔΘäúÃÈÁ”©?Œä¡íÄò$@žÅ?37ý€”÷Ž`JDð¬ã{vñm» á@å—¯l*Æ3Ò“/siƒ#DoôNÕq&w˜È¥ïàÝz9AÁì—AUSåx}K–é„]9æ´5yIhªkBÙ§({Ÿ©ð¿,ü$Ö2§~ÐsÉ <ùV<ÙØí›íDÇN †{ÿ2«v©Âx3w€dÿO¡'É-a¿æ‡ÎÐFXÆŠg°"ç×’CÖµjï|“Ø–®ÎÍÜ~"¹ãMVè;ÄOJAi܆[@ÅÍ VL' -Fs}}<åÑHÝ* ºIW”ÃRÈ_ !~*&A˜9ÈuOÛ¸h!ÚƒƒÑXº—Ëö©e –)¨³mŸ»‚q9E·õ†Pg]zåF!ßß¼jÁ²…É›‚­,û«(é©Ï÷ÎꘓnF5TNU<Ìe<¼­ß¶ÍBÀ5§"Ó™ÙIA¢ûGЊÉf1Œ*ê#¶ÙºF¶ µZä®ÄìUå…ÚRP¬tý5¯²ºJdôÇ×¾=Y—ÞuÚý õÑÎ(ß5A!.<Š_J]ìG˜\ªxƒ’óLÅÙô&B5%V.T¿“A p–ä!Àä5·d€„??ÐåœíÏb]%㌒—ô„&xÏô9Yò®¡3wËqó¡£]¨Ãõô¥LJW ¢Œ‹[ýØô†üP¬…%n(Mvmî›XøÕ„Œ>ÕæKýqØgŽÀÌ+M^œÄ9¨f³$òqwnUƒ˜ï‹Ÿ5ÖŒ$ýl fÊ £yÜSI>æ€Õ‡÷ŸæÖ‚ 2*˜åäÒÒ:56) «_D Z×ry矬‘~Cë>þt#WKŒT ÈÙ:VAMföw%›Y _iq~”ÛGTñ˜ò0(«:\Tøj²«óSgç—nbU‚¿S•‰€ÖÆý†™ÆòTz*ú‹2=§ø,‘áÑm;̬–INÜ}TØ0[ñFS¼p=¼­}ñ„á·¬ç27'ÏZ1gyxLªtþ6S¼E§àGs3ÃòèIýÔK¦Èáôï¢þ”e7Ž,šÛ«ìÉÑ6À§>ó¹ÁÀ8Q.“VÛÈd¢>NìY¡>;ÅÅXºïJB”l´;`ö•°H¬?V`ó&øU«ÜÛ*X”-ÿÂrN¸rZÓ_ H9oÏrp*e¸möù‰Æ†\µÿ®f™„ÕxE%KH…<È(:Ê„^çyƒ´–zÆYÏŽœ@­?Ù¶· -1ùäúF@_1±Eb¦Óo÷üëQ*>sö tª¿²ù„4AôiY‘Ε"¿þòôÝAã'‡¯¸Eíý2΢OÌY×póXH„ÅÅQÉHJvá(²Ÿ–‹¼t–ž\vïÃ8˜wD˜ô|°¶J*åN9L8Ò2¾QØ5âYsÕÔ¨íÒã½ðøjÜÔ“S‰7ÎBþqQ1¼2þ ß?q*äº2‹ï¸:í6Âm·Ë«•éÓM!ËO‘+xAö=E†£‚!!]]òà’¬àÍЩ»˜ô¾’VLâ´ÀÚr7úMž;L—³v˜Ÿ¦{rð604¡ºÝ]…Bþ2Éñg%BnüÇc¿ ߎHòM¤w=<ÉÒ)C™· ™|ž­eöñ–÷UZwDÉš€“³ƒÂm@–ŒëžtmÄöpÍö˜°cÄGqøÔÔÎ N„Â6¤Ž7·¨q/!ÙäÌðÜ\Qçd“ÕÒw¿D¾rÚ¦¸Ejë·¯iãâäS‡ët8Ã^2VCë²8!ÐèX˜ô|b÷•bAÎêÿÔ3ñÓ– }¿4[ë’Á+ç+ºÑ+ sá¶‚²ú‚èá.L¢½ØDCÿ›åqîyõÓ©Èt•ð`¡y*\Þ %)²É¿(%p´¼B1ÞT˜˜dòÏ^¶%¸¬ˆ0fKìkC©ž5yý‡S¶r4OQý3Žƒ gÿ6<`"ŸYô¾/BM6>ÆÉ´–ׯga•—ê–ü•±íxi!xÆ(wþ%fê¬BîÌ•†³Pé¥FAæZ3ÕèÀ¤Qí«mj é÷/_ê¬ ÑGAÉÜ’Y«õ¦Ä)K‰ú'…Ñ Î ýßš,9–7t–ÚE炚}¿ÛÙ«IMæWSܶþ 4â‘”¥{ ¬øCŽîvý$B¸—ÄìÎÌh`§:i“‚aš?—Cl6eòl9Åú~ruõ¤‡xÌ´„¶byaûé¥Zí qµ¼~A׿wó“÷P"7§´íA‰R7Q%˜ÐäûÍò1o++LLÓY]÷ìlÒs"K§ý óØ<ÌÎënO,½¥ñIížfwZ¾¾Áºßȩ̈ã?J– 8²›-{$™Ml›zékÆfÆT®c. Û5<œ#QKÎßJ1ðqv’¤/úT±Œ¿´éëlxá³ËŽqUÁrD1–t·ãno'&p#kåêr[¡ö«Â%Òº±ç§¿ÏÝD0uˆ8¼wÅí1¶öJZC^·ß‹½¬Òó\|§É蟫ÿ‚ýÞÑB8xþ\3ˆšêäh5ëñ­{ñ±`ñíGv’÷ÈÄ×OnãD.òú©=~ð›…•ø^{Èkûú¬æÞ:‡„gÁL‹ÁwØ2xx8ÄÜŠêÈÊf£Û‡SýTÂU{?{.ŸöHhì#Ë»'FóŽk±0ƒ)pñS§Õ¡ U2a\} Alç~•ÝVÐImyQRïö•ßž}çL¦~l!€~N3Öä~³PêÞª¿¦•†,Û½}›»³Oc Ï­<_~ã}îQX>šÄÅEúFß@.†Us£DƒxŽòñ´ô›ùDÞZµíãR@ÊÚsøs±ßÔ\hk)#XþxN€Í®Çj²ÄÝÃý ¡¼1r»NMºúØ¿í}Õ9§oì7z¾’Ä kç q‰f=ü𤲠?:ªo6s‚é|)~”9DÑõàqêªkŠMHŽ3ÌêEßÉ1Ý@ÄÝ€Bk7ºH§$rSžQEYÀ8å?̸ ²Ÿ,–enÌ>!fg_T7Wuò((µó{ò¥íZ63»6µ¼ÑßQð[c¥ä`¬p³0Nã? Ë,u׌ÌãçwÓöB=½@ñ–2-®žUÌìÕ Ò‰Ö£Ÿ¬. U+ÜïŠÜWZR“WyF‹oúeÿxŠÃŠh8GÆC¦.B$ÿs}|¼U‚¨…Šø>%FüË¢c–Zó#éón€ìJ³Áå3Ììx­‡ò}J®¤k"¢õmXqu¿Ø÷_u28 ge×Á”хѺ7|± Í0ñ¹<wEPþîÝ7= Gjgt´á§`C&^ûpÈY)pŠQ“.I2/jMhUPm))7òêÇE^e½¨·èÇOƨ¬¸ò~\¡Æ/@öØI_.øì¥¦UiUG¦Û‡Ï¬òÓ„pX¾Aúc‰EÊnjƒŒèbéÖêÄè#›–Je¦µ÷æóÚ‡¯É¢ˆñ'ÛŽÞó‚Ÿ@D¥¡v¸{J *I¹ÕÎÇ(Üïm¢«@d­—Leã—´÷—½U"0’·Z·½Å˜EÞöÇPgúfÉs9"îh?“<ÑæŽ?(ßlÍMX,bgü¾¨ãþ0„ï“eê-ý±0Múp6QQES+@]½‹¤Ü +q#b££ 1åZD|7Z×{;§³TBY…£œ çí~÷Cè Î\ ñÊ’3vy¬•Ó-J6<ÝsãÇx!'ó¢ü"¬½ª‚ÑŠ:%üa˜'ºh•¬(e·)Î&§åg•yIEUEªuÛ¶Ø&ÛÕº—C9æû½‘Ä>¾½P‘ÎQRƒ{•õûœçqEÃÆ§sÁ<©~kb”ÚïB?Åÿ8›Š]å#–ÕfmÇm(G²¨DF-[¶æ]…ê¼pt‹i™Çƒƒò¯O >IuÁ3“8´—GM Sœ«ñ’U~W•PŸ_4¦zÓÏŠsfþ1ó­á¦Ò«ßLB ŒVQs¿ ë%ÄCŸ‚oÏÃGìà )'6".ä•;’Ü$£ïÈ1ïÂÿ–{ÇKWÄMDò0ØÜ°0T-8¾­'ýÒDPéDCcàøvѧŠÛ‚Qaëx;lT£`¯¦Ã#¥ãI\LPs˜^Èþì MRßP£S¹´F<è(Iÿ5›5äíÓEšvŸ£#"•7 yú ·àA_¬ZÂyìdr=ža)ìtùÝ>o(ʽ¬äg hN¢ËèI‘\ñŠÓÅé÷¿%þl`Ç)QPÙ_È`£,…û t˜™êa Ö;³V­6ãÒG·hÒÖæÝ´Ôëá¾zÔ Ô¯ÁGå4æ:˸~µX¾ßP¡ì^ìû1ÈiB'j¿?Å×kqFŠì_Úý3~Z+EÓ¹s )?yùâx±9ÊèlxRdQö³:¬*ݬX«˜1çBăahO»yH“ijѰX.v|ôûQ~y*«"Žó®ÔaHw¬’ÚæøYåÉBã×·¬ãÕž!Â…”RVɧ¾n=I¸ôfš<ê™ä—'›…&$+EÔ3“èüG/Šò>ŒUØÉ˜øËª@¼àÁÙRI=.æÊ„§À÷ò.Þ•ï¥úw—ó‰ŒÂд4<{F~ÿîÀ¢VøEJmMÔù)È0TÍa ÿ8F@µ›µ?FázæÖCXHiq[GzÓL‡*i눂,êz®ãÇÛÞ* (ÏÜŶ-tƒ‡¶ÇiÚ‚"|¨Ûè"Î0¯f[_\²Òå ³C¢N$ÝûÝÏql¾¼‡ÅDˆ ¾kÞ«B¦â–yèX’Áèî÷åcbÈ=ã¡§a[?›Ÿ ЖnxO¸4‹’"Ýqâß—žÌ „/×sssþ¡¥›ã ûˆ.µª“rW½ÆuFYZI>î}OñF´ _àÓõŽ\G½st*¸Tk”“ó0ýãFÀém¦ýóåNÔ=ÅÙ/º7£PŒôâ=u’дŸÿð¼·q>ddÌ”i‹ZÛ¥÷ddXœvpd5áfä-»{k¸Êº Яà;ý!«üdi»4ª¹äýàd/xÐ)z hoQ¾º‡åu }ÀÏUäeñýn>ûØ]ëƒ7ì#;i?sZÆ]An8×Ï7ȧ’ª©yÁšâÁŒõ…åëwœÏ«*ºÍ©8ß®>ú¾»ào)Ð,5n½öÔ€}çÐ1*¡Í¾‰ &!‚ûQQ3A|H|ÛÈlÓݧþU H@ã<¢@§Õ¦Å—&IHôHu»²¦öça„K‚ì…¿”DX»“ä¥cÊ*ÊòÈž†Ó¹›ýÄE–ª ¬ÐB_ìoòÝ<8ªÀÞÏÇA Ùƒ\ÓÛ­ÇÏ%((SzóføLÔ¢Þú",V]W¥on™ã%ß”žpKVQÁs5ïqðEš@m9}ZÈþמG0›;ŠÑ¼C «nX²®*ª‰‹ ï)Úyy†¬2œ‡ÊùJT¦œ+MáÛ©U°Iáò©%Æ#d»‹Óñæj¸ºs¡pîçký®ËÇ&iD(ýÄ‘nySu©ÍÊß-ün[Çói¯¾(0ñçd e‚.ݦ^’߃ƒ áõì:·kœ KRݤkYš'èÍvt‰Y­ÛþÑI-ùÍgÆÓX<<’ðo>4<ƒ¿˜‚ b¿ø5:;³t§­j!u³Õª.呤;'‘*.IóyÅéŸBñKqS Иá¿èyP«#D…:é)‘Ýâê‡Ûm–9ÞÃÜÞá¯$Ë åØn#o `Á¦¤8ÈÓù v…¼àî8?ùãÁ0Îà ²3Ez 's°'àNŽÅËÇ:5W@8èªÀ{¸tRH£ØÆOÆàã$µ+˜4}&O=ηÕgd&4”|CÕëVM©þ´OcUO÷àJØš—*4yÚBŽõÖõ׳øv¿G7vŸ‰‰Ÿ7É?Kˆò—‡=n.éž1VÕžÇV>«I;¤qχÜhFÿ ,«Oq3!!Y-1tlßLíSýN’¿E{gpÚÉ”$ µWbÉ#?ö®m·}lŸÝûé7—áø¼âkleWàp€líSþVx)ÇE<ñUà x)Ó;d¤ÇDùœì^-º;zà»rú]VÍ“†ª¶#píÍdžA[ý^Ì;;Å-sˆÜþo?!›ö”mR|àÏÑN¸%cþy€C#ò¼ßDÅ…røì‰s p?¢Hƃ:pßö¤Aݬ=8sVwä{—j¸\§gÐ7•¤Žê/k¡_G ]ÿæ…Ç5?“ÞÔIÃ[ÕÁÒÔÐåzHx6ÐÊq=Ú;®j7_°lEx–‹Þ!UÑlQ¯nNha-ŸÙðÌœåjÖm_ÖnÞ:}¢=YÅ+úMëq¿nfó³æ"NŸšòBJ4ÚdÛƒTz "[3ý6¯„ý)¡YuØ´"5N¡L¶°›Ô ~é½™T½¢OÁäckiž»V_ˆÍ øXÕð[xzZÛ¯L<ß.£ 2öH4rÍ[¯†ô ¨‹gç’@ŽÙiz¹Á}íŒiÙûyYùê|7É6ÜßMñ?Jæo•î|¨ñžÀ#„ Šã È9qªX¹÷î>Škƒ]=’è/:Fº1oÍÐã" Ô®R»=2¥u{ò#ÈCfYûø²W@o`p/Þ9J²Ÿ¡Ù" øêntUh™îúDý–‘+þ|EMnjû·>¤èK¹ÈÙ}kNû‘4vÕVÞYíJîræ'ëJKÕÒ²ÇÔÜà³9ÍÛ!÷}É| V žkuíFºÈäyML.ºƒÜI±ŽDr„qUÖïÝØ¢K†v®'v°ZÈ6½zš}GWz/oÅ íÕSÈÝd¤°`ò¿s–Í£ŸÁv0WÆJ†_… ŸÍ9lOÞZË^¬~k).°ñ š,Þž®J¾Œ´„aœ««o'eç°™ªnÊ6bΔ÷‰uL›°r³ëˆ"®·ÀbjDþrˆÚ–Öœq+ÿ*üû“x„ìQàKÞöþVûhó ö1Úˆ½?°'é=ÙÉc ÕRµüŸ¤•^Ѳ±¬.¹O/()¹ÁfÜä*ÐT}:0.òUɨO+]ÚôöBƒ%ƒ<Ö¾‘M 9Èã§Š{Ûn) e>&V̵–(¤KÙ³î´$/ ”‘ªXZµè8]ÉAÛSN´K¥Õ‹Ð!Ç5‹Wjv0µÐ,½ «A¤Q„[¤¾á6xÀîBèŒ=T®?-+ê„ÈþCkYSÿby>&Í”ŒGˆÔÿ€ÿŽðÚ‰(Ê5ò˜hæ±lâíB‡´«_¦"ʪág@høOµbö€¥–‚ž’cË•#I y4ÞÑqJ$ÿã`z<Œýã§HR ^î'—V$X“ š©n$ŘÊÌ Xû"‚&Sɲ2°Û;Z° -éI>›¨F¢ôSlƒW‹]™"’™´k’C%\Ü]ñÔZ_‰lJž< bÊT®j¹ÈJýÛvÅKtB[¨™HÍsA¹Î¯•Ó5éîƒ|'¼­Ò^ð¡ò\ä–`í'gN£P†Ì„“ "èœ+£q«iOí´5Öý…Yj¯~G°`…߸–)]ÇK€=Ü»ßfƒè„ͦ§Ê]õ¢b6}äbh) ^³Ä©Üª¾)Áp5.ÑÅANÉP]üîR?«]£ö2‚ð¯9î. ‚®¼u øË+vXã‘ôŠr­àÆ%ÒŠš³ppoí:.í¡õýÌ[y%TtŒÇwfÜE«Š›Š¤Ö¸§yj²¢A-(­CÑŸa•9˜køò«Ar»M{¦Pó%k[­kÌèëSÌX€Ø4vʤZ ‘‡áõüÏéã”]!1…ß׸òAýŠå)èXªXYl3Y<Ê4~¶ Љ<7¯º!$÷"½½ ”^{ÕB Ùp{9±õÜ‚0 jã³²Çã ½Ü[~ÿ˜²À™î¤óáµ_è)AÈo 3F1\òÞÜdgëÀuàâ±`MŠßº±ÛýhiÕ<åYä#•}IñÆ÷iý0´§Ô>!äƵ<ŒÄV–»ÜÆ0Ær]–:M®¯GP\š$ŽãíkQ¦£Ã'yá@£ÜP&ÈàÂðò9ýV(/üωév£¥ÅÄdÞÌA©©¾ÇAç4ĺ~øŽ_Æuìfx\Ñsc€•¸cyKÝÈ¢¶©®PMÔSݯYh¤ýá‹aiÚtÆþr9û¨ê/Še”³ME `æ9ü´…oÜÛŠòk7'µÊ«ºŽ!K÷ø¢c§>IkB0Tù6ŸÐIÒðɦKÈWÔ$¹‚{Í(M–Ãû&|q²|ÏA¿àS>r¾î"À^ŠÒ®Þ±4ktán ©O-J:œ¥…ôHy–tdA);mÏSTTm0 –Ò{5ÖÞâ€Zòeꫯ¿S ÖÑÙ'OYì–ñÐÎrþ¤—™âÜØWe—N‰“ŸãÆÚ×µG H|IÌcñ—¡~ç‡t¬ius[£–4›x¦F¬c:õsmÐjÍ‰Š«gñ<^–04;®kµÎ;gcÇsŸTX†=‹¸+4Øfs¢]òÒV63ÖÐÁ0ë/nF¼=aÆ \ö~Gl¥rüµBÓž,NÖMMrÔý;(2¬Ëºˆ€w‰ÅËàCÅã9ûØ;qžèw‚´¢f¸P0‰/ËöX«tc¨ÐûG Õ²òÒ¿¨xtÝüUËì߀Yð,î¡0ÝëºÿòÐæÊÄ ßüöÏpi)~GÊmƇ-5úmsPŒ-K]‹Ô Â!žy`ž¯PN/e‹ ºU‹¤yX‹Ñãµ Á˜Ö¤_Y½ýðCƒ2nÞ# ›A({ÀÓ·oDL³õ°»÷l.²ÌEñ³xûgn¹´…¨Ö8°&ŸHÏ¿ï½Ùf >úõóRÄ,g1[!kåéÎJ©ü©àüø³üÃl]¨€_UÑ26Ýç_td=W© Vúƒ¦zx¨.¢’é%ˆéÅå#$´ÀF2á+Ô*¨  à÷›d>¿XäO5JT‘| gn> wµTmbxd°VPeeA—™ù× VÓL4ÜôF½Ñ>E˜iS°ŽL‡Wamž† :ÙË‚›ƒ—´ï½Ï”)FVø¹Ð%ß![XöY®9ì=÷C¯ Q‚?È͉øÑd5êâ4W˜Ñj±„·Êej˜…öß<| AÇr‘'¦û]™OQ  k;‰Ã{^B·4˜–‰Æ(á·ö”é«° Õ?z©ÇÕ_§t¹6¿²ü:Å£Ô(½ØË\®"Æâ¾W­˜ÐE]ìì(QM_—A±Ô€¡ð‰¶œ¡ÐkÎjô¦ù…­K À+‘Ñ:[jÒã¥S¢©»2*ë~©Zuy‹©ÿÓØJ—¸—S½‘I%þÏ¢¶w´ºÊÉ?HÞu CݪÃÉ"˜µ‚ÕP‡Nšnj°Ž‹ñÁ…´„:ù¶Án¤VšÒ‘nhkÐ…§êiV?çãš§,ÕÛI5;nÈööúÉ¿‘­]Ú¹Ž»g'µiR _ÆkÚèæ¨úx™}yËþ•üdNLÌ-è<2•6{á6Yq«“¬¸Yt@õ&ô«ý|?–M(’9S ¾ˆdl[Ù0»¥ŒÊ:<·i8ˆ“f\úà¥rqKMqÚ¤|ìjµ=$ÀóŒ$¦Äøu²”‘=nÑSÔ¦G–èÙ•²c2¸ÇÅFÔ€MëÇßrAQ£D›=Î8bl‘x+¨µ ŒtïóD]ß_«÷|¶PÞþÙp™r.ßp;/û¶¿…º™ô'm“>)ÙCÌH;ì¾æ­ ëq‹ 8§ûUWuÓfYšõ‡Jt$œFöÊ|.Tc¹æ9æÌ·êoDÝÒB 8…_þ?»ìYÆvy5'±Þ³ê·vÄQ¢/õa, *×C† e½·,3¼¿'Ì–ü`°TJ'ɹÁG:óýî_ôöâÄ}šVÏZPË7·×Ä>À*ÎR#Gä6_0}ÂwjëÁ9µKQ*cz}C?ÖºR¦ãé%„-Ê ÓÇÌN]àŽåã½PMÛMli}ztvØÅƒ³ß2“ž `¢¢Bíáe·äw<ÇtÕÈ/úœ8–p)u|ýD—ˆÖ×…6<|jžÍ“ª¨Å7pVÕëW9Ö_M»­L¹‹dEõr`n*Ç,q‘&"¨YÙÉÿí@FAE5f—êi¡Å††£cá£ÕκmMàvªÂjú±žîü;6é ç?bxYê—Ä@·=ù’ë§Ü_TÓ3¼¤=Ùt3X­·ã(#|xèÁ#‡Ô¼É°vBÍBíK'y4mòxNå[c6~Ö6œv£ÇœÞÏmK¥çí Ь43Re¢®†Ï̸+\M,+Š1r¼1º}ë”#4q“î8S~z¨­M}ÙúnD{?Ó$>¸—ù„WðYP#宆äàËõ®¹Êúouw÷°ÂMì{æ3ô[À–}Ü ›Œ(úìjf˜¹Žó K<Ü­»ß üïªÇCïÏÆŸë©N'ÝøZ?;ɃÑqyÏÞv*¶ô´#çUýtðÇM•Ш›û4š;K¢Î óq½Ý#5ЏKw’²Ö÷XC?UséÇ ¯°,%ÙµJp–ŒÒR¼ˆo ‡72L±éœz¼ÆÜÁÅÆ8 ¾Ö ­áH!P¤Õ9z}¶ÇÂ¥·ÿ ö<¼}Q§àn¹ *ΓaÇuº®>¢-<Θh¶L#Qù¶ºj3¶áÈ|€ÃýÁ;£Â«QÂn[ÚÄÜò8˜íî­•¦(ñ^•¥qflšÂ™«Oº–!‚Û)­Ë”©[£#2lgàÁ:¾³ª²üHúG<6B{&˜çl\:Œ:s©XŠ~ 9¬­[°©´y8ç}“Ñl¨1ôBZg~'íÙž¶|âïÏŸ†9~JµuÌj°6ˆ²;˜Š£èEöSÀ%íq“cÑ·+mª’Äh/¸\K;(í„GQâ&-ŒÆï—× 5päÂ2ˆñx!9,^ò²Ô×;¢ø\E…ê1÷q9¬xŒÀš—¥9¡å)Ô*pt¢¾)¿“`»8ø’ñMOðaØÐ¢Üqj³6öT\E˜ÅéúσI‰,¬KÑ,‘:G8Å»yN;Mûº‰Ðäö/ÎwYcÆÚÇ+®JÀ¨&ÀòzÏü:tJÿ/ê¨ "ôóµ1Â¥.Ùw_¤seS—G3Cõì#™ àŒÅRû”¿Þ ·…i^í!8µ-¬Ô¨öpžKÓ¾HåÚ­$iÒÖëÈýÔeܯ;D<>2êhÇs£ùÍp(|ÝXÌìï‹è÷zyêCZ.÷Ž–rÖ ÷{Ì~¦êžvðŸoócöÙQj~-PjH6"Í1廳‘oDå°Pãûõä±ùe)g”~!éîàmoÒ•P+ŒÖvIîþûŸ#}'!Æ5&ÿ";'$éÙÆ"2únL𒤍Gb\Ó:¡rZ|xÐMÒçNÚ³š0Þ1þÐnY´€gøÞ®ÛÛvœÈõÏMÌ[~:áVò'ï;v¼ßKƒ 5= Ùš™Œ­;Î’Ïø†‰Kwé)‡Û5äíÏžúŠVÐ9_J@°T+H±åw$žÞß–Õ¡x^»¢x$¿XDœ›_qŠä~§«0HŒ¼1XýÓ‚däøøÙƒPšŠ¶P?·ßÁÿg?üfÍѳÂÍîÛ·ôN°ñÁ!õžhu6˜ !ÏòÐäÒP–¶· õ•>ù¸‡ ª3_‹7:"Çø×o¡'®Û½ ^àµ+òa‹—,}2Sç—™ò Œ¬Ï®P¾êŠ÷dÍ ` £céVÊ’‰’.'ÃY†2ÔÀ»:ÀÂ}^ÖIüá¿XS»Y>sª—ž³Ü^âPÌ¥[éàÝF;+«%’`ó&¹ï`«ºC¸5~4¤ÍABÿÌmûj iÆbì9y“sâWÝ]êòßû1Ø#~·ª:å(çrž–„©ïÙ[ŸËÈ~òžÀ[ƒò’‡óCh jÓW÷5q»ñÞ%I‚€,bE$—Ð4DÍvÂÔAÇïl&‹EM)å0˜±µ„1lTaAN¤áÈOn‘Ïã×(Ä´tX³ïuwÌoÀ»”¬Íð1xT6D~ø(ðä•u¼l˜èú¡á©!Ä–aÕ¡8:èi1Ÿô€e®¢ãzšg-{Õ{–˜Ô“{~ùµöSF$k!E<£Êâ[·¹å `«‡Œh(† SÔý÷JC½}{šï„Ø·®ô§tVµ!y¤ì-)¹±·òF@‰ó©í"Aì>ÂbEÅ’GÁ Î8b*ázG1¤è_8ˆŠ,İs{rQ¢ûM¯:<^8£}þ¬$8§6Â{“A(6»75̉,¼Ü²S?]Êç‚pý€%]TZZ®7GgÖ굉Ÿl¹¦P±ëŒü5¢·ÒœŠ9îh“ •Ò=o~ |þöTMè5¡n *“œ×e,ÝŽÃ׆J)¤;;8_©5å&Þí1O¨æÑŸWÃËŠª¥WÆÝ¶+œ˜¿Úà LèÖ“aìxŠC[z Îóƽ-ÍMÜåÇÁÞZޥךûøbÚ>–y×…ÂÞr)Í-ØÄnÓòòs£TÇ6ÌÙ'ºæør€Ð4^›ßÜQŒ w:U÷[ÆÁwîJİýínü­q »£¯Ê½N4Òƒ%߸˜%™B‹A—é…úÇÈÁ$…Vœ{¡‘þZ4¨L)jÏÔ¹#€U5|&O÷¨MõÝ _ïÞuÔÙªÀ.tmdNi­ïû'¥µc„ÎZÕƒ‚Ñ¡…ÜolŠÐ²l¥Ö`) «z; K:ä?x>XNÒÎ÷v¯¼úŠáUe°.¦‹,xþ²âäÆTÔ†›Ï·¦…žgkÑ/Ø ÓÉ¿í4?nèÌp]Îñ-“e(Z¤tÙR÷àµ=©ël݃ú×ô{GÝî«=äãïxY@ÆS˜ïÖ¯hð‡R«Æúº†SP¾ ¯ –Zã(#êBµÅ¾ò¦ï22,ÆXdqšxÄGžÅ™ïÚ&?ß2®‹M/P–¥¯tÓ m§˜Og•<¦iXˆ~îF¯Uûá`Ñ—óyÎrOöHl¤oqt*½*ÊJÁ‰yü‹ŸǸ©Åô0%ª¯¨=!MÇGXQøñÊÄ:´ArlÃüÒö>ÅôÃÚÎGÞ~^dC)½tž}µûDÓýòƒt'N¨EПÒM››Ž;þ?é»Oºrj+œv×jï*œéÙ¤ù÷¡9C ÷z8~{) úÕ *fU¨9ró8ÝÛe¤¬|霞ÔcI®‰j3¥ß{HƒàwÎ?ë!ôLŽÍwS+ŒPA0ÿúææ³¦6õƒ* òsüSA(r’$B[#ܹð åÉ1WЪ´|T+¸ Âö!„\*åìPæÙ(qiD{‡©Iúfqã›^‚RU{q$¢Ë–Ø*]©Ò°ºdyΞUÄ%ßl”÷M’Kúb'TÎôÉg²“±Ž-]ž¹§…Mñ™u§•'¡l™Ù«¹@+sh`ºquu‰2öj¼Å•”€æ^ÖlFTqadÞm:¥¥¢rîwÇo¿¡˜„›õ°<ÓÕHUge§¸–¨`@Z@O‡1ÞOVåUú$)ÅLê=& #üF#KàÇ™|o³Z?ÿ1@¿ŒI]ÐÊ)qÊ_x>w¥&îT@®x(ß³Fë!*0ÜSi› [Õ[ä%13oÜ-áÓ*Á7Ar'*ä×F´ËÓÂð…·ˆ±ë1­Š|aP&* æþÛ -ü­öƒmRD‡IYéÁ/_Q*×£¶#yç‹Ã‘]Õµ'…}-«0›dÊ#Åâ0qômy•Ô£Aã¼ü/£ãˆ~™M†ó¹…MX›t%í¬ ßè`AØñçØV(ùaZ8ëÁü>ØnÕ½Sp·ÉdKÄË…ä WQ%k/‹rBwS Ú ÓâÈÖ„*s ßÃ6dpí­Íw(”¿Üz±á!}O5ºW!=äŒ8éu…Ë6~0ß Æ.¬ú¡áø~ ÄÉ"ÙQÒzápp/¾hö.0V·¥ e¢l ¥çÒ†š[+ÿ±”Dˆ[¸.CiPz«ú}òn ²òU-?n¦jGªÚþseßYðê]acáÎÞÝÅçß>ØGò$Ͳy Ð] åm=#žp/Ÿ’&;F-LlÃÛ/$¼Ô†|Þ2këëÖÞ\þÔì“wMmV -g;rMPÔ4Ú$ÄššØÝ,„ i£¼ä&ŽL1zØNgúy¯LŽîmÏ®ßJœzøH:”h‡ðò+[ꪲH%Šò7Š&M\ªˆoã]ó퇰1µ£i@oG\.`ŸÑ;»¼™s0²dz1s¡‡é2µó•ßźSÔK°9¶´É7ì`MfãºM׋ôRË‘z‡ >Åó;Å?Åž?rÀSåÊ ìñ›cl65ƒÏDjô¿_2ö*}ê'ˆf¶ë|àÈòãR™¿ƒÏ×Å©>]SY¤PŽjô¯?\šDÎj)¨VÎIâWÑÓ»ÍÙN{#s$|´LëÖÌ]d›TO®-½¦ÓúQŸÂu5@ÒŠ^ò´y÷{Jø\åNvM%³Ò^bñpuèþ4b®SÞSt­,ÆLvÆ4åëZÈzpÂ5ñåìñI14aåLVYŸ#”»zÌ û>²³p™YV 4`»·¿„¨•Ëcü@ ä†Ø»o/4øœÅT‹É ³Øñ1®©œÓ<øšKΠ’æ3ò#Ô±ú}hß Yü ňàrÅ@Òì2$ dM­”æË]£k<žuc†Â§^ Æ®]“Â8«Ô2$±IEN~ö£ÒͼÅëò¥–G>ó~,¯ ?»rØá¥U[vƒM9ªÃðê âp‹uØÜžÐT-N¿ÉÐÕ{˦ ¹(&j6‹cƒÊù4VE¡ìÙLìØ‚f¼'·_ŒE«é–½'—Âjq™™ókàÙš}µkì/ë*ƒ`½V„ó¡Ùø­ÚÔXeRêLnË€–ebÜ%kœ.9¶4Q43Ž{Øþu­³ïæ/y ;¿t`{ŸœõÏâüCÝ'Èü²ºã#ì PùOÆ–èsm~g›Z.UÜ›ú-º^I›Òî8û’Çzñr0†×²””s–-±f}úí0ÁÌ­ÚÚ/A-Šúnæ÷0—‰zLû\ÒmîÝf$R9òUé˜o>ïpÇÔ‰‰.I (úûìÇʓƑAWÍ#Åt¾Y}ÔĪÄ&©ŒÜ«®%ت\ѯȾ}ZbY“ru»ØoŸ~@÷”ø C<Û_YƒÎ"Ùm«ÁÔ~ÁŒ©°Ñ…<Ž\™qáSçë(ñwlk.舢͌M–Ü„ ›!+¾8ú¯s3À“ϘíN=úÍf5ÇÀBK¦Scð„Vk¡‹»<ÞoVa»j˜ö÷à$eðf7%ž&ÿä~=Œ TD©ß-öþN¦9´—^döZ]ƒúÌ>ãÇ™r˜X:– õÌeë%‰‚­:/o–\8ò1š¶…¤/-c«ÙÖÞC eÞCðPqÖ¨£»;>Î2ç78û¦ìqKZ\+(Z%’@Ý´0ßÅ¥cD׺dG´/"­w½‰~à;Æ5„îGN‡Š­f7¦5Ká|‚õ¥êš4Q‹ÒÎseÝ—áiÀˆ(k¶Æ±kãYé«“úÙÝ.f•Ъѽث¥‰:û´GÄq¸æË äe¨2ëÝ^Ðn}Cp»ÌªE)º•V´÷võ™X U y ÐñÖšý‘¦8Pú+‚ò£; ÚXÈIáÝ}8Eê±®ñ¶NÊÅêҸˮv8á¢4€V&D7yZ-Z=)¤,»ïWœ7°¿è\@é)–º0 Ísþ?ü üÿü¢s{ )Øä` ¶Cù? ó2Qendstream endobj 24 0 obj << /Type /Font /Subtype /Type1 /Encoding 1178 0 R /FirstChar 33 /LastChar 125 /Widths 1179 0 R /BaseFont /VWMXQJ+CMTT10 /FontDescriptor 22 0 R >> endobj 22 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /VWMXQJ+CMTT10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-4 -235 731 800] /Flags 4 /CharSet (/exclam/quotedbl/numbersign/dollar/percent/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright) /FontFile 23 0 R >> endobj 1179 0 obj [525 525 525 525 525 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 525 525 525 525 525 525 525 525 0 525 525 525 525 525 525 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 525 525 525 525 525 0 525 525 525 525 525 525 525 525 525 525 525 525 ] endobj 1178 0 obj << /Type /Encoding /Differences [ 0 /.notdef 33/exclam/quotedbl/numbersign/dollar/percent 38/.notdef 39/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question 64/.notdef 65/A/B/C/D/E/F/G/H/I 74/.notdef 75/K/L/M/N/O/P 81/.notdef 82/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i 106/.notdef 107/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright 126/.notdef] >> endobj 20 0 obj << /Length1 1309 /Length2 7984 /Length3 532 /Length 8789 /Filter /FlateDecode >> stream xÚí—UT\Û¶® ®A‚ pw‡à4¸{¡…www  îNÐà܇ÜZkŸ½’»Ïã½O§ª—úzïãïÿècÌjmÒP¨ª³ˆ[€Í€2`VA€¤’º";€ƒ••†F4u±;H™ºqW+'4Ï+ÈÍ.È -H‚= 6VÖ.zI†¿Šøâö@ˆ¹©@ÉÔÅhÕ07ÔÁæ6@V€8Pûk…3@ è „¸-XQ986æ.3 •*Û_Žä,Á¾…-\ÿrBœ¡¦ôP“ ¨E °È`´DeSC{¡Nþ˜úOqWHÙÔþ/ù¿§ôßò¦ö6 ÿªÛ;ºº!%°âðŸ¥ÚÀ™SZظÚÿgVÞÅdc.î`XX¹yÿ¶q–±qZ¨Ú¸˜[,MAÎÀ¿ã@‹ÿ4Þß6Øtt”õt4™þëTÿNªšÚ8¸hx8ì¿«ÿfŽß ÄÆ ÏÎÊÎÎ-„~ÿýËð?šI;˜ƒ-l ×‚‡` ˜z Bï”x^  ;èuÌÆêv.@ã°CPÿ:TnN›©3tR6Îveþä°™ƒííMGxlÖŽÖ@‡B¼Ðøoâ°Iþ&~›Ôo°IÿC|ì6™ßÄ`“ÿM¼6ÅßÕTúMPMåßÕTù‡ø¡šª¿ º'µßí þ› [Óø‡ ëô~´ßï- @û™ý&h?󈃺Ðâä°ÿ@¨Ë?êÀê„Z°þ¡s´ù¡&ìþ@¨ еaÿ¡—ŠÍá„ÚÿPŽ ´/ä„öuþ¡£wù¡6\ÿ@¨ ·ßÈ mäñ7þ÷›/!v÷báå°pò°ÿe‚ ÀÇÃîóš»B @—¿ÿZ ÏÏ¿ÙÒúÄî@sÔ¥y°¹P°mZSh™¯táT9ƒó댒౮† !Öãu!œ¯æI Ù%v¶­MVê©B%›…%Ï&Q“¸÷—:[È"ö.CA¦:Ò™ù±ì—¼Á^Lûœˆƒ%ò]Çf¦³eª› ·.„jÅ#¾D§‘ðe ó¿®|íüÆ7—ÐÒ-¨öRQ óÚS€Z‡ñ£÷'²àBðÒÇ/™7¯ž–ˆz×fìV12¢ò”àæ2„QØÜ-·ÆQ9²ìÈ—t’Z¿¢P¯"$Ñ,}ƒ“ºú™V– ê±²â9·Öû” ¼ü4Õ@üÈöš"«óšỖ^ù¦)Ím¯#’›Û›ÝýZu1f—ãŽÆdX£Î{[Ê!·¡üÆ ƒ­Ÿâg½K#}än1O+r¬]¡¸¢*>Oû’mBQ­;—o;&ýP7¢>˜¡À‰TE+_~^¿p½¨oo£ ¹kà´0Y=ç‡Uk2Q²ÿ¼|åä?¢S²T÷…ò¾ 4E*Y7â¨3Ôª~»Ô8D6Zn°Ž­[³—´R™:ÿåK[-Ÿò­Ú4:¦È–d8fV›±šEºíWv›l§¯›jC wº^_b\-­«ËnXÅ;gpŸlÐWÅ ¢õ´„¨0»ÛHìT;ã]´WžKêï¿¿ÜÈ„ýý‡·XH^Om uUy­ù}PZç³'ÝÓ†OOŸaÄÃk#IÃ|ÓLƒðê!¡ˆFnÞúêvCøžÁ¨èœÚJû™>™}à+¶øHUÇ+† v¾U¤Œ #ÔY'TE˜s”ý£<ÖÖϽýR¿RÔ¦VóÓË„.Ün°'¶„›ÏîO½e+'cdan<§RLR³núUøäùÍóeÝîä×]–85$@ gÛ]/‡ù‚›{ˆýΖhd·™Ýß}8@y˜kqW}+u§õQbe2ó0“ka½UÓ§&¶ƒÁ1ôéÕü€Sw×8 3˜ »$⎑Kx~m”¤—“î¸qMŒ½]nŸ'³¦ß:}¼›p×î9 æFùSc¯YED´D++2:ÖzâÂJF¦ƒŠ'[UDÂû‘öE©x»÷îFëé£F"gúLOÈþiª…Ûk ‹2ë/KDŽœ¶æÆ&90Sξõ-ÜÈÜ—N/tö÷ØÅp[Ââ¤ôΟ˜õsŽ{£´je>&ç|¢?ÆyÄGÑ—-4¯(Xá}/\ÓÌâ+!ømyæÑü`g0Õ•ID¬/o—ŒÛVùœ¥sÚqÏã»&Y™x1Ì 3l5™”,­¯‡æò ¯)ÊZ’ÁZý4À2c¾æ±5*î7ÚÿÒ!)j¡-ôÑþKg‹¦”Í#Ê.^}­”³á{Q’È3ÙÐ ‘®÷«½‘ Û³£\nD§÷«?^ÊE´í,(·eÝ®m§1VÄGij’s€ªÖR[JAeÛÄo!?¼ g]s °•šs"Þ]4²rÞÂx/`6ã{ ££LçÝïD_Æ@º‡–…½\®ê®øÏ ãív›’ =î˽ª?} &y{½Ò…;ÉÉØÕ‘”’GFà/Ç}“œI2ÿàÂóbèÓÍhwN8QMâNáŽÛªÞÇb]k¬·²~wñ ¯9õµŠ‚B^O`‹»¡áñnß"¾£ä}>‘f¬¢©C¸d ÎDlo.V~ÔR7}‰ô¥¶ÈŒ½|›PµÕõr*—S€êÔÎÕ·î˜Ï`“¢Ý”‰5‰rЉ·=ibCÖ=È¡Mv¯Û/o[°þBLö`ÂÍøi˜­) ¹‘ØçŒpw ‚èj¡Û$ªLE»‡Õ:äÄ©¢ ?Ø!«—WL+(Ãé g¡1ñ¢&r³ìÂòNÀþÌ_®¿üô·‹Ï¿xL†87/"ØIÆ*$ª²0n‘ôuÕ•Ï\Ó±†µV´»Éå‚ÛâyjßxúC®)f òúÄ3m!ãl²Ü/©l¡Öoøk)Í9ú#æv„p‚>™HéÔ>g²£?`-ƒ;éƒÄóo 6v(ˆlv)E Ëõ]ùªK©êw9gIÅÒ±QP™5­m…‚Õ72ìqª_šh›d†…ƒiÞ9Ãb¾þ:íTÒ›4M$´$•9@Z¬\…5ÆâiJê°hæË ™Ó©Ö|ÞXDŽÐ, ª›év1~wêÄk0Ñðe­=J› Í/…£€pÚöïÔÃF» ³Ö|l”†Êy#ç{ 5Ô“"Eì£\ë¢<Éû\ÆÏ³Vß, ÐGv÷8\Ý*aû߯c‰¹#Éf=Ò$ ýÏSZz¢¸œOæÜß ,Ç;b²6š¢w„xç*èzß2á¾®'Éu,Z—|÷:i˜J_ËÃ/Ÿ1¨Ûú‘Þcã.¬R>c,±¥bð?<Ï*j/ñÿ¼L„…1ÆÛ!ÅÛlØÇË’ðÄ#ʋȱZtypËÖþøÊ²äê«c¬ˆŠ7O‡Ya|šw·/6+2ÌÕÃNwÌ|ÞîƒöáZc†§HÅΤh#ߨ4\èN¤aâMuþhc¥»ª#Îy›ööuU¶7£˜D/¯‰b³›bÞ½ñ ý©k`!v{.ÖªOBDªSòÉÔ;Ñl¾…2½}ÖÌ'=Üd‘*åùðÇùÑ,Ø÷ÎÏi£Ö¦…¢%'éìPǾ<ïaàð‹ÀnÌÏâÏ ˜þMIˆls³ª«ÂŸ7E2ɺóy>Ÿ»xØ¥Œ¥2F)#{Hñkâ7r?D`\Ù¡ÇŸUöZeæ1hî~\ïý\}ç’y\¾Ó¶è+{²Ú2s6ß\A“ˆ…-hÐñ¬i“ê&€¤"ôa’`>uÎâA¾Ä±¥fS¤œëë„£ýz]ñ 5N!Œïþäwöa‹ãJ¿Áú+®ýµ‹&}Š ­ÀM™ª¯Ël{Ã(çÊÊqaSع«ÌƒIùsu’•N¼ñG¨v+‡Ñá6‹³¾? ˜på×ßd¹Šá⮥h²û¯º¡ I†k,ò²*ѰëDüh¬"{õc,rAë{nÖ‡ôÄæîš¶MºcÛˆxåbË4´¹Æ"¢<’‡‡KDcnµ]ø0FûI4V¯{ÒôVc­G\RK›N’äËHX§weÏí¹\ÁC~Qö^d]1é_Ç¿å”ä;]ˆ—Õª½õ6cŠÜéB%*,/)–|íΛƒÈmig?öêõƢ̢ܒqð/Éß«ào›ÿõƒ Gi®Û"ºR´–šH:ºÌ†?+2³€~4(i/5„æP8Ù`£×ø WjIoWD@Ì?¤Èù·öÌnö27rënðw]ä®= ¾kžGDÃX>'¯% výI=º˜&©LºU„ES'ȯ‚6hkÌÂÆ˜VQ'¯«&Dœˆ2ƒ¡8¯mÕr ´´=cgå|ª4PÝ©Õã¼kûø¾íV€§Žº¯–§"uîÊnø³,BŒ×Hd&g ‹üXmD®Öº0€4J¿1RKˆvýŒVC&η@-±‰J®v©sçóé++;E“óí".¦¬Ë®ý¤qbÙ_QùØÃ?`ƒNÑ`¬JîDCލû±áeéRöتky©“X—GÆ€…¤\OY_+ÍÔ5“+ÔGg6kîÚ¿¸Û–Äö@|©Úø9U;ãµU>í>ŠZ3%(åsi^%×7ÏrMiû7„çvš/ä7s۪櫚tÇ]ä.w^)ßVŸÜ¶² Íó Ã*ùQ£s ïâÛ ðŒz+ü¦„av2„¦«šÎ˜Ða@¨èò´*¨(’‘RÄ wƒ|Ú´=‹XÊBÑNuc5•!_–äïù¾ý&ìPb`Yûõ…´\–J¹¼%Duïéqت<È ßÓÖÃõF?“f_€¡üÛ¯'ž†áVþZü‰³Ü8Œ7¬*¯ï‹èÍD»Û >&ú¯¤Øˆ¶ú¯»¸\„b“>† ÈÎ`à5ð‘¦ñ‹A*NâºRÞ…V>{Cˆ–ÅÍW•¬h¯F²Ô”ÓPŽqhó‘ž)ýŸ¶¸c²dÖ_ǺZ,íåM1IÛ“rÚmªÆ^i7”Øè=Eª{7M46´'Î.vÇ‹qxž_p'‘«zÎ:$5‹š‹VhÆ@_ÊOeëK’Hq ÀwÎ ö¾¦ÐE0eMƶÂqïE­u{B_¤Ü§–’ËŒ,¥–ôÉ)ºPo›.‡·‘ïï®8IjCÛb ó ­¹ *ižö+‚=e×-ØÃ+òD>ÏÛNkј®ÐP[Íx"ƒž•ãÒÄ;‡ÅȰdú Ï€xZo:«Y2G=åJÅásJ̳‡Z¬«"ºS„g+¹."wh’9"æÎÓ/⤢¥ÉH© °Œöh[œÈ­Â¥ mEˆ*°â½ï)NÁ °j¡;,©å t=Âè}¢ùà€v²O6¸½  äÂÝšÔ$wDpÏžå‰ý£D\ö õÔv~¬mek\øýŠ ;Ç…Íýà‚mQú Ÿß½XhKÕDŸDÖ¤´§Œ7ôf¡Ç@ƒã„´“¾®Ü ¶UÓXí~s”þ¤iŸI7‘åi—ýÆþiÈéÛ…àŠÇGÒì@²!?ñ¤Dh&]}tU×ðÔ䇧K:þéÛ.ABÑbîŠÓ‚±•/¼ZÔPÚ -~ðå[Aûîê̼øü^€“€‚À H©Óë•â8v–<>ê’lÐÇvÜÌ)6,ÇŸæ? °ŽkA“©œDšuM;üC9öL€®ÞÝïn¤NÕcÆ´¯¯½a¹F¼}üì½_p¿|¸¬’—5ç:4DÐÇr¯bõ¹3¿ù,:Óg3íjPÜ4ÑRP/Ç2»õ?ÍøôF»Jm‚`ÍQ¤—9:K“aæGêÆ„0¯ºQ ÃÐS;eð‚gË0Ñ3b×Í1˜.… þ' uÙ¾vâ6\½€OÏéAndkÆHF¼(–9<,9nmkÒB/ @ëà}Âkôz;ÞÑWIʸ•þ ['ùÃþ/uùǯ_YÕ.3qáøv2EwɧÁŽŒX.ʼn¼Á˜2t ‚ýðuKhÄýÒÌì¥0c‹Loœ"ŸU!ÖÜ/‰'ÉÑlÝï…R sßL½Aûj–^ôh€Ò XÜ£Â]BÉœŽ&OTA„v˜ ZƒâÄ/jyž»Ì€v4~ìrÆÖëè‘™Oò)bakêã–’C–+ZHXou¯}›OÝ:üû ⼤¥> éˆ~<¯m0ƒ(ûÝÓ\¢wÕØ+8éTöÔ:’½¬­nÔýÕ|)I¯ öÒJL\œÏó0l«Ñ"9Fm—ð6jŸk/½4¹x²çqç«Ì ?ÉX?ßz¬%]d*­þ(ÌBÚ䣟?ž‰µáðÍš´ÆÏäÏåü¯t{;ý©è‘ÎI§»fá`8¥y^iˆEf >çY4Åò13UÈe†¬­ª=õë>‡[ïå‰É³Ò£ÉYÄ€Ž*”ZŸvÐ#Ê ò_Eh¹¿ª¼ó†Í.›•Qy@¨×0£ã'!W_Õ¦¹]Ù‚(`‚ñöÄrz½Û¸åÚ C1w:?uÆ^6y1 -=z {3»¦…”_Þ«ú¤•×Ó·,µÃ]Àj`4ENî¤@"ùpI»¸ey íaM›ò¦& >¨,c`_¨ŠðæÓ½%Ó¡8rP…Zè6>Š ¾¾ëÂ’ŽJ- 3×mªgšù Ï„½hPì9ñ5› i§ÝôyƒwÃÁë” ïT²w;h&Q鹦Õó—§„çêäØÂߑ忏œ#a°‚üH•[G胪³RQ–š¨œW½Å“^JÇðæY©_¨¨·Ì*%fD¶ßՔޙjKúIîpSD‡&†uT]èœé˜à_,ÄP„©·ÓžKçÅek já%¾»r>£ï+\;SÓªÜ7¼²‰—½,E3¸§WðêiVµËx(Cþ'vÂ8Ÿ(ÙÌT®gëšÝ£t~Ü["?*·~Ù.Éš'þžMQ6IqfýºTiü¬ö0f>¹ÎÿAÕ›F:?RÐ9G‚ËDÕÿ\y¤ný¡¹…šŸëŸ»…- òòË}»•èšÔ_€ïOt lr›gTYÕ ÃgB>Z •´¬¯…p’5ÏnØñ©R ›·Ôho»q²9ﺴ.eÃ%Ø *c4‹UOo|":9³ûhU•=Ã`%oŒÖd™æ<˜¸î£/ß¿-ŠÜs!Ï%ìzù·i<‚bõá$c>†dkx=xýÊöØa»ò“giN‘Ö‰©!•åqmEÏV^Å1î Z±×ú1GáBe2³Úe™¾QIZ·;lÛq¨+„µ+`!º@ o¼w üxtD#Ÿ Å×˪u×Ó»IåÙͺ†h5ƒÇ~½‹5w«Öº5O÷'Φ•^žÜ®“ÎÊ6ÛdQRÚ˹“šgRÎJ¨¹OøºÎ 7ò¤™ 2&‡gG—"å•an5dbT¬ál!ŽøÕ9"hq²áô[N®{ËC`g‘¾@OÝi6ÛO“÷Áª©ëh-–X}ù´ýôeç"NH~ʘõ$ùÝd§_PQÇ`ê)Š''W[ÖÇ,È3Z;³Šd_¯óßvµÕ¬"meÇ7s4¦›Ð÷aÈ@‘¬„/êNy….¨œ*:(5ÐWïz # Ù>@Þã!oâyyЦïÍI¥Ü¾ÌÄc]³°œá_jhÛ¶ßÀÊ·„[ùIðcFºh^º½5 édd_§ŠäñDRüé‡`ya懭œ—VpÚËðu–)”ZÞ¶¢djU‹`Ú‹¦½]F›º°%¡Ù jQ¼s‚ HlLN ÂN1Þ¢Nþ[“Ÿ+bѶŸ˜ä÷h2b¶1éeŒ(L"ǘÜì /¤™Õ›nfðäQÊ…ÓªKaÇÐ~ø× …3=K³(¬2{KŸ“–j«º ‡Ã`(^û÷”A?OÍ'Óß§º|C$ƒ×ÏZJÛ@ ª;ô)HõKÏâs¸™’N5Ç.…Y$~£=çìU|˜ã7~5³¯ž7›jQ¸D›Ý€ =.Ö LØâôªÅ]ÿºÓÒk£¾°õaºkŸOͯº‘ÑçÛÒ8u/…ƒv'tZYoBÕ¼¯T'Ô;öq—(wýÇ­^[Ðh¦)*~Ï´†°L’¸y¾*Û6 o“)è@ùHå¿qŸZ‰]BaS éØ;cÀ[KǬ“5¬9$»cŸ?ó}&u覮´ 8•e¼Àì¯ò22¬ns½ì y|¶:V£’ ›æ .ÔL}!§HðÉ€[ÉA‘IQ¾d{Sv÷;lø3iƒ!ôÀüá5jЏ”pldvØAÌlbšQƒ~Š‹ÿ]ùÛýAš¨'“ r»NÜ`œwû£¬þû¨æþÛ¨*†Ñ"gÁ²:œ]Òï–äÓ£ÒI‡£‚[ä IÂl‘yL-o÷Dä?Ѩúâw¦ÌNðáÎ>ÐÁ!m¨§=Ëo–áNœý<.˜¯,©;‹ÑƱžßgÒØRëAÌ3(n¥K{Ѱµ.Ú¥%µNržë“âñ‘°~ˆhP¾¦”„)Ûqo\©£ù„µ:ž…‰øôüí!¬‘Ë[1i{=)f¸±V­_Ÿš±g@1lürï&2;YÚÕ]ûÖªèuîg³¾Ê†¦E²8MŤ¯i4µÚE:¸Îë­½ˆÕŸwº‹m$‰c˜à{­BI~7\¼Y„⌣)5c.c¸U‚w÷Y_r ±ûÀ4îf»jS$¥oÖ5yy m 1å¾³ˆÀóGÏÜè_œúþ56x=½›Ü¶£vÖ%ïF`dxqÛhë4ð²‰)^ž<5Òsy-µ ž½5üЉ)~Ib”ºÓ¿ÝózÉyçÀpšüQÑÞyý/ŸÙ+ù† ÝÁ„BB)´sÍ$<³ôâsÆ»ñßp—#—ïñU®ßy1¬›àæÝç'"áøøÎ(¹à{"¹YæLL¯÷kXj0˜LRƉ‚ÖŠµúʧΒOb®êu5qƒþVz×f’MÑ £P¼~ë1šF;b¤ ßñù¹-~ÂÕT€”B¡_ãÑh¨ " KÛhäýÚzƪ»÷W8TÕ˜J¸z`·ˆ]ñáLã:£%Ä›c´©k-6'®÷ …¢ WMyÜ…ÂÕ?tŒÙ!—Þ¶zWÕº…¼YbPR½&¿8§;}ãAa{}"†8MwÅrbC_«pÿôÔR)¸5;-ò40Ç´ô*B2Ž£‰zÖô)UÚÁ—rùb|ŽYJ|6îÓýïÞÏÉ/ŽD¬6<®«Ò®…ø²­Î~©[k);¯k‹ìpÇ5§HVšÌ¦&–¨~Ž'±E§R=é‹› ßTàT`âÍå–¯åÖ÷ò‡¾—Ø "™Ë‰¼O]L¿nм%ÐL]Ên7›µ…è˜Q¦¹.„ &ÇÙÎÞÙ¦¡_þÐÉÜOÈlH®B ¢Ï˜Å?¬ ûy,>¤ZYý¨‚¾zß›ëþˆ¸›HÛ\E ¨zÝ ó‹_­ŽS¯ †€fH/úæõŠ2«¥hÀ§zç Iµ&ö‘ãMĹ1¦ðLš½¼_€eQf;‚jFËlćÊ×L9³{lz¯¬s5D×èä-X cÕ¾—ûã \]¬Á1ù,°‡_í %oÔò§ˆ¤°Î´¯ç².2ïèj&Šù}eÌ¥Øÿ?¨ÿ+ð?BÀ4…¸€íM!v¨ÿqÕ}•endstream endobj 21 0 obj << /Type /Font /Subtype /Type1 /Encoding 1180 0 R /FirstChar 42 /LastChar 121 /Widths 1181 0 R /BaseFont /XXNZXU+CMSL10 /FontDescriptor 19 0 R >> endobj 19 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /XXNZXU+CMSL10 /ItalicAngle -9.46 /StemV 79 /XHeight 431 /FontBBox [-62 -250 1123 750] /Flags 4 /CharSet (/asterisk/comma/hyphen/A/C/D/E/F/I/L/M/N/O/P/R/S/T/Z/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/y) /FontFile 20 0 R >> endobj 1181 0 obj [500 0 278 333 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 750 0 722 764 681 653 0 0 361 0 0 625 917 750 778 681 0 736 556 722 0 0 0 0 0 611 0 0 0 0 0 0 500 556 444 556 444 306 500 556 278 0 528 278 833 556 500 556 0 392 394 389 556 528 0 0 528 ] endobj 1180 0 obj << /Type /Encoding /Differences [ 0 /.notdef 42/asterisk 43/.notdef 44/comma/hyphen 46/.notdef 65/A 66/.notdef 67/C/D/E/F 71/.notdef 73/I 74/.notdef 76/L/M/N/O/P 81/.notdef 82/R/S/T 85/.notdef 90/Z 91/.notdef 97/a/b/c/d/e/f/g/h/i 106/.notdef 107/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v 119/.notdef 121/y 122/.notdef] >> endobj 8 0 obj << /Length1 1658 /Length2 10499 /Length3 532 /Length 11433 /Filter /FlateDecode >> stream xÚí·UTL·° îîÒ¸iÜÝÝ ®Ý¸6Ü%Xp—à$¸ ×àî\‚`ú}Ï>2ç\Î\Íšî›~víªzvÙZMG¥®Å*r¶Ë:;¹³r°q¤T$õ88l@::)ØÜÝÖÙIÚÜ,ààHxX8^A.nAn:€”³‹ÄÖÚÆÀ(ÅôO@ ±µ4w¨˜»Û€¡cXš;´œ-mÁî>l €æ?=Üš`70Ä bCáà€l-Ý`k['öŒœ¬œ|ÿy¸üw“'â•0B%™PE³“ƒ¶BaWu†Î†šü¿!õ?—õppP5wügøWéµ›;Ú:øüŸ gGw0 â Cœþgê[ðÉI:;ü¯iÜÍl-%œ¬Àà…lÝdm½Á u[wK€•¹ƒøß8Ø ô? Ëö¯»’¤Œ”–Á›ÿ³Ÿÿ6ª›Û:¹kû¸ügزÿeކ®ÄÖ`d9 ‰Ðïÿ2þ“É8Y:ƒl ‚‡`˜û @O”x¾['Øö†³³99»C» Kâ°r† ü³P-v+Ûbÿ"€Ý ±;¹ÿ'ÆÍ`·ñq±;½„xÿM³u½„øìïÀç—€€ÝÙ üæØÝ½^Úy8 lÿ•ñ‹³ä%Àõœç_Üv7èÂü‡¡jn`Ͽ̠‹Àþ_ÛúŸ´$'Û¿Dx¡$^ÚAò… ÉR/­Iú… Éü‡ø åȾ´¹‚"ÿBÐ*^Z‚â A]”^ê¢üBP•‚º¨¾ÔEí?ÄuQ!¨‹Æ A]4_ê¢õBP킺è¼ÔE÷… .o_:»þH:»Á A3Í_jmñBÐ~–ÿ! ´#è/„zƒÿÂNÃ_5·þ ¡ê6!ÔÝö/„JØÿ…P ‡¿ªáø‚P §¿ªáüB5\þB輿ðŸøBÍý/„jxü…P Ï¿ªáõ‚ÐÝû/„jøü‹ÿûq‘”tööe…ÞVNè-âàà€$ ÿÿ-ÑÒÞâßmèõßle }ÐÀ`o°%ÊÒ¼³¥P˜]zsDE€LÑd%<3¬¤uK¢jC÷L'jèâX‡Ò%Wæõz½‡OY¸ûðû”^HÝb:ü4Æeσ]3æžö=Íö³Þµ‘ê]e©øì¹Pß…c¶7Ï^ŸðÀªM¯V¤è÷ç^ ª3Jk ®RÁôz6öd‡ñòéÉf9èD†×ÓsQibe¸VDqG®ya¥$Á­} °‹Dj}³réÜáóP„Tüdú4®kv§t–惾cð8v‡Sd\³ãQ ’©_õÇÂp•2‡ÃÐá*6{–á'‹»Qfu—Ërõl^±Á½1w¥\´"ºmÌ—Îb*˜ºÄúÀï-k;lÌ To)ÆŠæÉl”äž›¢Þ n6Î`Äù È@£á ':ƨaÌf¢}VäR _J˜—y¬j ̤pK¬Ãøa'[ReÕE­N;·Áª°Þ´x2šº$ÚÂ+bSœè*­‹u!¼c†,ƒcßÝP)“Œ¥ }¢bå~!/(_ùòß6ÿü¬/ÃKz¿IY£Ãp³3æƒ ³V¥gr}ÍIj¤cL«÷6&ú€•ê¨A¼áSÃwI4Çû·‘"Ê+te<îÅëlj¬Æªñ¨RÚß¹IHWDé½zR˜bΦcžê»«çViIø]^£C©ã‘M÷ eQá¾\~àô*™uû1ºÓ2‹S’_¾ìÞ¶”Åö}’ [.ÂCz,éÞFyL¶bY<+ø§­á&$蛄±•íàRLu{7†s;'ÙDÿÑS6ÖY­Õ¾éL_™Æ­™sÊø—8eÝ;qÙ«KÛ$b'塲;s]-œ«‘$ѽB±¥Ê± ™6°º¡(æèjDˆËí„I>þJM{?cþüc€ÿ'÷‹)xß}FOØüÔi’> 3™ï.uó¬ú-ÕIMa’ñ¬-®qßÅ©÷jM´@Šè,äKÿmß [ 1-¯–´˜:‘·Â(<úô]£%&~›´ÎüR‰’ˆ•ñ§jFÉãþ h @Hº‡{·ï!ßÇ튛Ìh m›!¸âNòø¡Û§'8š2æWo¼¸k€Z2KÏ3‰÷-G ÉŒô9ÝK5¶ÃFƒFB©l¾6Ûkúë)’ ÝÉFýGͲ(³ ü~Ë¥fese9Ü­Ù£´¿ö¦ðch䩊n_Ç5H}Ö ¨’) ’œƒèþ§[¾eo±`Á8Æ„ÖÂRºÛNÛdZ‘Ë“óæãŒÀÅìküpÁN©Ü¾5–ƒ}“a¿ #¼Ø}R†A¤É‘iúÚï|ìµÅ8üÀ˜öÞ'ˆ“âú^öp0K];ªò–6Y#_¯O`îïäï²x¹Œô>Žë3ËÁë"Ь“©¢ÍMë»ÄX¯ÞQgÚ´âuGøžï´¿mØõä¼#™0Qzw>[æ=~Ùªò“Âÿ´”oeY¶ O\("œ¨ÐWƒ8mQSø5pˆ×¦š+Ñ pî²[ =4&ÚòTˆÂÐy4‚}ŸAô M­Œ!§mÝ*®é §7ú^Ì€s{œc159WÐ&–}ÓK‰ùém‰ûp?{fCd ±SèHÊ‚qK#§×æ’rk^C=©‘•i³PÙÝá>I…½÷öDT¯}1v'$ÒJtqÕ­6»ü½ý!ý à(aÚ¼wGÔG–Vòd­¢–ޤ'šC¿ŒÞÃ×*U- %o-ÉÏã°eôû+öso„‡ZE%¾ |¥zØf¾ouÌs*a\Ì =uf‰3s“õVC…?t+ÙÑ‹yŸíÅôÜ]>á|Ìø93¨þfs¾ÒH‰50ã[r»܃H¯ÁSn‡NJ‡:œ,XX°h[¹ÍìY^¶syPw ‹ìŠá®kNµ­À”Ö «ÜͧQYÀ\YÖ>FÇ€$û#€ërøOãÊDýÇ–>?Ö ) ¡ãÔ_Öu?LaåºÒ'ÂcþìUŠ#ýÆ+÷Ë­(!vž^-µ²¹¸CÌüÔ§ƒ5äÒs&Ö´"DeŒ³ÆÉý€ò*®e<ü÷-HvÐ¾Ž—ndå>SA A§›ïõJÓgK«{Z±;¢¨öýìçç§‹5rHVÞéÓÝœ…F=7?Vã™ H ˆ›üÎnM‰I±¤=mŽ»_JÊuÎd3)/TçEo×í1SQ 9üÅÔ5¡^¡¯Ž¦3½ 2÷”߀s”‹|óNEõ(úõbe pé¦+¢æ ë:¸ùÊV¦ãÜ$.L®˜l’%äÑÏŸÖšÑ^ZÈêböÍ ×¥,o†­í¸7×ÏÄo·CÑU`U°'ãC?!S’VùK‘ŠöÐîÑéÿöKÍÀÓc ³ö‰ÄT@6õÖ/¦~€žé]Â.¢+¬ÑxtJ>¨ AþÄQø…¼|}HÖ¥^˜œ~°?2FÔZÌ‹™ÂÿÓ‰ÂÅ­s@’KV¢¥Ô7{µÝbZo­Û0rÞÀV¯Ä‡_‚‹„:ºöµO¿†ªÕóÆ .mòJ•þ$P¬¨ÛÛ®ìÑîCDk~”FZÀZL¹¡RÔwº©;ÉHåi„”st… s(âWrv%u– Á¾»_C¶ƒD]EÕÐ'Þ_rV¥ äÈh¯‘3óAœËÔ -p¢1•´Q•‡ˆ6`3NÆ]ll!̰äÈ">«÷W^怬ºÏ \f¼`[<¯E ™°íAÍ*͉K¨Ú¦[´-?ªlÚyiņ¿mîÁ£¸ß”–U;Ò&^LB%ÌÌhÏ»ÎCÜ{æEù“@ÕÌ;×ì~¨]íüåÑ],J<$E&4ï)ÊÛq²¡®VåXä§þMù´wVÓÇÎv†_tŒ=…>Å*æ›ß˜Ú'Î.t”Æšb÷c$újôxá Â\ ˆ#ôUþÈW¼¥õ'Øú†3µ¯ëAy7kùÆŽO2úún«zÁqõ|¨Æ8R(þ…n)–È+»S 'ÑXëã‚ÝëÁ•¥g\ÌH¼qˆ¢Ÿ¦¶j‰ŸWd˜O›FlþEš`°"ºvªY¥îví}Ù°\vOÃ!{M8raBj]˜ê™BQ¥„šÛ~Ÿ@ Ù×Ã’z‘Œ  DÊðïèèYÅ0yøÇ⌠{H'ñQZãj=6º‰¦Moéw5‘ðŠÂ0•ùéÇ©œ?…y†õ3l°_6[˜Î-œBŒ£»Þ9Z6wJ MY¿ÑFcˆM.ck‰û²0Í2ç{rÏÖ¦\¾cç$scyŠ;;û-j»élj¢A ƒð1³QÞÐ1ãõöÛÖKö‘úÈ8´å±€Q÷… T¥œ2D°+`>e;£ºç¤~_°&/ŸòÄæ®S‘@(ö,+ÓJØŸã€;jèA™^ß´fˆ"ÞÊ{• Ç'k€à’5ßêiÿ{×#(M»ž«XÞPw@Ï.#…{æ¸wE½‚°ð^BN´¡$û‘ù) Ðе´:ÄðžÁê ö±8Ù+tBº)L]u¦>XùöX•V(·Ï}ÖVéýãŸ)š’"LÌ=é”-ÚS>Ǭ̃1?«:ªö-?_ϳh6ÿ!m.ecÊÄ®Ø(8¤4>Mâ߀J|„AkJÙP›yØ+¾&ÿ ÞNg6æ—ã½6fGólM€“™YÉõb0œØ`˜€5©æŽ(͉gVu?«û÷ã²=2?º ñ8Ø"Yí¾ÊÜ}óa¥ÞqGÄ~`ÈBf蜽°»çbÔc_ƒB0Pªå¼Q,›„† Øè3C-d û9-/XÄ6ÛÃH\ ‰å 9\-#.Í¢–gï§üåC„GÙÞüÌ9á ª2uo=›H¡H*I‹öÝ0Ýí9 b¨5M]`Ù ‰ç$éÞpFe›g_VûDm¼>q3³&ÐèlôÝØQȼõpö:Q¬c!Ù3Íô{¶ÁÛznJ—ôcÏ}±ƒjÏ‚ †Y—==6¼¹Å&eÑÒ.£ìRÛ£MŠA"›«ëh5Ö·”¯4Eò“‰8—õ¤X,Ƴìriør–×bë?ÎuG}~-ͺkeövçj¨  Í;éùÖº ‰7Ù%Ê·¸}=Ïx†õ“‡ù'pOà†”Å!NÉÅÂ['ѹ¦›<¨Åz‘M¯aFóc³HI®Í C™4e^ï óêt:…I¢èT(?Q`. N\=S2>È}Ü*Û3£Ù:÷Õí)Qò>R/B|ihOlÚã½CùœT?êCûj“ŽHb¸–¸~‚d{¢™uäðd)kœ³’w¯©À"ô¢®>ƒÙÀt.·•"kœ¡®í»GLû vÇëþ½†—IC¸1"´ m”PëÍQBlÝø9~AÆŠª7…ÙÑqA¹FÌ·«y~mJ†dÆŠ}õ]6)JÎŒxFi›p´:'qr÷d›Kå´ïXÒIx^ÈfÌLž¥”¿V¼¶×ð¨óæƒã$ª!·=Äâ¨Ý4#`ø·˜›==jlj•ŸÆm‡¨˜È4!öMæ“°ŒmÂÅ,ŸÒ¸Ò.ÿ‘d’zܺÀ6K5y`¯ ¨A×#ñ‰ÊÐc*µW×ÐBK%ifŠ<Ä3¿íÍþu :%_D³¥è&X™rP«@ß1>*®Œ&#¬_É:$tE`ƒ¼hJl1ü½À*†«^è;SÂ3ÿÔ•éæ$ÖÇÖž äolêÑid^ñdˆ‡?3Üe/Uáwš[¬yxt®¯¬0M2¬ry½l|é6.2å¶èî‚7d9¯ð¿>‘c’/웘^­côy¸{|µýŒ_˜<+Ûd¬Üª²®'LÓT›±÷qÄ0ÞôÄÙl~ÌB…$N‡îÉ=“ŽNºå6Fº;L`º6¼)ä­SÊzÚ™vôÞ²÷’+"¸SüÓü2âãEçóa¯¡ýP¬Tƒ€ýÑBÚ‡è.7Q~Š‹µ-2˜ÕŒT¦È·ãÅKkk´'y{ñúTFö²x±š­¯Ê|ÉWŒ aÃSUƒœ8ÚZÃàpŽ©·†´_•£äij?ï}¨õ½sÒrûDÿèoV³p»m¯ ¿¾­o3„K„3ë _R£XU·=Ü@rèÉ&‡5ú5.¾aÓ‘›.e ç´c4!6*罯N|±OLø8ãÃHÛ´üvþ[×g“âN5æW4ˆsÔL²]ÍdÓqmïÿ˜‰mUïì4D01éì"uÑUSŠçÙš5ú±€ °ðÂs0—[ϸfÖ ÈÕ ÒÿŒî!e2ótµC”z„›cX¯#5Ñ_µÄ½}~3¸ÇÁfhô¦õ‰¦ª¸ö­†ýùDÿu o(Q÷ˆÝ"ÚŸŒFv–ÃmBMƒQæ=)Æ­MxY¤Íî∠„+çÒ§}{O*ÉÏ .rÆ©–Æ®Y³ƒAEf]“0R:DïMO¬Óîå§èq8MÊkûËÌn44”6*k¹Ða]_lãáöŸÄïÄÑBíÒÅLÖ(cFÑÖ¸þ¨Ô[áÙTŽ«×ÓÁ´ÒÎAßà „ƒù¶ =—î Ä*nÜ?¤…»H{ ¿R¦im³j†ùZ|xb§Pp§ò¬£ãK+ó?l\z‡¾¿Fi¸¬”ž¥Z¢¾s- Ê<ýuüË#†Â$௾H#º•@äþ„ î,ÈÅ´û\û¦ÁXö‡L$k>‹ŸÐ ªÙ¼%MFIn]?Á¸æ7M8û5cfIÄMÜÕŒŒŒµÃ«•EÍ3l¿µö{Éol¹¢+•[D·¿ÌºÝÛX"çÁÀ&1©–d ˆpxbü›x„kóMó õÝ+‚øðW{ŸÅ£x°`Ÿ}ôÐo«v±À ¦Ty85'ã³±ÂÃ8éï\ä”G?9‚‰uoWWWlxß#<:lz$ÅX~îÊNÍ‘–Œ¹b†\u%Ãç%‰ÿŠùðg»Íæ£0뾑l×È-é§lߡӅƒT½9MuËœ¤ªòp#nf w€®ÍQJñ·Ÿµ8´ÏG%÷Ü»ä춪‡«_Œœµ¶"B„-ì¥RètQsd¯}Í& {´Q¿»¦q¾a”Önݽ© Ê;DY¢þäøeW †”iWñëU{k{>™p. üìã¹ÕÎM–2yi¹Í» ’Xã¤îàŽ”z~뺒7rÚ[쀆«oác|7_>rÙÅo¤V²72]Ü)©GЗþ’JáFoæÔÛ‚Pû,§ßÁVãIÈUÂyP›‡Eø{¦3ïMh”4îÊ™î\¤Õd+ã¿RŒ©{G°Ry¸ç¾¯Ó6dALSŸò*^Ÿpû:lOŠßÊúî$·ï¡uvæo!yGQï­ ”`"ÌI")QºCææ*‹ú&ì9]¤~Þ"ÜKþ딢 ¨a£L w=>¾ WÂñ|0ºH ûƒ›x"¸A¬§yr†™D±‚é§$Ö¾˜y®GåwŽÁÍä1÷Ì)þeîd£µýÆVÒÅóóÂú"…5èÚñÉ€B’Íö±ÜÖ£$tç™ ÍÕ4UAbåÍQ¤•¶îyy¤¾Áí ´YkÑÌl×KÅ?Sp|~%ˆ±|‘lõe?ê°A»¥ˆB”ÒIÁfavÍï]e¬ÑNåG6SÕ¸Ñìê'.ÖÄÇ:nCŠÄë½ÄöÇvÜÚv¦zóŸ˜P޾Òâÿ¾áQÊLs£ùr”YoÌüžàH‰‰ -ÀømûM)ö÷íŠLr™…êøÅù6Â.¶±a‹ºßÞpªÄk•áþŠÊ¹.…»`³©øÁšTÊ“&Ý´Ëb†,“)„äè­ÄÖN!)ŸiEJ¶Ú³Fµ <7Ù¤Y…™IERÌæ‚áF#k² Ôæ[fÅÕeAžZA‚ ÷ZF ¿šq÷|ir>Wݧô=@}£G¿»ŠÀ9*ºø<‚|ç3ÖE³¶T¸wpf~Q¤ƒ¢¼Þ×AmÔqo§ {Û®ÏáÚ}µÙ^ù4}àŒB+âuËGGö˜'˜ñ°xëÂbšáΤÙ/FœÂõª“nC•Ÿ¶ƒ=¤ñJ1®4…ìà”¥Xù½t®|ö«d­YÅ:”a¨è®ëßEÁ¾5àŸ“ä7РƒC¥-#mO5àÐ]ºœü¸ R­ñ ŠA„8¸pŒ¤åøìo6NHOÙšmB¬/mú¨hóvû®ð&á÷òÊàÉ™ëCJÑ¢Ã+îj*®Ëî6¹å‹WÚAlÇp"¶z¨ÞΛÙÁì#|}†”º.N,=Qö-ÖEÒ Yñãe’Ø™,Kì»©Ý Q q!ÃÆ™$ئCKx¯¾úŸ³(û»ÎkF8ê¶!ŒöQ„ÐŦØÂµ®“zͤå5p¯4[¯ I»Ä7%¢ú-YG‚Æ(NU«…g>Ý.ôþÌ"fÌ$]Ó òßÿx2ßÈTqá¤u»mÃïKDä9ÓÉ%ÅÚtfÕ¶á°e­WfCjÞÁßß.]´Rœª.¼¯·32V½¼kXR­å7«PH¼¥^/H™˜ñ•g‚ØiéfÓï׊)ã,VøUjµhT_€)—s* ry@õú•’è0ò„¼ÔI‹- WFýÛVµQ—¾ ¡_iN‘rqÄû”æ>õá¨ÞH›Ñp#% Ý"e¤«CPád$¸Ð©Ôo.» ½Ê‰(ÜS;¯m"©e¥A‡`rWºd¼Uˆ?Úm"D‘q¶ MÀ×9¥¾ØÈŽÅÚ鋯Nn`®–ç<=&éð3±¿Ã:)ý©“èyÉ‹ÐõŠŸêIô;4ëá Xžû•*†1;ÒÆuvÓÑt«$¤ NÛ½9Z×!öÁú溵”gÞ—ÿ¡*=éòÂFm‚05­$¡ÞˆÍuªRDBkf³ËêëÛœ„°£Ìd²øÚ%k.Çß{íÁ`bk‚ëŠêµrÌu~ÿ´¹ú¦å†,#lÒ¹n—æ²½‚úåVŸˆö¼Âr`²Õz¹‡™¶KšÌ^Áòä;é]'Ãx¬J'ÒÈnwFĈ\2ë8óW—W£ëm<¬ˆã8¦Ÿ¬¤Ù“S’ÛðN£d\ x¥<Šð¶™®ˆÖûɦˆqR%÷¶œ„Ápâ¦òìo49Ø^'l°›)šù¡ïUiÊržßÁãJ©K¥%|¤vÕ[± Yà9eèÖŸ[ÕDÇ,ü î´ûI½M¦U©d¾ÍeÛÒzYD“%„'n5p×çž'ˆ¯Q_£FÈR16Còžæˆbdá6$õ›¨=–Ì8ͽ—á?óÂM„¼³Í(}åÃ^l* `_°ö\šÈJó-ЇAÆõ÷—Kåu÷hÚë¬ ¬è¸2XÊ›Ïì;\±;ZÎå8~AñÊO©Hñóé%bf¹ZÒýXz(âõŒaŠDX=":¦& úeWOLíPÃ%­?®éV?„?iïÄÅ~v{äâÎ_Æ» [´t)Ö<çÖß®ï|&‘´ MØ$ÓÈJ°æ€kHþ›r’{ÔCÒ„I•«GK¦PÈR_*¸\1|ÉIxñ™¿c‹1…–øƒþ‡ù”ÀÀ]ü\0¹o–59!ñ@OXèJÙmkù¹Š„PúaüÑ|03²É©Ü÷ݤÑ¡«£ã¢¹”ÀÓÁ¤À`_I¹¿Êo¬(Œ²žY>Õ…bÜšŽ¤®Ç‚ÜŽÇþdrM¯;ºŒ|ÔêK¡¼K6LµþÑ]nÈ+› €Ò“ŠF² ŸBí~cjø.çQy%Å‘a¡BØ÷ÚÊôî—×FÌ(5¤›ƒPzI0£?½YÏë ÷RUðîõU! V· ˆ/!g|]Qkuíè@`$Þ´j´jÿß2ï1Õû0fü›±"šÎ×Þ^<ô‘|VÔxv#ÄÓ_¶Sð“"t̸Xn*!bhªélÞŠô ßQkË÷:'ç  ¤¯ÛšØøMf5‰cý®ãû0çÅ––^Ùò­´&Š¹Æ¹ý1ô¯¡‚­-øç›á@=ÖJ?ŽÐávÖf=Œ³öüp*þ¸òiáPß÷kùŒ &«¼F%ìkD͉ê+#…œ¯®¡ŠãMhYÎGÀüßùùÏv³¯5Ï$fN GJ;Ž·9:?”ŠFZzF2‰Ÿú´Q =«d¸¤_«0+îz*·ñÁŽž½V$ 2+ľ¡ÈõÖ”ª¬Ã«žª®Ì:_ÚIcSÉ/.èv‰Una¸ÇýL’­bZ¢Õ9ÑŸ,€ÂeUI)Ô’"\qs•õ5š&³œAdØêÕðÈ„çÀxC¤" âk ~ë"Za¥ãP€ÛÖ®¼k1§ï•÷ZO®"gOŸ4q—ShLÅÌ}aW(ÎØ74_æhÝáФêÚä`7‹»?®QÂG*‹ÉxŠ¹ßŠ°Õ´O›j×Í-ïÅ'ÀîùŽ1ËðÒ'7Z)‡ý¶óÓ(jG¤zfºQKH¯Á« ÁY€Bt»™1)¶~™Û” ‡ m¤è°O÷ºZ$ŽüMèçÜLž¬ˆ÷ů.ZÜ2]ÁŸÕ$ö¢äœ£±*X õ›·µ¥õ,ÔŸ0§­]Öa…ô~GžÑˆù©Äª,ç¤vZ?'ºåðˆ@)ø»mÀÕs9(,£±Sš¸#[«£äÉ¿9†ç—a£+‘Ê|)ª¥ìAùºÎˆ9™ÖïT|†u('nN#8÷‘|XœËRw5< ø^x"?1m>Íé9¶ò”æ„÷ï~Õ-ݬòîê'dèŸK:¡¹´ª¦Ýìv™òþp#žWÁoÞnMÔ˜Ýr•T"@j˜é9Ú8²ö€W2]Dñ¶œ:z²lG‰…ÙÔÀYfš†Q‡q˜w~PÛ'rÅU£>¥Ÿ|íÐHm§ÀŽééÈ! ÃL†™fÄ¡õ‹V¤ã­fïÇëéqà W0ºÒ]ÙßåÁT ¯C¿$éOå*ÙL0Xø;óÌK<¦ÊñeW]~Õia‰·‘Ú¥õxvi™ÄÛ ¡DÙÈ56Wû ]½Oüp…lk¶ÃOÓφ6Z/؃d.Öª?xoưµ¢W»Ájª´bk'?âyÚ’š¶ôÇXöçîŠ Y¤/Û£!°†K–ï0ê_>ôp»æÂBýê0µ`¨Ú)ä"Ø®kûp“9ÐtÑäR5|¨³ÇE8â‹ð1÷.^ZDÆœ“íu¶ γ!㯯=hMÆDǘ)Reçë.'ø@Niÿ”­„?C²o…¼`dÒ‰À-$mA¹©‡a"jµŽ!ΓÅUƒÁUæ¶’™?œqÛÜ'Ä| Ñ'!ljéb ÙÒÃÀK?áñì±ùS„½Ì‘2Õ&j‹Ì?»3¼Õ¯®æ+WêSì˜0̈¦Ûmï!R9¥ðm¶Ì'ýõR|6,ØEì1µ‘bKJ¯öÏCöóO¬{I¶Ž ºåZßùèeº”CºObm3òÐÔúݳ'íb:ˆ”Èt´eÉ;w{ú_›*ì|Èh¥Çú~8‚*õû­CÔã©×JŽ*¬¸+Àz–ó„„žš ÉàWaªýs["’%tø˜-Aäðɇ€:zh`»±èƒ  wÔo¿‚¶;ŠiÂä} }® Q$ùå)ÕÜ÷Þº~ÒÊ¡´щŸßÙEO Æü6L$®ëVeÎþRëyLü;±í`–âZ¾’ýÓIË©|}µSùh:fMÓÚïË‹WãÂÆ›¢œ2¬Vt+‘#%[~ròÁ/!’ ãó¬u<$pê¾F½³40Ø6¬«˜P£RÑGÜivî„0¥·u²tXÅqOœˆÍëYò¤+¾Ú`±´S¡77xs¶ù§óTFßYÖ)›¾íˆ¾’ãÐâ¦ÚtñœW™ðN‘T «`=¿=ЋM–-–L1„uM É›¨À»xHf.ʰ*D’ïæ~d?/e{à÷Ø[àÿÃÊÿ?Àÿ'°t›CÜÍ!ö(ÿ¯Ž0endstream endobj 9 0 obj << /Type /Font /Subtype /Type1 /Encoding 1182 0 R /FirstChar 12 /LastChar 121 /Widths 1183 0 R /BaseFont /KBECSZ+CMBX12 /FontDescriptor 7 0 R >> endobj 7 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /KBECSZ+CMBX12 /ItalicAngle 0 /StemV 109 /XHeight 444 /FontBBox [-53 -251 1139 750] /Flags 4 /CharSet (/fi/percent/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/Y/Z/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x/y) /FontFile 8 0 R >> endobj 1183 0 obj [625 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 938 0 0 0 0 0 0 0 375 313 0 562 562 562 562 562 562 562 562 562 562 0 0 0 0 0 0 0 850 800 813 862 738 707 884 880 419 581 881 676 1067 880 845 769 845 839 625 782 865 850 1162 0 850 687 0 0 0 0 0 0 547 625 500 625 513 344 562 625 313 0 594 313 938 625 562 625 0 459 444 438 625 594 813 594 594 ] endobj 1182 0 obj << /Type /Encoding /Differences [ 0 /.notdef 12/fi 13/.notdef 37/percent 38/.notdef 45/hyphen/period 47/.notdef 48/zero/one/two/three/four/five/six/seven/eight/nine 58/.notdef 65/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W 88/.notdef 89/Y/Z 91/.notdef 97/a/b/c/d/e/f/g/h/i 106/.notdef 107/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x/y 122/.notdef] >> endobj 5 0 obj << /Length1 2031 /Length2 14953 /Length3 532 /Length 16060 /Filter /FlateDecode >> stream xÚí·eTœÝ²¶‹kp·Ð¸»www§q‡à.Áƒw‡`Áƒ»[pww þñ®½÷JÖþ~žó댌}Õ¬9ï»kÖS=  QRe6³7J؃\XYx¢ò*,ÌFff Q' ±‹•=HÌØÈ`áæfHMÞß¼ÿñp°óp°"PDí<œ¬,,]Ô¢4ÿ$q„í€NV¦Æ €¼±‹%Ðîý Sc[€ª½©ÐŃ lk Pùg‡3@è trš1"°°Ì¬L]&@ +Ó?–¤Aæö®ÿ ›¹:üÏ’ÐÉùÝ€ú_6iï&ÍìA¶3 9“‚ý»ðÝËÿ¶þ÷á®¶¶ ÆvÿÿO¡þ¯ec;+[ÿN°·spu:äíÍ€N ÿª ü/oò@3+W»ÿ½*íblke* ²°˜ÿ+då,aõh¦dåbj 07¶uþ+™ýoï•û—& y eºÿºÓ­)[\Ô<þ}ê?Éÿb–?ü^'«Ï]æ÷ò²¼'¾ÿþÏ;ýÿ¥%2µ7³YX98ÆNNÆïÝóN/€È øüün˜‰dïò¾ð^€¹½Â?ú~çLæÿŠý²¾£Õd{GÛ?ÈþOòŸe¶wvtµwš™Øþ×Eÿ{…Àrµ3ù§O,@ÂÜÿ½á?³Ù™LÆN@-Ðü¯(ËGÿWò»¨©½ñŸÈ»˜¥‡ƒ%ð;çûÞw{³?!.“³­±³åŸÈ'“'ÐÉþOàÝž=øoæx÷åâþgãÝ‘‹¥ð¯Œêeïêô'ðOŬÜþÊx·ëü~—ÿæw³Î@·¿¼¾ßð?>"Ç»UÕßF>ýó™míÿlâ|·tt5þs9œlÿÔèüÏ´ø|WþCïJ"è]Eô½Kˆý¡÷Jˆÿ›¸Þë ñ‡Þ¥%ÿÐ{¤þл é?ô®.û‡ÞÕåþлºüzWWøCïêŠÿ¦OïêJè]Oå½ë©þ¡÷Z«ý¡wuõ?ô®®ñ‡ÞÕ5ÿлºÖzW×þ7q¿Z'cS Ëtçû þwïÿçÛ¿7ügãrsþ÷ŽÿLwò§•¹ß˜ü¡w'¦ž>æ÷B˜ý…ÿ´À_øO+þ…ï6,þÂ÷ÒXþ…ïµùë1g~·fý¾{²ù ßMý5˜ß]ÙýÁ÷ÁÆú ß]Ùÿ…ï®þšô/|wåôþólü…ï®\þÂwW®á»+·¿ðÝ•û_sìÝÕç¿ðÝ•Ç_øîÊó/|wõ>Åÿg6üßÃ\DÄþ³ëûóÿþÂüÏMp¿_'·Ïdšº:½+—}W¾Ÿö?lnõþ ~š",ÎÙ›ò[k-õÏŸ,ƒ¦±hŒSøÑù« 1há+¸mѰ¬#íZ­Öcyòô±û3sD«·ò˜Äy€c\Êìëž›Ñ^šg3ÖUš¼Ç®é}Ð1Êφ™›pÅ鵑ÒD킾̋þã\%j1µ}ذ.]·º®ô`N.-‰4[õ°ZJ6ÔÇÒpö°UwÔÄx¨Õ‰ _ë0¸&ºåKûVWôÇ|¸œ„W½{¬X4ÓVb6•-ZL•}Á“’‚0T”š·ÞÁ*¡t€…ª`z NeX:( #´*Ó_Üpêg\<\Þ휾¹U‹ä…‚S­hÇÎв@f¡ù">ß¾"šêÎóõü›;¯U6Á|ÃÿÜ%Á%7ZCFš©Ùš G§/-}Ó“ù&C_ØÔA0ñÍËU(M_اÈÁjõÑZ„æÙWÑ¥·ŸOé0 '«þ£œl¯ ŽÓÇ¡ËM‘ƪ =¥_Q*hòÏÓòjÞè«höP¦kB*ÅßU„ó|v?s˜Hc æf!І~ð2Vudæß«„)AVGÆqsÛûYG›F^Ñ*P=ìåÉûZ¢xÊ=úd§¦[ÛÚ›e€ýÍ ¶<3QÝvæŽü\3ݬa…§*Q°?Ú‰3†WÄef˜³*ÖT¢‹@tÀi”œ‰—„^v<Ú1·X.-ñ,¡ð ¨y³áŠ*Y5H9Éoª´DCIáJÞ ¸„Á”V^×u…bÍc~ɯwÕùT¿ÿ¶¼‹ &?õù7n¦cÓòM’RËQÆe³wÇÀh²tÌhB$>jƒÐç¬H{9LÓ A Æ™zû¡Ç7¼68N\üÃF+ÖÙØNÔ˜iøõ3ïùÂb/¸.…IÕRƒ²æ Ájžu 7ÈÎT¹ÓæT”ÊÙf·E‹¹ù Bˆ¼‡ÕzúZQ²^’».œâ»yêýΑœÌ‰˜P‡]XêÚ « G²ž©™I`ä•ÕÉ 'aÔwÛÏ »ÆÕ°ßÚé†YëT…\ï¤ µ§î8$-²TüÅíÝei¿^/ôó2E¦¾¢8·ˆý˜À*Âü˜?;ö™_ ŽXf|àšn-'f¾µ€|?jófwŠ}ºö9pèxf!ŽqÁ §§²bÄ{Œ%ƽ̮qƒQ9.6Ùʽ-*ö¥ífRKLÁÇçëçè£Tïvhñ8F  › Éh5™ƒÎí—êÏ\¦jh¯œåú. \_a¾À„èö¢«EúçDïSÇìi¢úˆ+~“ÿ4.ÈùTà-ÙäüÕ˜À=>’XÊKUèÜ©Ïy ¾på];À…RÚ FRoeâ_hH߀æeF#P‰\˜'zk? ëΗ¯OÀOmÆGAòaœâÚS)in7£j1sjÉ÷»¸†„üÝ›þ ·‡çn¥„C°:J'87è·ŸS ¶öDI­Dÿ *>Læ‘ðAÚžRRr þÈ †~‹e™^»öjn bST>Bh ÍŸ}5#¯IqªônÐ\TùÂÞ׬XP4G04=œ®”Gß’c%(6UÅz+Þ¼I¦j…Yüâwh™Õ­L=ˆÚq+QÖj”yë·™©L̪ÀšdìÞËe‡GhEHòÜr½ò³sÌÁŸhL.¨“Ñ*Wh³`⑜,åŠh5ùÔßh9å CPŒT¸…¨Àùr(Évù—røÒ=zEÐÆéFÌ3_^]ÞÇ]ø Rx—‰ÊàÁŒϳ‰Œ|V¬>æGËÜpÇM—IgvP»Bk¥0‚"4òˆ”_ÊŒNŸížuf°Pß{Ùƒ¥“½ y·g”ãBî”[ßsŠíÅR’Žå9Ûà…*Ÿ^ÇÒ%ÓIË,åìŸtî ãv2zîŽÄÂb°=]ý_^Ð Ø#WäòSáË×£„! cçÌÑaÐ }ﺳЅ"¿7ñÌ€9Þò*ba|’ð:kЦ‚›$œ÷EMk1íÊÞ¤„QÆæî[œU¡÷·b ,qÙôÊpå9»äÂ]åÌ«ý•i«èfì"Âsè4bœÌîf­ŸCñ`ÉEËçÊ€b[=„÷\Ófת4•9<(c ¬3ªÀÓ¬a]ºîwÑJ©@ Ú3QRœ¼BMT1¹a>$QE4­[¶Ÿ†÷f‡6{ë&kNeçsöcO—#ˆ"JeUz¤5*vr©#£Ÿ§õ ½pIò×ÈâH H„™ÈûÛW°òÎé°ñç;Ó.Q¹Ì™Ô§/šú ÑV–,sévFjÛÎ{ÎpLCÎÔ~ãê½ÙÛ•7è…¦JElMá ÓÝ*,3ÛPr}è©ûÃy±:¢fG »¯þœÖ"ûÎ|qhd$û–±£Ö7(Œ–í¬jÈœð4#YÃáUâ Y¨%“¸q½4N,Šä·c{Å’KèÀEÔ,Ó-l&i™-O}gg††q¹+æ™s=¬Í+ÈTT„]ær!):Lrã®G£XfùÉg]å!¨"üK^û®£0cv³7ŒeoõyNN`]ÈúºŒi¯·aΰkz7~¼~6'„xa÷ÁÖp*öT&×ýEœFþYsô¦2C§†£[õ1.¼Sô1NB "˜8vÙýÚ]B¿)z!ñi0ÄO"CÏŸ$ùˆð«¨Ÿ &¿;  Ÿ‰A€i=–ù»÷éE¡ønÏEsdM¤óÝÇPÊQ4Gw–Œm…<Ú„ÚöOæ›]tøhXŠv»úV‹›*†Ìù¯,D||ÉÕ¥4]V¯Ê+ÿaŸÎXò¡Wâp®%ƒœ¥RÑ`„¶kâ1ü2à|‡^_*9«0Ý‚ÇÑcV¥nǯÁeê&Óp\€Ò@”Íx xÙ¬ëÿc(Ã9«Íåþ$Eâ•*âAIÖÃk}àç‡î” V„”ó}ê\a\p»á å''5þ‹+.¸·gÃeÿ¦Í”óoN½ùföـèïÊ„ã×úÒ!9¶“ŒIpÜ5#ÁSžP»k©ìZG*<Œ?D`ZÁÆç™®Û>!daž'w(íÅ„ÞX5-wê•d—éH1Ç;ý2DÛ„¥ˆYVAhŽˆ¾RFŒ_þª µ|PÎú»ÿû¡ì·¹ Ò›ÓǤÀ2í“76ûÉ-;žÏFq\ùë8¿i25ëwDæd2‚0ýI³â?–.!%Û@uy kJѨÒõüv¡¸öBl¦hû¥? /]3ëÇ‹“ƒå9Я\½ òÊ6ƒH$³pˆw@Vñ‘þ0²¥»ä[yލ\©ßÜB¨Jr Ù8Ý>µ¨ˆ4Ý+ù£« >Ûâ›Í8|œë5ýòJФ~ÐrÒŒ9åp!º›ö"ƒ.KÝ£ÿE³6,Ø Æ›ÇTŠnîÍöÅ^-¢¼évÅy&cƒ;P…öX ÍõyQ$ô ©GpëÌM?}L­Ú£´°úsûm!âi q¿áV‘ow§ã}ª­2—ÀOl€ãoRVx£1‹¤æ+ç£ÍÊ#Ñè—ocB?”,r/²ÒÍé¿Pç ˆ»—¹C¨¼ó„o˜ÒN<ç)#5â>cû þróÔ[RþÂp®²]øé\áûAÝÊ(ð (óxœ?’£Ôip~"ˆAÑTOnëOD*ÏvV?NÛʆ˜rFR"p­Py -3‚˜~ö.¡ƒ•k¿}AÝaHÌⰲاŒÍ¬Ôóæá(£D’Û(º~OA·)²üà&‡þ-^LQ½½ïô9‚¸h؆³¦UÒa•’ÛŽq„±•ÃÐãÎïêÍ]VAGe‹Ê?ÛŸ¼–AaÚç. Ö5m·Ï̳Ryîn_;NäæaãH`#ڄÜ‚-ƒËÒ•;ÅIl²uƒ£°'ùã~J€ÞéHAlòÚµ0Ì?l¢Õñ:øÜΗqODk*ç¾óÅ 8\;V+”dôS»+ ½ÛºF’ƒ zº«ÖåÎ*—Ù/ØãØ«…A¨ÂåN{<¹›U &ý Ä’¥J¢…³#¾«ÜøÞÝ;ó™øÉ/ß9PSÀ3…í¹°>Bmµ‡*Y†þ&ÙÒû²ö±¬âˆôÔÝké{u¹¹Fw"ÅêëεD4N zIû[LÔ%Yç¢)¾|ó†¡*)×<˜ÄϘá[4Ô'Nã6ˆA'jNŸœI‰ü!D<±¢wJ?ìZ‘ÔƒÒ“àgú(ÃþQ|9Fe·=BŸAd®H?¢œn;v›¶ÊʡͯÅÒÓ•wÇ FE¦ ¶½uBä¼ß]ïϹ, øÍïÌTZÕú¦œýƒG¾<øu.Æv8d z¶]åZÉÌxGÏw$IUŽßdÑ B-† å*\‘ݣZºulÍusUtlH¾8j ñãê¯(à.Xò>¦<ЙêêAU÷y3©Ÿ§þ¢1—ž!B÷~sáLSÆà4ím{€4 á#DÈd‰`„M$‚Ó“ÑD:+¥!§kqóHPzBäÎòV±YÃ¥ÓI¸µÄ(Á»á"àVÛiÿ†É˜ I>$„bó¬uj¹1ˆqÂ|Ò£ù«3%©UÖÜ[ð„]l®ßunk¼ÁSX›~Ÿ%xÆ 72iTÖê¼uîèBÀ›Ûö1¢~U[ßqÂÄ[<Ê·¨î›¾Ð²£˜vÊ^Àií¡F: Ü—¤ü^"úÜcëõ[Ić¸N¶õ™JØFü–…™(»²÷‚‘Ä ZþÛmWÃ܃ðÖôsz`fûçE×+’BE׈”x…-!•v½Bký€6£ ìo3 ÖŽ®îq{Ϲa-ð” ‚ã0—Å’&Zì+Û vôGx×/Å碰ÂÓņoJ7ÕŠ°Rúm˜á„hÈwWíåûP;¾ÔTÏÊáw³ë,²Æ/oðbzÁ/ØÒ+tw h|v’+º(š{™;Jû¦™»â…hÇ>m ûÈ$ay_y bƒ…™;NmdK\ª®Ùಓp4R=u¨ ^¼×86V²À}J꜠Žüjø*eS£>ª|Ü„ wÆ™ÐjÅ?^ݦDwqe…ØùFªUVi’ù ‹ÎÃUS½4^Yº}R°ØFga¼“;Š´IÐ.k7Ž,Á=¤'ɯÝöËf£èD¢Û ,OðôRÇÉ‹Ví‚´g–ÊXhô ö3³s|£^Ü3‡­däøfqë÷¾ëiðæ †WeŽÝ ³Í‰#Dáç0ùB®2²`\&z2Ò¯æÌcè¦}ª®&HÉ0ŸBãP‡,ô ÚuSÑ–3&8GÿÙ}g ‰ðMʇ¸djú—â¸94F\TÒz3|& 4N³hsÐW×9[ÚF#öÔ´käst°ƒ/ö¿¸}Á<ÈÝœCà¡™0—4ÌäæùeΚ«hȉ`ó}_¢3…³‘¨ü\²aÿ5™bÂCèµ oK +ÒE‚âØ” ôͶ¼’í–©ÒšßLŸKJn“»T«½Q1˜À>+…D”ô|±¿®wÞI£ñfÓ_ã«P-gm ñ¼;Mmê^î[$Ü`ûê±@Å¡±¼µ¼”ÉÊ^é¬5b‚/Æ"dV—<”‘fÓ”È@Â^€i,ÅáÉ3Ìׇ¼ãû[‘”þ’œ€}rºÑv,Ê·Ö–Æþ3æ½Úr‚ =VgÚãÆ•3æ4™_Ò9µ/¤è‹¡hTæéT±~à–“\^4f \4qਫ਼hñnU­ÙdÆj€ÂV?ëÀ -Œšˆœ¿:ÉõA¨ñï‹3+q_ctÉh<;2ð8¥­Çkµz¢·ÎçÜQŸŸ€4#”“ðE¢æm½¬ëŒ÷LSÖ>*fidô|ǡ鵌ôׇ| ½9+{9±#Ó ÝíJâg”Lôôèm¥o¨‘JR@‡Ä¼ÿã=ê…ÚõÆæã‘Bð–o·c`®8˜¼C¾Œå'ÃTr§`í Ýú¤ ºÁ\à·˜1~k.üTçER*¹Ü»šôu¹Âgý Ï!¢×ñ/újPJœT#±*’VûÇÃÞ~NLþî*ä©îv²;MÛ”¥bep»qôzrr_(rL5àQaæVdFMsµLâbÒÂÔ¦Xè Iºë¡&Uës§T¤*â¢Þž¶)b;)¨ÿ&2ƒrÀ=2»æ¨V´@'wi@Òß(2œ=“mv$(hq6Ò«è{•:qj}dŠRgÊÿ í;Œ~q]h9š…ÖQ€ýÂ%]KÂt'ýb,A»9€2·)¿2)qÈÛØõ£”»AT‹4[p.œ;λîª.Tñ·ÜO¾†0¬j_ì ¦œN~ÄA7Î&Þcq9Ä3ɧ¢î”Ñ ¦ÛÚ?„¸OæÌpGwÅÊÉgV¢¹ååëþ×d¸cçп ùFXpˆ˜8›²þDq[Jм)3­üØã¯> zÛ.IÔK{ÑÙ ä@ži©·]±Šú)µ¶w[7+ðÛu½ÙWަ²s"*€R"ö†9Ü`ÈIZq0à“†sï F`T·+K¾b¸Ø…³ 4NŒá·>©ÌA\ÕÒ]Pd3YÄ—Çé݈«_ñ‚épö¶"q×… ˼ýN å„2êc´¶Âs¿:µÌM³šã./#‚Iãõ·Ï„ "Ûê5zÁ¿bޏsÂÒ½Ôò×hü»^ÆÁM°é5ž Þ$:Zw²H„;i8ûˆ¡¦ bð1Â@$¢#¦Mç}¹Î ‰wb«pEÌŒ±>P«ÞþÔ oS1z¥<áO¦xæ¡4´¿é9%0ðsa)à9 ï÷¦©N4ôÐ lG±øí|0Ž5UâÚÞ :͵Ò\;Bç®T:@³Ú;ËÐ÷ýXä×â2ª9+´`ŠRÏÆWæ¼—4éxv¾À¦c*†Üv$8î…ª—ÚšyØq@)bEÜ2»à÷„IKü†ÀÚcÍKÈ­z½R¨¿ý5ʇŠ«*ì8ñ†^ôp«RÝ ÿ°õG1ûãÇñi^=A,¸—ÂZÄÌâì>_F8íÀi*3f´°»™ ;4…}>…P¨{åÚÕ¿í39€ÉÀÝ}ªoZ˜OþE3;G>—dÐ!á‚'F—ÅÉÓyuë\õf\Ⱥ‡`UÖ 4a\/é·ÈBW2Å_5\yãï§^ â|ÓÐyÂûŠÑÒAGOÇÇÕµ÷€"º'‘BÑ+;ÿMöÖ‰¸~‘æÙžÚQY$*ÜÁ§;š• \ë8Øa³|î×r/bTæè^«øeßi„L]^(L©™çÜ.÷*Y&ô<¢ÊÊØmG4IðMPüäkÊ÷$ îq/ìFЪõ–a÷”y¿‚à|< z`Ä¥uLTºpPQ…Ñø®„˜tä§ê579vKÐñØ $ÌÇ/fâSó…ùÅR7!c+÷óÉêcØ'؄؀_ôEד]Ümß{ƒAàÙuçY]Q¨,·´ÐD¬w0IóóAÌgVÂÔ¯¯ãUN¹:y~Œ®¼ÃP\ßw;öèà~’ÑÆ2Ì­1dòØ#<èöÅRMV,ð<§wôÜ ð˜Rx àû©Ð)|–.I³ÚˆP Åߢ“‘AìÙb×°hTè,¡k¼ÝèÝ{ î±­‘f³iñ~ù­1¿ýÝÿhú'5uA`½Í6Ù™?Ø—ôòâ_p1ò_P¼e{I84ÃÙ†Ò:Z´Ù+èÇfNN¶>Nf-ÏéÇb›ý‹xrnh§Ãer<Ü;¥Xq]ý<|‚‰>ºä `Ř¥&Wê«ÊðOÉŸ)• =xð’»!0£œrð’ðI]hãɾ€Šrwîù›Î–nôÌìH¥¿7µ‡nic7;±P|kMCTö|žK“¶þY>¯Û€:×ÚÇbxªlºµ À‹î²Y›â€=‚Î/ŒÔpùäñ½ýkùM^ÜrÌÎIY<ïÖšPPjaWºpTO=óî€çjl~¥6 刲TÈB¼cÝ>ô©p‹|9 ñd+á0j5Úöé,9}?Ãø¬p1ë ݯc­SÏ}Dõ…àDYLrLñ!&ûyß³úÏZ‰!¹èDLΓm+u¿Ô/\,Å—MÌæÙ¡¨%¬Uý²p” t2…h‰h êÇ–uR}ç‹ÇßÛ’ñ¤¡¹GeÄS,ÍïRu+OcS–ã–¬I‰¥è¿Ècm7ÂX&ÀÑ[B¼p›J-®ÿ¨%aä0n¶çY_·à² Ü~™Èñp™EâõæôìÿN1¡j°½„m/Ó¡lñéj6gña^¯2 ƒèyšô±Ö|hDW¢-FQÜ6Çëîqàó¡ 'GÝdû­ùÑ€øSè×JqËÕ€>üu¾½k*kH;Ó–Nf¶ºæZ1‚QI6…N½:§RÅ Ó.䫱=bcsšfÔ`†Î²zd]èb¿PI_,S;Ú’µŒdÑ޽ѡ§ª‘QMƒ”_k­Ø¯™ÌK´µÅ|tB7­y8º:P ó™Å³«±ÌZ 㦔9Ædhr‘u$Úa(íË33°ä­†6²Äz€é]Š­ }… ŠWØmæ`m°•IZ‚îuß§Ú6[_ w†c3Ãçô¹)˜?ï~‰hîÉ⋵ַy½TÿZ‹Ý¡e‚4½Û1Ê“¸Ö{,ú¡Yöž¼*Þ>Îe²þjhÙǨ¡èaz´Ÿ¢¢Cõ‹ioÕÖ«“„íDtýB5@e…SÈp¥Ä2ãûRó²×ÂÀuÇÍ<ýe7Aè|»1Oz‰ž¥;%Ô§IÚjK y¹g#UZûaHtª5–+a‚x;ÆYÙ]G˜ùòS_MX|j±ÔyÃåUúK5±n›€ñR¯-)Š[o8‹8||]Ÿ„2Z®û(§¯ˆd»Æ|¹¥3ŠöëñIÁr‡‚l6ÎqÁ©‰¥pâ˜<˜õ7¤$–ØLˆiidäҰ©]žçqýGŠS¢B°ƒÅ©«P)~4\裚ÔxŸ€e$¸O6§™™Úú4[çŸÕcÛ@ˆ³M â×ÖÜS¨©\`sÛW8ÓŸ‚²xžs~´»à•Ô—«sçS†²•m!øýáÎÂgt MóµAË‘цÚX˹‰bý5µÒîºbOØ|Ÿ|,gõ.¾aŦÄÍ™WîGÀ#ï‹â=ÕMI( -𵙉±‹¼!Uœ/µÓðæ,·Û!p䦴 ƒiÍßeêä &ýˆáe©¹«‡^"”ÊIM‰«Y˜M<:̂”4B®©e²œo+)צáÁ²0Ûb˜&®ß8F>»od*5·ýŠ_U¦œyA.׸TûmÂù☨àt³ÿê“DX;0÷ƒ‹F°ÉB„nDÁy™èPÓâä¾§,ÊhŸžè¸ ³02ºOì-¨Z¥dv©¯ñÁu©gu´¯¬ËIÐ ÕÀ–elŢ↚–3íƒ!Ìr'I¿Ùaš•óY8dü3Ö¸‚ÎbšÝÉ!B%Â3+áD¿:{%6ð±N%ÀW®G& Ò|Îm Îé7Cd´«ã©:iâ‡a”lå ‹²1¢-÷"! o&àÕ:šD›y_dÌìéÈá¯b3‘žÜ©X‚k¯Dp´„ˆíÁœªO‡µƒV‘—6è4ŸX&Ó¦3ùS«S‘2d<½‰o¸|Ó]iG^ÈÚyV'%Ä*…Œ>ï¸oLÀÝZÈBæ}\jºiIQÓ6´Ti@:£´Ô̤c2ü–!ÛÅñ" |–Ú.ÂÁÜ -K§ÔØzÚŒÑ[žkG°´Ä ÿ\¶ÁÝÙ+˜Ëc¸Æ’pž{€!V¿Ž•+¾?Wñ|¸¦¢s¼wÌI‡”€’ø$è ±n~º‘j br»&¬fB¨î&šw©£=U™+Á#Ë`ÝZeâÖ~$Øý²DÙv¼ØÚöH¿:¶Œò  ^À½& ¿zò¤IHËÆñ•Y«¿à¦]ˆ5¥ÕŠSº ®¸²oÔÖjÎ"–>dlõè&2t×Å€ag~ÑŠœ1GïïßÞ5÷t_éu5Lµ¼o ˜Œ-­'}F°3#Q©5ûûÍ 7Ã+ááv`Yx¶Â¸§çž«ŒR®ç3Ë?Ñö„>ܶ –EíI~F—Z@Bi cO¥]dàå»—>¼q7>SÎWÞ“þÊzJ'½·Á/‡_ÃEð iów’¸*†ú9TiúVénTµxÞ£cº×pyÿµ|±ð-{CNÍœlµ#›ì"+ÍÇ›•‰éäÉrmþ\úC†Çyº™ÐXëb¶Â¤8©_¶•PTÓFqÉðµGOb¤UÉs¦’IM’­Ùb}gH”€f:ûZKü†qã5Ò£ Nópbžñ°/^Z¾ÙÚôÒ¡ª2QŸ­QØHØî^ï:¬6kÄelv/[I¤‘õ8o~‘éP4ëù1aÓÿÖÒ%Ô¥© ô5^£áÅÞûqœzj,ttŸ˜Q”:\yAóõÐõeSüIkQ¾•&Xjð†Þë«T³M£“Ü8n^›H´x¹êzEÐÜ^œÔ¥(È¿qWWúcH.T³4©f¡FÆÁ›…øœo¬Á6oÝ@™¯ìЭ‹g -`YÒ2>Äï„8“·È ×`´“(Ü(C`ÒÐkÃãüiµàð¼¿Qñ3“éöœdïD ìÞöxôÐu&D¦w§}™šHßBuÖMxÓcGá7ñÇç:yF%¨3@ !Åæœ+&Œ;+(ëVG§!ÝÃÒÚØËåb½ÞÏ[eaˆm¬làJ2þÔ,tbxµŸIõ«Ž”HåÎ8Éߦ©Ùų÷Y29 ù —F£~Ô¯ Kñö{ókMÞ-:C‹á¡ªÖ眼,©‹<šÖˤýã£áÒ¡hŽtnÅÉûI:°ÌN`ü‡5ö‚Týc-«»ÒY¤KOîXœVè±ôýù˜!}N$Ø2ÇxdŸÛ‰f.úâL€2BcÔ—‘/å°Á±÷OS©|%.c~½4o3;ŸÛh 1¹&1ý€„ËGØœ†y’¨÷Æ×í^vå:ÞœŠÆä†7(Ë%”ÛÓee[èIºûhOÀ6‚ dH¨Bæ£îv52‹K -zÁŽB „ζ2­6?qvhÃY}Œµ*çy&[á’˜9'_e¾Iø4MC—ç¾â.ï­Z¨*0­ÊgBA†Tó°š(Þ¸ͬL5.x<8çe¦æGÅ>ë&£QXZÈbƒ.[–”¢ö§€ýô 騛ØÒ° ŸUrå@ž,Pn¹¨sÙ"™iØ.3¬^ÝŠ}¹ßšO uMÁ¿ÛúëÛÃJ '+.ärÌ­R±É®– xuôèç~H9jà@`ƒ$ÿ"Õdß"OÿeZg(šEd­Gø©;h^;óÒ”Z”9žh$É)¼*cö¹gšÕC|fe-Wöá8ò¬O?‘¬·š†¥›ôpù•lÐŽ†‹ª†CØfíu&Ͻà‚ùTªC»²Ëbêæã…s$Ø€¬Ë'ò€¯¡£(X…}cVæ‰!ø¼ZNN¸a b(µæÌuÎápÄŸ“U@¾"G‹ýM™1ž]Ðù*Sa¾óúâúá©Ûíj#tZ¯¿›Épôè/*%vbé ¼|ÏÖ.-ËùmB(¤D•kÈt×_ßœD¶H GKXž3ü4~jh«ñk’0ð¯踆Ðn¹—ë áUÝl>@¹ÚDó&1!àH^+ê6”m0¹â)¶> ?Ð˼I¸}/j«¿?;?„mí':ÊÂÌÍ98_ ™Bj‡GrH @Û÷|RnqÐK¤/ço/ïì»bp_„`òì6åÄžÏr[ßÄê•%Ã’ÀÉÉISn‡¤Â Üå~3<µ÷uâ)½,nɼ‹ ?…áôÄO¿›6eY¬ÑÕü9óqçćê3k,À娶N _¦Ä>XÔ»†¥v¨&2 ž«ªÂF.ÅÕ8ÿBd/!yÕ7L÷i1áØw‘è&tò\gV@b„6-²îe•~D}µŠÛàFub»ò$p¢w]`tÿ±ô1Цs”±õLT÷…ûYiÔu¬2a*®,­I` õ$ÄG1’a ñ…_ÈÃ6Í¥ùãsïEÓ ÃWä›üzïc£kSÿÆñŸÈ +߬; ÷7…®EÀ|ª»f•1­¥Óý­ n/Öœ)Ÿ:3•n‹1‹%Èä! ÕDóRqCÁÉ’ƒDiÁ¾Yõ=áÖfìº%œ6Ëë,Bž†!>ù^ŒVDàƒ´Ã’tÏœ¼UULéZNuµ¦ã è1¤,Î ÏyË:+Ì·ùgù¶š=iš÷.Å^³ØG¯_pž9mОpH¯ðNiz•5䬟½ BÕÚjèÕo|³æµ÷?…ãk Ô¬£¥.ɵö͉!_Å}Ê1³d»Ó:˜‰ ¬¹úû„ø(sÔÔãI©“°Íx¦p°½®må–xÕeaV4»;H-–Û¾†¶ *r¶*ô‘AsD"ºv»ù èkÆ•Ï8ÏÞ\”¾O(ÒWEäw™‰S[(UT·†=spBOW.¦ÁèµÑÕ—©6/9`M„5ì¶).ÂWeì82ËSê;X^p;2—ŸRJˆ ü„ dAx‡Ýð9ŽRÿNvhs²µ‘²Ô©¯MÇB¸©ušx‰§Œmå]$š³Ü›ð+Ãbblæ·Å•g¾ ä*X_šÈ°ƒ2»‡ÐÞçõfgo*‹PK.µI} Ÿ´Í•`&¨tà¡w]×Û ñºÉ£—|ÛOç ÃRÞ$îŒÖèDäUÁf(Å\ñIÊ”e¨ /Ç’…:€ýÙèÓZ"d¿Y&%>>ms:;ñÙ:TæUá¤?ã¡&‰?k–ŽÕPÓ’®…Ç“Idý½Ëq¥Ž5#×"OãZíSH±qƒöy|àÕQ êe«H¿Žw»2ºðBú£¡ßPh=¿ÉcNÂ`GZLØÚ3/ôÔ&àɵŸð÷üËôzhÌœäÇ’ã)ì"2;t‰€Éýq 7:“›:Ê3õßvK=dÅÐ^¯0µô“Ÿà&fÛú0pÎÁ$jhÊoJ¼ð=·j޳ÖL$>¿fÏ*•Ã,71²ÀåÃÞN—m¬áQäOh[ÑÍð¿×Å|˜2-d|VõÒl­:pCœèØ=½³b¡øe(Óó#³ôל¬Ð³NOtÓ^WöE]ãMþÒa.ƒ¼ùü|øQV?Q“ÄìðCœ ‹2M~Óúú<6„‹Ú—Bu nfëlõáPr×n–Éù[c½üÐ?¨é#ðÃñÌùõ6‹jÏUëëa™N¿~{5J]* Ë}^¬_e¼ñ7ôö™§gOµ#P!¤†§¤¥ G±–lHÝON¥¦2—«†ãk¾jÆÌ~‚³,Š…¶CBA8 ["ÎóH^w;¨ÇAI³ÝiÂXËôÒ¹Û"¤rÈÏêmmO ¹¡„Bpî¶Ú‚ ¸ö:&¸…é2¾çIò6Dj{8Ðú¬jíÌDdöqÍË¥ÜrK1©“ÀÒ%¤±‘KŒÙ±í ôUy¤:y”…×ø†ÆÝܤO—ÓͲæŽd74+äU°WÍÈ"щï=×îi2ç-0¬NfCV.O=>3‘EZçRv½óÕ—7nrxÕ˜Ó¡Õ‰/ú€åÀ€7S­ò²}¬àÕ²ÎÞj¼¸KÚ~«‘–®ÈBH˜y§wÒ{: s¡¶æ1­•N*B2É>žfŠö‰I¢§Z*n¬î±Prþ>¦ãEX›—ò¦Lì‹NÀmØBåyÚÚÏíbà)–U†9N‹ùUèø×{› »4Ea;kpnŠCØf<ÈB›Úqž¬((ë­ÑXYF9ÕW0Nð³&·ò Ž^‰¦`·S%ÔȘ•f^Þci†ž(©ØB,8%T´>ºj 蚪£ÖÄûì^²}k‚>kËFÙÚ Cb\uáEÿ <¶¦LÅwùa:RÝÑzÛlê«ê}ç3L‘QíÆbýk¢«Pá»Û 9"`A¬ï…ù–=Ý!{Næ‰bcËSã¢Nù›qmžmÅ‘»õk7¯¨j±ú¨ÉÅtȦÞ=óT9ž–ŸÆ}p ¸GB/8&P7ûø6FøÂBa‹[ÿœI_€q`ž'Š4aİQ)eîm”ÓÉ/l¶8*1¨–?¼›û1AîëÙY¸‡»*ÿ›ì¶•×l©Gb㛵{9»‚©Qˆ²™ªžóX§_ø ØPhDHH9¹Ž{njAfëcÿ_;udNá()Ù%ô¸ È ^züìü¦]åò:{­Åvv¹‚ß?‰svÝ«¦›Šx>BúBq»ºý ÷%Ug ŸÌ-JàAÒ‡êu_I?cÙ¢O…{?˜2ˆC,05‘@®¤r©j¿1þ„ ̓ú’®Nz`7íäÑ-À¤~Þ>T–+Š\üå®D“cÍO~Örtžnh©à,›!è‰_í¯Ù¸ý’pÔ¢}Ç®±=k×ÙÀ¡ Ù21"T¡0àSZB0ˆ„ÃìûcEƒþL+‡w>‘ÚÒqô;—s $iñÌKè§8¼Çž±%*)ùMÙ£]êeƒý<‹«B w¹ïË®Ý&ªÕùÃHˆLæZÇòm^Ÿ¥ùIÏXZËð/Õç8¾ÄÈÐ ¬ÕºÊými¬Æúv'À¿ô‰ J)ÙKEØ3ÄBhZI†-žÜò†·‹à»ÉT¯J£™°9OÈÃïh- §úÆÐ …õ ö•R>8Öfbv(z´Lñþ«äÂ|>‹ï&[ÍfÁn?ÀôÑûs³G:'Ij­€y9óÓÜ7”Ç,r3ÜÛŸUV >èæGÝ0±r‹Ã=O”%à~Ÿ‚2Ÿ_ê žÂÌÖv¸:Rô÷Ûzf]äWogj—@s2°r'¶À=UÉì)ì'mÖm™$™V¤‰S¦¨¬ƒV¼>$ ÂÒ!eª–ïo+`äï ¢—(W>Y#ŒTÝù{]P…iíÊ´ ]mšàhì^.¦cw4·¢õ»oÖiš„@¨(Ð:2'ª/˜ü”²Ùgû–yr˜ÞÆJøK¾™Úe|LZͳL¶–ŸQ¥ƒ0/¢?ê\]~¼F Ö{ ?Ž©{3özF±ÄÅÝÃn"t™ów÷Ì:ºMí/¿›ˆ)êa(ä]Á °VЫ˜¿Ou"²²Še.¤­F7Ê;‚§ÂÚQ!þ¢ÊôKE•—W;‘d¥á7šX+éÎæïÆyœi]~f~j ƒN$Ÿ.²9¥šËGÆÀ4kÀVÝЂ¾»XGZ¼L€Ww®®cö½¸¹gÀOH– •›ŽQoåµû YŒtº–£îóÇ$ÃÇm[þKˆ÷a ÏS.[ÈCe»Ñ;QˆÞ€UøÖÅBSç}aþSoMû0}PØ@û…äÑEÓV’w_G!€Þ²lɘ³"¬}Èø£‰²Ê{£FÊÛ)$eJŠ0 ’s1Äû(“ å¥Gx…×?ÄpT=‘‡Ûïúä䢡´gÊç~8þŒå~ ) ’rF9¨=¿é7ddG<äÆÖ‚±ó¨Ö¬w)–ò{M{[Ñ÷‚`Ã}Ãj.£3p4Ú¥5Ú,¨ˆ¾Öm`·žª.^mì2«Ga Tø7lc¡KïÀ~« ‰vp³ŽYÃ#Taðk`þøƒðÿðÿ‰LmÆN.övÆN6ÿدØ)endstream endobj 6 0 obj << /Type /Font /Subtype /Type1 /Encoding 1184 0 R /FirstChar 11 /LastChar 123 /Widths 1185 0 R /BaseFont /RFMRVQ+CMR10 /FontDescriptor 4 0 R >> endobj 4 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /RFMRVQ+CMR10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-251 -250 1009 969] /Flags 4 /CharSet (/ff/fi/fl/ffi/quotedblright/numbersign/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/equal/question/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/R/S/T/U/V/W/X/Y/bracketleft/quotedblleft/bracketright/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash) /FontFile 5 0 R >> endobj 1185 0 obj [583 556 556 833 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 833 0 0 0 278 389 389 0 0 278 333 278 500 500 500 500 500 500 500 500 500 500 500 278 0 0 778 0 472 0 750 708 722 764 681 653 785 750 361 0 778 625 917 750 778 681 0 736 556 722 750 750 1028 750 750 0 278 500 278 0 0 278 500 556 444 556 444 306 500 556 278 306 528 278 833 556 500 556 528 392 394 389 556 528 722 528 528 444 500 ] endobj 1184 0 obj << /Type /Encoding /Differences [ 0 /.notdef 11/ff/fi/fl/ffi 15/.notdef 34/quotedblright/numbersign 36/.notdef 39/quoteright/parenleft/parenright 42/.notdef 44/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon 59/.notdef 61/equal 62/.notdef 63/question 64/.notdef 65/A/B/C/D/E/F/G/H/I 74/.notdef 75/K/L/M/N/O/P 81/.notdef 82/R/S/T/U/V/W/X/Y 90/.notdef 91/bracketleft/quotedblleft/bracketright 94/.notdef 96/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash 124/.notdef] >> endobj 10 0 obj << /Type /Pages /Count 6 /Parent 1186 0 R /Kids [2 0 R 12 0 R 15 0 R 31 0 R 35 0 R 40 0 R] >> endobj 58 0 obj << /Type /Pages /Count 6 /Parent 1186 0 R /Kids [44 0 R 61 0 R 72 0 R 85 0 R 98 0 R 106 0 R] >> endobj 121 0 obj << /Type /Pages /Count 6 /Parent 1186 0 R /Kids [115 0 R 125 0 R 134 0 R 138 0 R 142 0 R 150 0 R] >> endobj 169 0 obj << /Type /Pages /Count 6 /Parent 1186 0 R /Kids [165 0 R 171 0 R 179 0 R 186 0 R 194 0 R 199 0 R] >> endobj 213 0 obj << /Type /Pages /Count 6 /Parent 1186 0 R /Kids [208 0 R 215 0 R 220 0 R 229 0 R 239 0 R 247 0 R] >> endobj 265 0 obj << /Type /Pages /Count 6 /Parent 1186 0 R /Kids [254 0 R 267 0 R 274 0 R 278 0 R 285 0 R 291 0 R] >> endobj 304 0 obj << /Type /Pages /Count 6 /Parent 1187 0 R /Kids [298 0 R 306 0 R 313 0 R 320 0 R 326 0 R 330 0 R] >> endobj 345 0 obj << /Type /Pages /Count 6 /Parent 1187 0 R /Kids [338 0 R 347 0 R 352 0 R 362 0 R 372 0 R 377 0 R] >> endobj 387 0 obj << /Type /Pages /Count 6 /Parent 1187 0 R /Kids [381 0 R 389 0 R 393 0 R 406 0 R 412 0 R 499 0 R] >> endobj 734 0 obj << /Type /Pages /Count 6 /Parent 1187 0 R /Kids [622 0 R 736 0 R 847 0 R 961 0 R 986 0 R 1028 0 R] >> endobj 1186 0 obj << /Type /Pages /Count 36 /Parent 1188 0 R /Kids [10 0 R 58 0 R 121 0 R 169 0 R 213 0 R 265 0 R] >> endobj 1187 0 obj << /Type /Pages /Count 24 /Parent 1188 0 R /Kids [304 0 R 345 0 R 387 0 R 734 0 R] >> endobj 1188 0 obj << /Type /Pages /Count 60 /Kids [1186 0 R 1187 0 R] >> endobj 1189 0 obj << /Type /Outlines /First 1038 0 R /Last 1158 0 R /Count 8 >> endobj 1158 0 obj << /Title 1159 0 R /A 1157 0 R /Parent 1189 0 R /Prev 1155 0 R >> endobj 1155 0 obj << /Title 1156 0 R /A 1154 0 R /Parent 1189 0 R /Prev 1143 0 R /Next 1158 0 R >> endobj 1152 0 obj << /Title 1153 0 R /A 1151 0 R /Parent 1143 0 R /Prev 1149 0 R >> endobj 1149 0 obj << /Title 1150 0 R /A 1148 0 R /Parent 1143 0 R /Prev 1146 0 R /Next 1152 0 R >> endobj 1146 0 obj << /Title 1147 0 R /A 1145 0 R /Parent 1143 0 R /Next 1149 0 R >> endobj 1143 0 obj << /Title 1144 0 R /A 1142 0 R /Parent 1189 0 R /Prev 1125 0 R /Next 1155 0 R /First 1146 0 R /Last 1152 0 R /Count -3 >> endobj 1140 0 obj << /Title 1141 0 R /A 1139 0 R /Parent 1125 0 R /Prev 1137 0 R >> endobj 1137 0 obj << /Title 1138 0 R /A 1136 0 R /Parent 1125 0 R /Prev 1134 0 R /Next 1140 0 R >> endobj 1134 0 obj << /Title 1135 0 R /A 1133 0 R /Parent 1125 0 R /Prev 1131 0 R /Next 1137 0 R >> endobj 1131 0 obj << /Title 1132 0 R /A 1130 0 R /Parent 1125 0 R /Prev 1128 0 R /Next 1134 0 R >> endobj 1128 0 obj << /Title 1129 0 R /A 1127 0 R /Parent 1125 0 R /Next 1131 0 R >> endobj 1125 0 obj << /Title 1126 0 R /A 1124 0 R /Parent 1189 0 R /Prev 1068 0 R /Next 1143 0 R /First 1128 0 R /Last 1140 0 R /Count -5 >> endobj 1122 0 obj << /Title 1123 0 R /A 1121 0 R /Parent 1068 0 R /Prev 1119 0 R >> endobj 1119 0 obj << /Title 1120 0 R /A 1118 0 R /Parent 1068 0 R /Prev 1116 0 R /Next 1122 0 R >> endobj 1116 0 obj << /Title 1117 0 R /A 1115 0 R /Parent 1068 0 R /Prev 1113 0 R /Next 1119 0 R >> endobj 1113 0 obj << /Title 1114 0 R /A 1112 0 R /Parent 1068 0 R /Prev 1110 0 R /Next 1116 0 R >> endobj 1110 0 obj << /Title 1111 0 R /A 1109 0 R /Parent 1068 0 R /Prev 1095 0 R /Next 1113 0 R >> endobj 1107 0 obj << /Title 1108 0 R /A 1106 0 R /Parent 1095 0 R /Prev 1104 0 R >> endobj 1104 0 obj << /Title 1105 0 R /A 1103 0 R /Parent 1095 0 R /Prev 1101 0 R /Next 1107 0 R >> endobj 1101 0 obj << /Title 1102 0 R /A 1100 0 R /Parent 1095 0 R /Prev 1098 0 R /Next 1104 0 R >> endobj 1098 0 obj << /Title 1099 0 R /A 1097 0 R /Parent 1095 0 R /Next 1101 0 R >> endobj 1095 0 obj << /Title 1096 0 R /A 1094 0 R /Parent 1068 0 R /Prev 1092 0 R /Next 1110 0 R /First 1098 0 R /Last 1107 0 R /Count -4 >> endobj 1092 0 obj << /Title 1093 0 R /A 1091 0 R /Parent 1068 0 R /Prev 1089 0 R /Next 1095 0 R >> endobj 1089 0 obj << /Title 1090 0 R /A 1088 0 R /Parent 1068 0 R /Prev 1086 0 R /Next 1092 0 R >> endobj 1086 0 obj << /Title 1087 0 R /A 1085 0 R /Parent 1068 0 R /Prev 1083 0 R /Next 1089 0 R >> endobj 1083 0 obj << /Title 1084 0 R /A 1082 0 R /Parent 1068 0 R /Prev 1080 0 R /Next 1086 0 R >> endobj 1080 0 obj << /Title 1081 0 R /A 1079 0 R /Parent 1068 0 R /Prev 1077 0 R /Next 1083 0 R >> endobj 1077 0 obj << /Title 1078 0 R /A 1076 0 R /Parent 1068 0 R /Prev 1074 0 R /Next 1080 0 R >> endobj 1074 0 obj << /Title 1075 0 R /A 1073 0 R /Parent 1068 0 R /Prev 1071 0 R /Next 1077 0 R >> endobj 1071 0 obj << /Title 1072 0 R /A 1070 0 R /Parent 1068 0 R /Next 1074 0 R >> endobj 1068 0 obj << /Title 1069 0 R /A 1067 0 R /Parent 1189 0 R /Prev 1044 0 R /Next 1125 0 R /First 1071 0 R /Last 1122 0 R /Count -14 >> endobj 1065 0 obj << /Title 1066 0 R /A 1064 0 R /Parent 1044 0 R /Prev 1062 0 R >> endobj 1062 0 obj << /Title 1063 0 R /A 1061 0 R /Parent 1044 0 R /Prev 1053 0 R /Next 1065 0 R >> endobj 1059 0 obj << /Title 1060 0 R /A 1058 0 R /Parent 1053 0 R /Prev 1056 0 R >> endobj 1056 0 obj << /Title 1057 0 R /A 1055 0 R /Parent 1053 0 R /Next 1059 0 R >> endobj 1053 0 obj << /Title 1054 0 R /A 1052 0 R /Parent 1044 0 R /Prev 1050 0 R /Next 1062 0 R /First 1056 0 R /Last 1059 0 R /Count -2 >> endobj 1050 0 obj << /Title 1051 0 R /A 1049 0 R /Parent 1044 0 R /Prev 1047 0 R /Next 1053 0 R >> endobj 1047 0 obj << /Title 1048 0 R /A 1046 0 R /Parent 1044 0 R /Next 1050 0 R >> endobj 1044 0 obj << /Title 1045 0 R /A 1043 0 R /Parent 1189 0 R /Prev 1041 0 R /Next 1068 0 R /First 1047 0 R /Last 1065 0 R /Count -5 >> endobj 1041 0 obj << /Title 1042 0 R /A 1040 0 R /Parent 1189 0 R /Prev 1038 0 R /Next 1044 0 R >> endobj 1038 0 obj << /Title 1039 0 R /A 1037 0 R /Parent 1189 0 R /Next 1041 0 R >> endobj 1190 0 obj << /Names [(-1) 988 0 R (-2) 1030 0 R (1) 17 0 R (10) 108 0 R (11) 117 0 R (12) 127 0 R (13) 136 0 R (14) 140 0 R (15) 144 0 R (16) 152 0 R (17) 167 0 R (18) 173 0 R (19) 181 0 R (2) 33 0 R (20) 188 0 R (21) 196 0 R (22) 201 0 R (23) 210 0 R (24) 217 0 R (25) 222 0 R (26) 231 0 R (27) 241 0 R (28) 249 0 R (29) 256 0 R (3) 37 0 R (30) 269 0 R (31) 276 0 R (32) 280 0 R (33) 287 0 R (34) 293 0 R (35) 300 0 R (36) 308 0 R (37) 315 0 R (38) 322 0 R (39) 328 0 R (4) 42 0 R (40) 332 0 R (41) 340 0 R (42) 349 0 R (43) 354 0 R (44) 364 0 R (45) 374 0 R (46) 379 0 R (47) 383 0 R (48) 391 0 R (49) 395 0 R (5) 46 0 R (50) 408 0 R (51) 414 0 R (52) 501 0 R (53) 624 0 R (54) 738 0 R (55) 849 0 R (56) 963 0 R (6) 63 0 R (7) 74 0 R (8) 87 0 R (9) 100 0 R (Allocation Basics) 92 0 R (Allocation Macros) 82 0 R (Argument Checking) 83 0 R (Basic Definitions) 93 0 R (Compatibility) 386 0 R (Copying) 38 0 R (Debug Tokens) 132 0 R (Debugging A Server) 177 0 R (Definitions) 385 0 R (Disabling the Library) 162 0 R (Dmalloc Program) 95 0 R (Dumping Core) 94 0 R (Environment Variable) 206 0 R (Error Codes) 192 0 R (Extensions) 168 0 R (Features) 109 0 R (Fence-Post Overruns) 122 0 R (General Errors) 232 0 R (Getting Started) 68 0 R (How It Works) 129 0 R (Index of Concepts) 415 0 R (Installation) 48 0 R (Logfile Details) 283 0 R (Malloc Functions) 101 0 R (Memory Leaks) 123 0 R (Other Hints) 296 0 R (Overview) 47 0 R (Portability) 59 0 R (Programming) 145 0 R (RC File) 96 0 R (Return Address) 113 0 R (Shell Alias) 302 0 R (Source Code) 384 0 R (Top) 18 0 R (Translate Return Addresses) 161 0 R (Troubleshooting) 396 0 R (Using With C++) 223 0 R (Using With Cygwin) 262 0 R (Using With Threads) 29 0 R (Using With a Debugger) 163 0 R (Utility Usage) 309 0 R] /Limits [(-1) (Utility Usage)] >> endobj 1191 0 obj << /Kids [1190 0 R] >> endobj 1192 0 obj << /Dests 1191 0 R >> endobj 1193 0 obj << /Type /Catalog /Pages 1188 0 R /Outlines 1189 0 R /Names 1192 0 R /PageMode /UseOutlines >> endobj 1194 0 obj << /Producer (pdfeTeX-1.21a) /Creator (TeX) /CreationDate (D:20070514132458-04'00') /PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4) >> endobj xref 0 1195 0000000000 65535 f 0000000489 00000 n 0000000384 00000 n 0000000009 00000 n 0000395576 00000 n 0000379237 00000 n 0000395417 00000 n 0000378137 00000 n 0000366424 00000 n 0000377977 00000 n 0000397038 00000 n 0000001721 00000 n 0000001613 00000 n 0000000568 00000 n 0000004796 00000 n 0000003940 00000 n 0000001790 00000 n 0000004694 00000 n 0000004745 00000 n 0000365537 00000 n 0000356466 00000 n 0000365375 00000 n 0000354929 00000 n 0000339418 00000 n 0000354767 00000 n 0000004088 00000 n 0000004234 00000 n 0000004386 00000 n 0000004540 00000 n 0000099934 00000 n 0000005261 00000 n 0000005102 00000 n 0000004900 00000 n 0000005210 00000 n 0000006507 00000 n 0000006297 00000 n 0000005330 00000 n 0000006405 00000 n 0000006456 00000 n 0000006948 00000 n 0000006789 00000 n 0000006587 00000 n 0000006897 00000 n 0000011700 00000 n 0000010950 00000 n 0000007017 00000 n 0000011542 00000 n 0000011593 00000 n 0000011644 00000 n 0000011091 00000 n 0000338428 00000 n 0000329962 00000 n 0000338264 00000 n 0000011245 00000 n 0000329005 00000 n 0000320692 00000 n 0000328843 00000 n 0000011397 00000 n 0000397148 00000 n 0000160772 00000 n 0000016986 00000 n 0000015838 00000 n 0000011816 00000 n 0000016880 00000 n 0000016000 00000 n 0000016147 00000 n 0000016293 00000 n 0000016437 00000 n 0000016931 00000 n 0000016580 00000 n 0000016734 00000 n 0000021104 00000 n 0000020310 00000 n 0000017090 00000 n 0000021053 00000 n 0000020458 00000 n 0000020612 00000 n 0000020762 00000 n 0000020908 00000 n 0000320372 00000 n 0000318983 00000 n 0000320211 00000 n 0000046356 00000 n 0000051911 00000 n 0000025223 00000 n 0000024340 00000 n 0000021221 00000 n 0000025061 00000 n 0000024488 00000 n 0000024634 00000 n 0000024778 00000 n 0000024920 00000 n 0000025112 00000 n 0000025167 00000 n 0000051968 00000 n 0000123925 00000 n 0000155710 00000 n 0000027871 00000 n 0000027654 00000 n 0000025363 00000 n 0000027762 00000 n 0000027814 00000 n 0000318636 00000 n 0000316636 00000 n 0000318473 00000 n 0000031795 00000 n 0000031099 00000 n 0000028000 00000 n 0000031685 00000 n 0000031738 00000 n 0000031246 00000 n 0000031393 00000 n 0000031539 00000 n 0000046413 00000 n 0000035587 00000 n 0000034949 00000 n 0000031937 00000 n 0000035534 00000 n 0000035097 00000 n 0000035251 00000 n 0000035393 00000 n 0000397260 00000 n 0000095361 00000 n 0000090740 00000 n 0000040314 00000 n 0000039611 00000 n 0000035681 00000 n 0000040203 00000 n 0000039759 00000 n 0000040256 00000 n 0000039906 00000 n 0000040053 00000 n 0000144696 00000 n 0000041352 00000 n 0000041187 00000 n 0000040419 00000 n 0000041299 00000 n 0000041801 00000 n 0000041636 00000 n 0000041434 00000 n 0000041748 00000 n 0000046471 00000 n 0000045674 00000 n 0000041871 00000 n 0000046250 00000 n 0000046303 00000 n 0000045822 00000 n 0000045969 00000 n 0000046110 00000 n 0000052025 00000 n 0000050485 00000 n 0000046576 00000 n 0000051858 00000 n 0000050673 00000 n 0000050833 00000 n 0000050980 00000 n 0000051129 00000 n 0000051279 00000 n 0000051421 00000 n 0000051561 00000 n 0000051717 00000 n 0000099876 00000 n 0000081446 00000 n 0000085514 00000 n 0000055160 00000 n 0000054937 00000 n 0000052142 00000 n 0000055049 00000 n 0000055102 00000 n 0000397378 00000 n 0000059106 00000 n 0000058459 00000 n 0000055278 00000 n 0000059053 00000 n 0000058607 00000 n 0000058759 00000 n 0000058906 00000 n 0000108955 00000 n 0000063274 00000 n 0000062625 00000 n 0000059237 00000 n 0000063221 00000 n 0000062773 00000 n 0000062921 00000 n 0000063068 00000 n 0000067687 00000 n 0000066986 00000 n 0000063405 00000 n 0000067577 00000 n 0000067134 00000 n 0000067281 00000 n 0000067428 00000 n 0000067630 00000 n 0000071201 00000 n 0000070863 00000 n 0000067817 00000 n 0000071148 00000 n 0000070995 00000 n 0000075258 00000 n 0000074449 00000 n 0000071295 00000 n 0000075205 00000 n 0000074605 00000 n 0000074755 00000 n 0000074904 00000 n 0000075055 00000 n 0000140727 00000 n 0000078897 00000 n 0000078394 00000 n 0000075352 00000 n 0000078844 00000 n 0000078534 00000 n 0000078689 00000 n 0000397496 00000 n 0000081504 00000 n 0000081109 00000 n 0000078991 00000 n 0000081393 00000 n 0000081241 00000 n 0000085572 00000 n 0000085121 00000 n 0000081621 00000 n 0000085403 00000 n 0000085456 00000 n 0000316326 00000 n 0000314454 00000 n 0000316163 00000 n 0000085253 00000 n 0000090798 00000 n 0000089718 00000 n 0000085714 00000 n 0000090634 00000 n 0000090687 00000 n 0000089882 00000 n 0000090029 00000 n 0000090179 00000 n 0000090323 00000 n 0000090484 00000 n 0000095419 00000 n 0000094597 00000 n 0000090903 00000 n 0000095308 00000 n 0000094753 00000 n 0000094891 00000 n 0000095028 00000 n 0000095169 00000 n 0000099991 00000 n 0000099241 00000 n 0000095536 00000 n 0000099823 00000 n 0000099389 00000 n 0000099530 00000 n 0000099680 00000 n 0000105277 00000 n 0000103960 00000 n 0000100096 00000 n 0000105166 00000 n 0000104140 00000 n 0000104279 00000 n 0000104423 00000 n 0000104563 00000 n 0000104704 00000 n 0000105219 00000 n 0000104854 00000 n 0000105011 00000 n 0000397614 00000 n 0000109013 00000 n 0000108299 00000 n 0000105382 00000 n 0000108902 00000 n 0000108447 00000 n 0000108597 00000 n 0000108747 00000 n 0000111753 00000 n 0000111588 00000 n 0000109118 00000 n 0000111700 00000 n 0000113831 00000 n 0000113294 00000 n 0000111859 00000 n 0000113721 00000 n 0000113434 00000 n 0000113577 00000 n 0000113774 00000 n 0000118123 00000 n 0000117641 00000 n 0000113913 00000 n 0000118070 00000 n 0000117781 00000 n 0000117923 00000 n 0000120752 00000 n 0000120205 00000 n 0000118216 00000 n 0000120646 00000 n 0000120345 00000 n 0000120496 00000 n 0000120699 00000 n 0000124035 00000 n 0000123423 00000 n 0000120845 00000 n 0000123872 00000 n 0000123563 00000 n 0000123977 00000 n 0000123718 00000 n 0000397732 00000 n 0000127997 00000 n 0000127449 00000 n 0000124152 00000 n 0000127891 00000 n 0000127944 00000 n 0000127589 00000 n 0000127729 00000 n 0000131203 00000 n 0000130563 00000 n 0000128114 00000 n 0000131150 00000 n 0000130711 00000 n 0000130858 00000 n 0000131005 00000 n 0000134778 00000 n 0000134290 00000 n 0000131297 00000 n 0000134725 00000 n 0000134430 00000 n 0000134578 00000 n 0000136493 00000 n 0000136328 00000 n 0000134872 00000 n 0000136440 00000 n 0000140785 00000 n 0000139922 00000 n 0000136587 00000 n 0000140674 00000 n 0000140078 00000 n 0000140228 00000 n 0000140375 00000 n 0000140521 00000 n 0000144754 00000 n 0000143913 00000 n 0000140902 00000 n 0000144643 00000 n 0000144069 00000 n 0000144210 00000 n 0000144350 00000 n 0000144504 00000 n 0000397850 00000 n 0000147217 00000 n 0000146884 00000 n 0000144859 00000 n 0000147164 00000 n 0000147016 00000 n 0000151493 00000 n 0000150411 00000 n 0000147311 00000 n 0000151440 00000 n 0000150583 00000 n 0000150724 00000 n 0000150864 00000 n 0000151011 00000 n 0000151152 00000 n 0000151293 00000 n 0000155767 00000 n 0000154603 00000 n 0000151587 00000 n 0000155657 00000 n 0000154775 00000 n 0000154922 00000 n 0000155072 00000 n 0000155221 00000 n 0000155366 00000 n 0000155510 00000 n 0000157102 00000 n 0000156767 00000 n 0000155896 00000 n 0000157049 00000 n 0000156899 00000 n 0000157551 00000 n 0000157386 00000 n 0000157184 00000 n 0000157498 00000 n 0000160829 00000 n 0000160438 00000 n 0000157621 00000 n 0000160550 00000 n 0000160603 00000 n 0000160656 00000 n 0000160714 00000 n 0000397968 00000 n 0000161834 00000 n 0000161669 00000 n 0000160958 00000 n 0000161781 00000 n 0000167205 00000 n 0000165736 00000 n 0000161916 00000 n 0000167099 00000 n 0000167152 00000 n 0000165924 00000 n 0000166079 00000 n 0000166224 00000 n 0000166368 00000 n 0000166510 00000 n 0000166655 00000 n 0000166799 00000 n 0000166954 00000 n 0000169960 00000 n 0000169472 00000 n 0000167310 00000 n 0000169907 00000 n 0000169612 00000 n 0000169760 00000 n 0000184930 00000 n 0000173915 00000 n 0000170054 00000 n 0000184824 00000 n 0000184877 00000 n 0000313216 00000 n 0000299648 00000 n 0000313054 00000 n 0000299328 00000 n 0000297515 00000 n 0000299166 00000 n 0000174647 00000 n 0000174784 00000 n 0000174921 00000 n 0000175058 00000 n 0000175195 00000 n 0000175331 00000 n 0000175467 00000 n 0000175603 00000 n 0000175738 00000 n 0000175875 00000 n 0000176012 00000 n 0000176149 00000 n 0000176286 00000 n 0000176423 00000 n 0000176560 00000 n 0000176697 00000 n 0000176834 00000 n 0000176971 00000 n 0000177108 00000 n 0000177245 00000 n 0000177382 00000 n 0000177519 00000 n 0000177656 00000 n 0000177793 00000 n 0000177930 00000 n 0000178067 00000 n 0000178203 00000 n 0000178340 00000 n 0000178476 00000 n 0000178613 00000 n 0000178750 00000 n 0000178887 00000 n 0000179022 00000 n 0000179154 00000 n 0000179286 00000 n 0000179418 00000 n 0000179550 00000 n 0000179682 00000 n 0000179814 00000 n 0000179946 00000 n 0000180078 00000 n 0000180210 00000 n 0000180342 00000 n 0000180474 00000 n 0000180606 00000 n 0000180738 00000 n 0000180870 00000 n 0000181001 00000 n 0000181136 00000 n 0000181268 00000 n 0000181400 00000 n 0000181531 00000 n 0000181662 00000 n 0000181794 00000 n 0000181926 00000 n 0000182058 00000 n 0000182190 00000 n 0000182326 00000 n 0000182458 00000 n 0000182590 00000 n 0000182722 00000 n 0000182853 00000 n 0000182985 00000 n 0000183117 00000 n 0000183248 00000 n 0000183380 00000 n 0000183510 00000 n 0000183641 00000 n 0000183772 00000 n 0000183904 00000 n 0000184036 00000 n 0000184168 00000 n 0000184300 00000 n 0000184434 00000 n 0000184565 00000 n 0000184695 00000 n 0000208146 00000 n 0000191465 00000 n 0000185036 00000 n 0000208093 00000 n 0000192517 00000 n 0000192653 00000 n 0000192789 00000 n 0000192926 00000 n 0000193063 00000 n 0000193200 00000 n 0000193337 00000 n 0000193473 00000 n 0000297206 00000 n 0000295354 00000 n 0000297044 00000 n 0000193610 00000 n 0000193747 00000 n 0000193884 00000 n 0000194021 00000 n 0000194158 00000 n 0000194295 00000 n 0000194432 00000 n 0000194569 00000 n 0000194705 00000 n 0000194842 00000 n 0000194979 00000 n 0000195116 00000 n 0000195253 00000 n 0000195389 00000 n 0000195526 00000 n 0000195663 00000 n 0000195800 00000 n 0000195937 00000 n 0000196074 00000 n 0000196210 00000 n 0000196347 00000 n 0000196484 00000 n 0000196621 00000 n 0000196757 00000 n 0000196894 00000 n 0000197031 00000 n 0000197168 00000 n 0000197303 00000 n 0000197439 00000 n 0000197576 00000 n 0000197712 00000 n 0000197848 00000 n 0000197985 00000 n 0000198121 00000 n 0000198258 00000 n 0000198395 00000 n 0000198532 00000 n 0000198669 00000 n 0000198805 00000 n 0000198942 00000 n 0000199079 00000 n 0000199216 00000 n 0000199353 00000 n 0000199489 00000 n 0000199626 00000 n 0000199763 00000 n 0000199900 00000 n 0000200037 00000 n 0000200174 00000 n 0000200308 00000 n 0000200443 00000 n 0000200574 00000 n 0000200706 00000 n 0000200838 00000 n 0000200969 00000 n 0000201101 00000 n 0000201233 00000 n 0000201365 00000 n 0000201497 00000 n 0000201629 00000 n 0000201761 00000 n 0000201892 00000 n 0000202024 00000 n 0000202156 00000 n 0000202287 00000 n 0000202419 00000 n 0000202551 00000 n 0000202682 00000 n 0000202814 00000 n 0000202946 00000 n 0000203078 00000 n 0000203210 00000 n 0000203342 00000 n 0000203474 00000 n 0000203606 00000 n 0000203738 00000 n 0000203870 00000 n 0000204002 00000 n 0000204133 00000 n 0000204265 00000 n 0000204396 00000 n 0000204528 00000 n 0000204660 00000 n 0000204792 00000 n 0000204924 00000 n 0000205056 00000 n 0000205188 00000 n 0000205320 00000 n 0000205456 00000 n 0000205588 00000 n 0000205720 00000 n 0000205850 00000 n 0000205982 00000 n 0000206113 00000 n 0000206244 00000 n 0000206376 00000 n 0000206507 00000 n 0000206639 00000 n 0000206771 00000 n 0000206903 00000 n 0000207034 00000 n 0000207170 00000 n 0000207306 00000 n 0000207438 00000 n 0000207569 00000 n 0000207701 00000 n 0000207833 00000 n 0000207963 00000 n 0000230306 00000 n 0000214594 00000 n 0000208265 00000 n 0000230253 00000 n 0000215590 00000 n 0000215727 00000 n 0000215864 00000 n 0000216001 00000 n 0000216138 00000 n 0000216275 00000 n 0000216412 00000 n 0000216549 00000 n 0000216686 00000 n 0000216823 00000 n 0000216960 00000 n 0000217097 00000 n 0000217234 00000 n 0000217370 00000 n 0000217507 00000 n 0000217644 00000 n 0000217781 00000 n 0000217917 00000 n 0000218054 00000 n 0000218189 00000 n 0000218326 00000 n 0000218463 00000 n 0000218600 00000 n 0000218737 00000 n 0000218874 00000 n 0000219011 00000 n 0000219148 00000 n 0000219285 00000 n 0000219422 00000 n 0000219559 00000 n 0000219696 00000 n 0000219833 00000 n 0000219970 00000 n 0000220107 00000 n 0000220244 00000 n 0000220381 00000 n 0000220518 00000 n 0000220655 00000 n 0000220792 00000 n 0000220929 00000 n 0000221066 00000 n 0000221203 00000 n 0000221340 00000 n 0000221477 00000 n 0000221614 00000 n 0000221749 00000 n 0000221886 00000 n 0000222023 00000 n 0000222160 00000 n 0000222297 00000 n 0000222434 00000 n 0000222569 00000 n 0000222706 00000 n 0000222843 00000 n 0000222980 00000 n 0000223117 00000 n 0000223254 00000 n 0000223391 00000 n 0000223528 00000 n 0000223664 00000 n 0000223799 00000 n 0000223931 00000 n 0000224063 00000 n 0000224195 00000 n 0000224327 00000 n 0000224457 00000 n 0000224589 00000 n 0000224720 00000 n 0000224852 00000 n 0000224984 00000 n 0000225115 00000 n 0000225246 00000 n 0000225378 00000 n 0000225514 00000 n 0000225646 00000 n 0000225778 00000 n 0000225910 00000 n 0000226042 00000 n 0000226173 00000 n 0000226305 00000 n 0000226437 00000 n 0000226569 00000 n 0000226701 00000 n 0000226832 00000 n 0000226964 00000 n 0000227096 00000 n 0000227228 00000 n 0000227359 00000 n 0000227489 00000 n 0000227621 00000 n 0000227753 00000 n 0000227884 00000 n 0000228016 00000 n 0000228147 00000 n 0000228279 00000 n 0000228411 00000 n 0000228543 00000 n 0000228675 00000 n 0000228807 00000 n 0000228939 00000 n 0000229070 00000 n 0000229202 00000 n 0000229334 00000 n 0000229466 00000 n 0000229598 00000 n 0000229728 00000 n 0000229859 00000 n 0000229993 00000 n 0000230123 00000 n 0000398086 00000 n 0000251737 00000 n 0000236330 00000 n 0000230412 00000 n 0000251684 00000 n 0000237310 00000 n 0000237447 00000 n 0000237584 00000 n 0000237719 00000 n 0000237856 00000 n 0000237993 00000 n 0000238129 00000 n 0000238266 00000 n 0000238403 00000 n 0000238540 00000 n 0000238677 00000 n 0000238814 00000 n 0000238951 00000 n 0000239087 00000 n 0000239224 00000 n 0000239361 00000 n 0000239497 00000 n 0000239634 00000 n 0000239771 00000 n 0000239908 00000 n 0000240045 00000 n 0000240182 00000 n 0000240319 00000 n 0000240454 00000 n 0000240591 00000 n 0000240728 00000 n 0000240864 00000 n 0000241000 00000 n 0000241136 00000 n 0000241273 00000 n 0000241410 00000 n 0000241547 00000 n 0000241684 00000 n 0000241821 00000 n 0000241958 00000 n 0000242094 00000 n 0000242231 00000 n 0000242368 00000 n 0000242505 00000 n 0000242641 00000 n 0000242778 00000 n 0000242915 00000 n 0000243052 00000 n 0000243188 00000 n 0000243325 00000 n 0000243462 00000 n 0000243599 00000 n 0000243736 00000 n 0000243872 00000 n 0000244009 00000 n 0000244146 00000 n 0000244283 00000 n 0000244418 00000 n 0000244553 00000 n 0000244688 00000 n 0000244820 00000 n 0000244951 00000 n 0000245082 00000 n 0000245213 00000 n 0000245343 00000 n 0000245474 00000 n 0000245606 00000 n 0000245738 00000 n 0000245870 00000 n 0000246001 00000 n 0000246132 00000 n 0000246268 00000 n 0000246400 00000 n 0000246536 00000 n 0000246668 00000 n 0000246800 00000 n 0000246931 00000 n 0000247067 00000 n 0000247199 00000 n 0000247330 00000 n 0000247466 00000 n 0000247602 00000 n 0000247738 00000 n 0000247870 00000 n 0000248002 00000 n 0000248134 00000 n 0000248266 00000 n 0000248397 00000 n 0000248528 00000 n 0000248660 00000 n 0000248792 00000 n 0000248924 00000 n 0000249054 00000 n 0000249186 00000 n 0000249318 00000 n 0000249450 00000 n 0000249582 00000 n 0000249713 00000 n 0000249845 00000 n 0000249976 00000 n 0000250108 00000 n 0000250240 00000 n 0000250372 00000 n 0000250504 00000 n 0000250636 00000 n 0000250768 00000 n 0000250899 00000 n 0000251031 00000 n 0000251163 00000 n 0000251293 00000 n 0000251424 00000 n 0000251554 00000 n 0000273646 00000 n 0000257826 00000 n 0000251843 00000 n 0000273593 00000 n 0000258830 00000 n 0000258966 00000 n 0000259103 00000 n 0000259240 00000 n 0000259377 00000 n 0000259513 00000 n 0000259648 00000 n 0000259785 00000 n 0000259922 00000 n 0000260059 00000 n 0000260196 00000 n 0000260333 00000 n 0000260470 00000 n 0000260606 00000 n 0000260743 00000 n 0000260880 00000 n 0000261017 00000 n 0000261153 00000 n 0000261290 00000 n 0000261426 00000 n 0000261563 00000 n 0000261700 00000 n 0000261837 00000 n 0000261974 00000 n 0000262110 00000 n 0000262247 00000 n 0000262383 00000 n 0000262520 00000 n 0000262657 00000 n 0000262792 00000 n 0000262929 00000 n 0000263066 00000 n 0000263202 00000 n 0000263338 00000 n 0000263474 00000 n 0000263611 00000 n 0000263748 00000 n 0000263885 00000 n 0000264021 00000 n 0000264158 00000 n 0000264295 00000 n 0000264432 00000 n 0000264569 00000 n 0000264705 00000 n 0000264841 00000 n 0000264977 00000 n 0000265114 00000 n 0000265251 00000 n 0000265387 00000 n 0000265522 00000 n 0000265659 00000 n 0000265796 00000 n 0000265933 00000 n 0000266069 00000 n 0000266205 00000 n 0000266340 00000 n 0000266474 00000 n 0000266606 00000 n 0000266738 00000 n 0000266870 00000 n 0000267002 00000 n 0000267134 00000 n 0000267266 00000 n 0000267398 00000 n 0000267530 00000 n 0000267662 00000 n 0000267792 00000 n 0000267924 00000 n 0000268056 00000 n 0000268186 00000 n 0000268318 00000 n 0000268450 00000 n 0000268582 00000 n 0000268714 00000 n 0000268845 00000 n 0000268977 00000 n 0000269109 00000 n 0000269241 00000 n 0000269376 00000 n 0000269508 00000 n 0000269640 00000 n 0000269771 00000 n 0000269902 00000 n 0000270034 00000 n 0000270166 00000 n 0000270298 00000 n 0000270430 00000 n 0000270562 00000 n 0000270694 00000 n 0000270826 00000 n 0000270958 00000 n 0000271089 00000 n 0000271221 00000 n 0000271353 00000 n 0000271485 00000 n 0000271617 00000 n 0000271749 00000 n 0000271885 00000 n 0000272017 00000 n 0000272148 00000 n 0000272280 00000 n 0000272412 00000 n 0000272544 00000 n 0000272676 00000 n 0000272808 00000 n 0000272939 00000 n 0000273071 00000 n 0000273203 00000 n 0000273334 00000 n 0000273463 00000 n 0000278513 00000 n 0000275342 00000 n 0000273752 00000 n 0000278460 00000 n 0000275634 00000 n 0000275769 00000 n 0000275906 00000 n 0000276043 00000 n 0000276180 00000 n 0000276317 00000 n 0000276453 00000 n 0000276590 00000 n 0000276727 00000 n 0000276864 00000 n 0000277001 00000 n 0000277138 00000 n 0000277274 00000 n 0000277405 00000 n 0000277537 00000 n 0000277669 00000 n 0000277801 00000 n 0000277933 00000 n 0000278064 00000 n 0000278198 00000 n 0000278329 00000 n 0000286713 00000 n 0000281599 00000 n 0000278619 00000 n 0000286660 00000 n 0000295030 00000 n 0000293217 00000 n 0000294865 00000 n 0000282030 00000 n 0000282160 00000 n 0000282291 00000 n 0000282421 00000 n 0000282552 00000 n 0000282683 00000 n 0000282814 00000 n 0000282945 00000 n 0000283076 00000 n 0000283208 00000 n 0000283341 00000 n 0000283474 00000 n 0000283607 00000 n 0000283740 00000 n 0000283873 00000 n 0000284006 00000 n 0000284139 00000 n 0000284272 00000 n 0000284404 00000 n 0000284537 00000 n 0000284670 00000 n 0000284801 00000 n 0000284934 00000 n 0000285067 00000 n 0000285198 00000 n 0000285331 00000 n 0000285464 00000 n 0000285597 00000 n 0000285730 00000 n 0000285863 00000 n 0000285996 00000 n 0000286129 00000 n 0000286262 00000 n 0000286395 00000 n 0000286528 00000 n 0000288662 00000 n 0000287634 00000 n 0000286831 00000 n 0000288607 00000 n 0000287815 00000 n 0000287943 00000 n 0000288075 00000 n 0000288208 00000 n 0000288341 00000 n 0000288474 00000 n 0000288769 00000 n 0000402592 00000 n 0000288811 00000 n 0000288852 00000 n 0000402493 00000 n 0000288898 00000 n 0000288959 00000 n 0000402353 00000 n 0000289006 00000 n 0000289073 00000 n 0000402269 00000 n 0000289124 00000 n 0000289171 00000 n 0000402170 00000 n 0000289225 00000 n 0000289278 00000 n 0000402030 00000 n 0000289334 00000 n 0000289395 00000 n 0000401946 00000 n 0000289451 00000 n 0000289505 00000 n 0000401862 00000 n 0000289560 00000 n 0000289628 00000 n 0000401763 00000 n 0000289675 00000 n 0000289727 00000 n 0000401679 00000 n 0000289778 00000 n 0000289834 00000 n 0000401538 00000 n 0000289884 00000 n 0000289936 00000 n 0000401454 00000 n 0000289992 00000 n 0000290055 00000 n 0000401355 00000 n 0000290108 00000 n 0000290163 00000 n 0000401256 00000 n 0000290219 00000 n 0000290270 00000 n 0000401157 00000 n 0000290321 00000 n 0000290374 00000 n 0000401058 00000 n 0000290423 00000 n 0000290476 00000 n 0000400959 00000 n 0000290526 00000 n 0000290586 00000 n 0000400860 00000 n 0000290646 00000 n 0000290693 00000 n 0000400761 00000 n 0000290746 00000 n 0000290793 00000 n 0000400621 00000 n 0000290853 00000 n 0000290903 00000 n 0000400537 00000 n 0000290956 00000 n 0000291020 00000 n 0000400438 00000 n 0000291071 00000 n 0000291122 00000 n 0000400339 00000 n 0000291180 00000 n 0000291241 00000 n 0000400255 00000 n 0000291306 00000 n 0000291375 00000 n 0000400156 00000 n 0000291432 00000 n 0000291492 00000 n 0000400057 00000 n 0000291548 00000 n 0000291611 00000 n 0000399958 00000 n 0000291668 00000 n 0000291736 00000 n 0000399859 00000 n 0000291790 00000 n 0000291844 00000 n 0000399775 00000 n 0000291894 00000 n 0000291948 00000 n 0000399635 00000 n 0000292002 00000 n 0000292046 00000 n 0000399551 00000 n 0000292096 00000 n 0000292153 00000 n 0000399452 00000 n 0000292205 00000 n 0000292256 00000 n 0000399353 00000 n 0000292315 00000 n 0000292374 00000 n 0000399254 00000 n 0000292425 00000 n 0000292481 00000 n 0000399170 00000 n 0000292527 00000 n 0000292588 00000 n 0000399030 00000 n 0000292638 00000 n 0000292689 00000 n 0000398946 00000 n 0000292739 00000 n 0000292801 00000 n 0000398847 00000 n 0000292853 00000 n 0000292904 00000 n 0000398763 00000 n 0000292954 00000 n 0000293015 00000 n 0000398664 00000 n 0000293069 00000 n 0000293123 00000 n 0000398580 00000 n 0000293179 00000 n 0000295266 00000 n 0000295241 00000 n 0000297429 00000 n 0000297404 00000 n 0000299560 00000 n 0000299535 00000 n 0000314030 00000 n 0000313640 00000 n 0000316550 00000 n 0000316525 00000 n 0000318881 00000 n 0000318852 00000 n 0000320604 00000 n 0000320579 00000 n 0000329576 00000 n 0000329275 00000 n 0000339028 00000 n 0000338763 00000 n 0000355899 00000 n 0000355518 00000 n 0000366088 00000 n 0000365829 00000 n 0000378868 00000 n 0000378501 00000 n 0000396496 00000 n 0000396088 00000 n 0000398205 00000 n 0000398323 00000 n 0000398427 00000 n 0000398500 00000 n 0000402676 00000 n 0000404484 00000 n 0000404525 00000 n 0000404565 00000 n 0000404678 00000 n trailer << /Size 1195 /Root 1193 0 R /Info 1194 0 R /ID [<256DE069A3A8652F8FFB38D22924A0DE> <256DE069A3A8652F8FFB38D22924A0DE>] >> startxref 404883 %%EOF dmalloc-5.5.2/docs/dmalloc.html000644 001751 001751 00001127500 10622115666 016352 0ustar00graygray000000 000000 Dmalloc Tutorial: Debug Malloc Library
[Top] [Contents] [Index] [ ? ]

Debug Malloc Library

The debug memory allocation or dmalloc library has been designed as a drop in replacement for the system's malloc, realloc, calloc, free and other memory management routines while providing powerful debugging facilities configurable at runtime. These facilities include such things as memory-leak tracking, fence-post write detection, file/line number reporting, and general logging of statistics.

The library is reasonably portable having been run successfully on at least the following operating systems: AIX, DGUX, Free/Net/OpenBSD, GNU/Hurd, HPUX, Irix, Linux, Mac OSX, NeXT, OSF/DUX, SCO, Solaris, Ultrix, Unixware, MS Windows, and Unicos on a Cray T3E. It also provides support for the debugging of threaded programs. See section Using the Library with a Thread Package.

The package includes the library, configuration scripts, debug utility application, test program, and documentation. Online documentation as well as the full source is available at URL http://dmalloc.com/. Details on the library's mailing list are available there as well.

Please use the forums at URL http://dmalloc.com/ to discuss any problems or to request features. If you are still having problems, the author can be reached via his home page at URL http://256.com/gray/ with questions or feedback. Please include the version number of the library that you are using, your machine and operating system types, and the value of the DMALLOC_OPTIONS environment variable.

Gray Watson.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1. Library Copying and Licensing Conditions

Copyright 1992 to 2007 by Gray Watson.

Permission to use, copy, modify, and distribute this software for any purpose and without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies, and that the name of Gray Watson not be used in advertising or publicity pertaining to distribution of the document or software without specific, written prior permission.

Gray Watson makes no representations about the suitability of the software described herein for any purpose. It is provided "as is" without express or implied warranty.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2. Description of Features and How to Get Started


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.1 How to Install the Library

To configure, compile, and install the library, follow these steps carefully.

  1. Make sure you have downloaded the latest version of the library available from the home page at URL http://dmalloc.com/.
  2. The release files have a `.tgz' file extension which means that they are a tar'd gzip'd directory of files. You will need to ungzip and then untar the release file into your source work directory. You may have to rename the file to `.tar.gz' to get some old zip programs to handle the file correctly.
  3. You may want to edit or at least review the settings in `settings.dist' to tune specific features of the library. The `configure' script will copy this file to `settings.h' which is where you should be adding per-architecture settings.
  4. Type sh ./configure to configure the library. You may want to first examine the `config.help' file for some information about configure. You may want to use the --disable-cxx option if you do not want the Makefile to build the C++ version of dmalloc. You may want to use the --enable-threads option to build the threaded version of dmalloc. You may want to use the --enable-shlib option to build the shared versions of the dmalloc libraries. sh ./configure --help lists the available options to configure. Configure should generate the `Makefile' and configuration files automatically.
  5. You may want to examine the `Makefile' and `conf.h' files created by configure to make sure it did its job correctly.
  6. You might want to tune the settings in `settings.h' file to tune the library to the local architecture. This file contains relevant settings if you are using pthreads or another thread library. See section Using the Library with a Thread Package. The `configure' script created this file from the `settings.dist' file. Any permanent changes to these settings should made to the `settings.dist' file. You then can run `config.status' to re-create the `settings.h' file.
  7. The DMALLOC_SIZE variable gets auto-configured in `dmalloc.h.2' but it may not generate correct settings for all systems. You may have to alter the definitions in this file to get things to stop complaining when you go to compile about the size arguments to malloc routines. Comments on this please.
  8. Typing make should be enough to build `libdmalloc.a', and `dmalloc' program. If it does not work, please see if there are any notes in the contrib directory about your system-type. If not and you figure your problem out, please send me some notes so future users can profit from your experiences.

    NOTE: You may experience some errors compiling some of the `return.h' assembly macros which attempt to determine the callers address for logging purposes. See section Issues Important for Porting the Library. You may want to first try disabling any compiler optimization flags. If this doesn't work then you may need to disable the `USE_RETURN_MACROS' variable in the `settings.h' file.

    NOTE: The code is dependent on an ANSI-C compiler. If the configure script gives the `WARNING' that you do not have an ANSI-C compiler, you may still be able to add some sort of option to your compiler to make it ANSI. If there such is an option, please send it to the author so it can be added to the configure script.

  9. If you use threads and did not add the --enable-threads argument to configure, typing make threads should be enough to build `libdmallocth.a' which is the threaded version of the library. This may or may not work depending on the configuration scripts ability to detect your local thread functionality. Feel free to send me mail with improvements.

    See the section of the manual on threads for more information about the operation of the library with your threaded program. See section Using the Library with a Thread Package.

  10. If you have a C++ compiler installed, the library should have automatically built `libdmallocxx.a' which is the C++ version of the library. If it was not done automatically, you can build it by typing make cxx. You should link this library into your C++ programs instead of `libdmalloc.a'. See the `dmallocc.cc' C++ file which contains basic code to overload the new, new[], delete, and delete[] C++ operators. My apologies on the minimal C++ support. I am still living in a mostly C world. Any help improving this interface without sacrificing portability would be appreciated.
  11. Typing make light should build and run the `dmalloc_t' test program through a set of light trials. By default this will execute `dmalloc_t' 5 times - each time will execute 10,000 malloc operations in a very random manner. Anal folks can type make heavy to up the ante. Use dmalloc_t --usage for the list of all `dmalloc_t' options.
  12. Typing make install should install the `libdmalloc.a' library in `/usr/local/lib', the `dmalloc.h' include file in `/usr/local/include', and the `dmalloc' utility in `/usr/local/bin'. You may also want to type make installth to install the thread library into place and/or make installcc to install the C++ library into place.

    You may have specified a `--prefix=PATH' option to configure in which case `/usr/local' will have been replaced with `PATH'.

See the "Getting Started" section to get up and running with the library. See section Getting Started with the Library.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.2 Getting Started with the Library

This section should give you a quick idea on how to get going. Basically, you need to do the following things to make use of the library:

  1. Make sure you have downloaded the latest version of the library available from the home page at URL http://dmalloc.com/.
  2. Follow the installation instructions on how to configure, make, and install the library (i.e. type: make install). See section How to Install the Library.
  3. You need to make sure that the library configuration and build process above was able to locate one of the on_exit function, atexit function, or had compiler destructor support. If one of these functions or support is available then the dmalloc library should be able to automatically shut itself down when the program exits. This causes the memory statistics and unfreed information to be dumped to the log file. However, if your system has none of the above, then you will need to call dmalloc_shutdown yourself before your program exits.
  4. To get the dmalloc utility to work you need to add an alias for dmalloc to your shell's runtime configuration file if supported. The idea is to have the shell capture the dmalloc program's output and adjust the environment.

    After you add the alias to the shell config file you need to log out and log back in to have it take effect, or you can execute the appropriate command below on the command line directly. After you setup the alias, if you enter dmalloc runtime and see any output with DMALLOC_OPTIONS in it then the alias did not take effect.

    Bash, ksh, and zsh (http://www.zsh.org/) users should add the following to their `.bashrc', `.profile', or `.zshrc' file respectively (notice the -b option for bourne shell output):

     
    function dmalloc { eval `command dmalloc -b $*`; }
    

    If your shell does not support the command function then try:

     
    function dmalloc { eval `\dmalloc -b $*`; }
    

    or

     
    function dmalloc { eval `/usr/local/bin/dmalloc -b $*`; }
    

    If you are still using csh or tcsh, you should add the following to your `.cshrc' file (notice the -C option for c-shell output):

     
    alias dmalloc 'eval `\dmalloc -C \!*`'
    

    If you are using rc shell, you should add the following to your `.rcrc' file (notice the -R option for rc-shell output):

     
    fn dmalloc {eval `{/usr/local/bin/dmalloc $*}}
    
  5. Although not necessary, you may want to include `dmalloc.h' in your C files and recompile. This will allow the library to report the file/line numbers of calls that generate problems. See section Macros Providing File and Line Information. It should be inserted at the bottom of your include files as to not conflict with wother includes. You may want to ifdef it as well and compile with cc -DDMALLOC …:
     
    /* other includes above ^^^ */
    
    #ifdef DMALLOC
    #include "dmalloc.h"
    #endif
    
  6. Another optional task is to compile all of your source with the `dmalloc.h' with the DMALLOC_FUNC_CHECK compilation flag. This willallow the library to check all of the arguments of a number of common string and utility routines. See section Checking of Function Arguments.
     
    cc -DDMALLOC -DDMALLOC_FUNC_CHECK file.c
    
  7. Link the dmalloc library into your program. The dmalloc library should probably be placed at or near the end of the library list.
  8. Enable the debugging features by typing dmalloc -l logfile -i 100 low (for example). You should not see any messages printed by the dmalloc utility (see NOTE below). This will:
    • Set the malloc logfile name to `logfile' (-l logfile). For programs which change directories, you may want to specify the full path to your logfile.
    • Have the library check itself every 100 iterations (-i 100). This controls how fast your program will run. Larger numbers check the heap less and so it will run faster. Lower numbers will be more likely to catch memory problems.
    • Enable a number of debug features (low). You can also try runtime for minimal checking or medium or high for more extensive heap verification.
    • By default, the low, medium, and high values enable the error-abort token which will cause the library to abort and usually dump core immediately upon seeing an error. See section Generating a Core File on Errors. You can disable this feature by entering dmalloc -m error-abort (-m for minus) to remove the error-abort token and your program will just log errors and continue.

    dmalloc --usage will provide verbose usage info for the dmalloc program. See section Dmalloc Utility Program.

    You may also want to install the `dmallocrc' file in your home directory as `.dmallocrc'. This allows you to add your own combination of debug tokens. See section Format of the Runtime Configuration File.

    NOTE: The output from the dmalloc utility should be captured by your shell. If you see a bunch of stuff which includes the string DMALLOC_OPTIONS then the alias you should have created above is not working and he environmental variables are not being set. Make sure you've logged out and back in to have the alias take effect.

  9. Run your program, examine the logfile that should have been created by dmalloc_shutdown, and use its information to help debug your program.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3 Basic Description of Terms and Functions


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.1 General Memory Terms and Concepts

Any program can be divided into 2 logical parts: text and data. Text is the actual program code in machine-readable format and data is the information that the text operates on when it is executing. The data, in turn, can be divided into 3 logical parts according to where it is stored: static, stack, and heap.

Static data is the information whose storage space is compiled into the program.

 
/* global variables are allocated as static data */
int numbers[10];

main()
{
        …
}

Stack data is data allocated at runtime to hold information used inside of functions. This data is managed by the system in the space called stack space.

 
void foo()
{
        /* this local variable is stored on the stack */
        float total;
        …
}

main()
{
        foo();
}

Heap data is also allocated at runtime and provides a programmer with dynamic memory capabilities.

 
main()
{
        /* the address is stored on the stack */
        char * string;
        …

        /*
         * Allocate a string of 10 bytes on the heap.  Store the
         * address in string which is on the stack.
         */
        string = (char *)malloc(10);
        …

        /* de-allocate the heap memory now that we're done with it */
        (void)free(string);
        …
}

It is the heap data that is managed by this library.

Although the above is an example of how to use the malloc and free commands, it is not a good example of why using the heap for runtime storage is useful.

Consider this: You write a program that reads a file into memory, processes it, and displays results. You would like to handle files with arbitrary size (from 10 bytes to 1.2 megabytes and more). One problem, however, is that the entire file must be in memory at one time to do the calculations. You don't want to have to allocate 1.2 megabytes when you might only be reading in a 10 byte file because it is wasteful of system resources. Also, you are worried that your program might have to handle files of more than 1.2 megabytes.

A solution: first check out the file's size and then, using the heap-allocation routines, get enough storage to read the entire file into memory. The program will only be using the system resources necessary for the job and you will be guaranteed that your program can handle any sized file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3.2 Functionality Supported by All Malloc Libraries

All malloc libraries support 4 basic memory allocation commands. These include malloc, calloc, realloc, and free. For more information about their capabilities, check your system's manual pages - in unix, do a man 3 malloc.

Function: void *malloc ( unsigned int size )

Usage: pnt = (type *)malloc(size)

The malloc routine is the basic memory allocation routine. It allocates an area of size bytes. It will return a pointer to the space requested.

Function: void *calloc ( unsigned int number, unsigned intsize )

Usage: pnt = (type *)calloc(number, size)

The calloc routine allocates a certain number of items, each of size bytes, and returns a pointer to the space. It is appropriate to pass in a sizeof(type) value as the size argument.

Also, calloc nulls the space that it returns, assuring that the memory is all zeros.

Function: void *realloc ( void *old_pnt, unsigned int new_size )

Usage: new_pnt = (type *)realloc(old_pnt, new_size)

The realloc function expands or shrinks the memory allocation in old_pnt to new_size number of bytes. Realloc copies as much of the information from old_pnt as it can into the new_pnt space it returns, up to new_size bytes. If there is a problem allocating this memory, 0L will be returned.

If the old_pnt is 0L then realloc will do the equivalent of a malloc(new_size). If new_size is 0 and old_pnt is not 0L, then it will do the equivalent of free(old_pnt) and will return 0L.

Function: void free ( void *pnt )

Usage: free(pnt)

The free routine releases allocation in pnt which was returned by malloc, calloc, or realloc back to the heap. This allows other parts of the program to re-use memory that is not needed anymore. It guarantees that the process does not grow too big and swallow a large portion of the system resources.

WARNING: there is a quite common myth that all of the space that is returned by malloc libraries has already been cleared. Only the calloc routine will zero the memory space it returns.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4 General Features of the Library

The debugging features that are available in this debug malloc library can be divided into a couple basic classifications:

file and line number information

One of the nice things about a good debugger is its ability to provide the file and line number of an offending piece of code. This library attempts to give this functionality with the help of cpp, the C preprocessor. See section Macros Providing File and Line Information.

return-address information

To debug calls to the library from external sources (i.e. those files that could not use the allocation macros), some facilities have been provided to supply the caller's address. This address, with the help of a debugger, can help you locate the source of a problem. See section Getting Caller Address Information.

fence-post (i.e. bounds) checking

Fence-post memory is the area immediately above or below memory allocations. It is all too easy to write code that accesses above or below an allocation - especially when dealing with arrays or strings. The library can write special values in the areas around every allocation so it will notice when these areas have been overwritten. See section Diagnosing Fence-Post Overwritten Memory.

NOTE: The library cannot notice when the program reads from these areas, only when it writes values. Also, fence-post checking will increase the amount of memory the program allocates.

heap-constancy verification

The administration of the library is reasonably complex. If any of the heap-maintenance information is corrupted, the program will either crash or give unpredictable results.

By enabling heap-consistency checking, the library will run through its administrative structures to make sure all is in order. This will mean that problems will be caught faster and diagnosed better.

The drawback of this is, of course, that the library often takes quite a long time to do this. It is suitable to enable this only during development and debugging sessions.

NOTE: the heap checking routines cannot guarantee that the tests will not cause a segmentation-fault if the heap administration structures are properly (or improperly if you will) overwritten. In other words, the tests will verify that everything is okay but may not inform the user of problems in a graceful manner.

logging statistics

One of the reasons why the debug malloc library was initially developed was to track programs' memory usage - specifically to locate memory leaks which are places where allocated memory is never getting freed. See section Tracking Down Non-Freed Memory.

The library has a number of logging capabilities that can track un-freed memory pointers as well as runtime memory usage, memory transactions, administrative actions, and final statistics.

examining freed memory

Another common problem happens when a program frees a memory pointer but goes on to use it again by mistake. This can lead to mysterious crashes and unexplained problems.

To combat this, the library can write special values into a block of memory after it has been freed. This serves two purposes: it will make sure that the program will get garbage data if it trying to access the area again, and it will allow the library to verify the area later for signs of overwriting.

If any of the above debugging features detect an error, the library will try to recover. If logging is enabled then an error will be logged with as much information as possible.

The error messages that the library displays are designed to give the most information for developers. If the error message is not understood, then it is most likely just trying to indicate that a part of the heap has been corrupted.

The library can be configured to quit immediately when an error is detected and to dump a core file or memory-image. This can be examined with a debugger to determine the source of the problem. The library can either stop after dumping core or continue running. See section Generating a Core File on Errors.

NOTE: do not be surprised if the library catches problems with your system's routines. It took me hours to finally come to the conclusion that the localtime call, included in SunOS release 4.1, overwrites one of its fence-post markers.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5 How the Library Checks Your Program

This is one of the newer sections of the library implying that it is incomplete. If you have any questions or issues that you'd like to see handled here, please let me know.

The dmalloc library replaces the heap library calls normally found in your system libraries with its own versions. When you make a call to malloc (for example), you are calling dmalloc's version of the memory allocation function. When you allocate memory with these functions, the dmalloc library keeps track of a number of pieces of debugging information about your pointer including: where it was allocated, exactly how much memory was requested, when the call was made, etc.. This information can then be verified when the pointer is freed or reallocated and the details can be logged on any errors.

Whenever you reallocate or free a memory address, the dmalloc library always performs a number of checks on the pointer to make sure that it is valid and has not been corrupted. You can configure the library to perform additional checks such as detected fence-post writing. The library can also be configured to overwrite memory with non-zeros (only if calloc is not called) when it is allocated and erase the memory when the pointers are freed.

In addition to per-pointer checks, you can configure the library to perform complete heap checks. These complete checks verify all internal heap structures and include walking all of the known allocated pointers to verify each one in turn. You need this level of checking to find random pointers in your program which got corrupted but that won't be freed for a while. To turn on these checks, you will need to enable the check-heap debug token. See section Description of the Debugging Tokens. By default this will cause the heap to be fully checked each and every time dmalloc is called whether it is a malloc, free, realloc, or another dmalloc overloaded function.

Performing a full heap check can take a good bit of CPU and it may be that you will want to run it sporadically. This can be accomplished in a couple different ways including the '-i' interval argument to the dmalloc utility. See section Dmalloc Utility Program. This will cause the check to be run every N-th time. For instance, 'dmalloc -i 3' will cause the heap to be checked before every 3rd call to a memory function. Values of 100 or even 1000 for high memory usage programs are more useful than smaller ones.

You can also cause the program to start doing detailed heap checking after a certain point. For instance, with 'dmalloc -s 1000' option, you can tell the dmalloc library to enable the heap checks after the 1000th memory call. Examine the dmalloc log file produced and use the iteration count if you have LOG_ITERATION_COUNT enabled in your `settings.h' file.

The start option can also have the format `file:line'. For instance, if it is set to `dmalloc_t.c:126', dmalloc will start checking the heap after it sees a dmalloc call from the `dmalloc_t.c' file, line number 126. If you use `dmalloc_t.c:0', with a 0 line number, then dmalloc will start checking the heap after it sees a call from anywhere in the `dmalloc_t.c' file.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3. How to Program with the Library


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1 Macros Providing File and Line Information

By including `dmalloc.h' in your C files, your calls to malloc, calloc, realloc, recalloc, memalign, valloc, strdup, and free are replaced with calls to _dmalloc_malloc, _dmalloc_realloc, and _dmalloc_free with various flags. Additionally the library replaces calls to xmalloc, xcalloc, xrealloc, xrecalloc, xmemalign, xvalloc, xstrdup, and xfree with associated calls.

These macros use the c-preprocessor __FILE__ and __LINE__ macros which get replaced at compilation time with the current file and line-number of the source code in question. The routines use this information to produce verbose reports on memory problems.

 
not freed: '0x38410' (22 bytes) from 'dmalloc_t.c:92'

This line from a log file shows that memory was not freed from file `dmalloc_t.c' line 92. See section Tracking Down Non-Freed Memory.

You may notice some non standard memory allocation functions in the above list. Recalloc is a routine like realloc that reallocates previously allocated memory to a new size. If the new memory size is larger than the old, recalloc initializes the new space to all zeros. This may or may not be supported natively by your operating system. Memalign is like malloc but should insure that the returned pointer is aligned to a certain number of specified bytes. Currently, the memalign function is not supported by the library. It defaults to returning possibly non-aligned memory for alignment values less than a block-size. Valloc is like malloc but insures that the returned pointer will be aligned to a page boundary. This may or may not be supported natively by your operating system but is fully supported by the library. Strdup is a string duplicating routine which takes in a null terminated string pointer and returns an allocated copy of the string that will need to be passed to free later to deallocate.

The X versions of the standard memory functions (xmalloc, xfree, etc.) will print out an error message to standard error and will stop if the library is unable to allocate any additional memory. It is useful to use these routines instead of checking everywhere in your program for allocation routines returning NULL pointers.

WARNING: If you are including the `dmalloc.h' file in your sources, it is recommended that it be at the end of your include file list because dmalloc uses macros and may try to change declarations of the malloc functions if they come after it.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2 Getting Caller Address Information

Even though the allocation macros can provide file/line information for some of your code, there are still modules which either you can't include `dmalloc.h' (such as library routines) or you just don't want to. You can still get information about the routines that call dmalloc function from the return-address information. To accomplish this, you must be using this library on one of the supported architecture/compilers. See section Issues Important for Porting the Library.

The library attempts to use some assembly hacks to get the return-address or the address of the line that called the dmalloc function. If you have unfreed memory that does not have associated file and line information, you might see the following non-freed memory messages.

 
not freed: '0x38410' (22 bytes) from 'ra=0xdd2c'
not freed: '0x38600' (10232 bytes) from 'ra=0x10234d'
not freed: '0x38220' (137 bytes) from 'ra=0x82cc'

With the help of a debugger, these return-addresses (or ra) can then be identified. I've provided a `ra_info.pl' perl script in the `contrib/' directory with the dmalloc sources which seems to work well with gdb. You can also use manual methods for gdb to find the return-address location. See section Translating Return Addresses into Code Locations.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3 Checking of Function Arguments

One potential problem with the library and its multitude of checks and diagnoses is that they only get performed when a dmalloc function is called. One solution this is to include `dmalloc.h' and compile your source code with the DMALLOC_FUNC_CHECK flag defined and enable the check-funcs token. See section Description of the Debugging Tokens.

 
cc -DDMALLOC -DDMALLOC_FUNC_CHECK file.c

NOTE: Once you have compiled your source with DMALLOC_FUNC_CHECK enabled, you will have to recompile with it off to disconnect the library. See section How to Disable the library.

WARNING: You should be sure to have `dmalloc.h' included at the end of your include file list because dmalloc uses macros and may try to change declarations of the checked functions if they come after it.

When this is defined dmalloc will override a number of functions and will insert a routine which knows how to check its own arguments and then call the real function. Dmalloc can check such functions as bcopy, index, strcat, and strcasecmp. For the full list see the end of `dmalloc.h'.

When you call strlen, for instance, dmalloc will make sure the string argument's fence-post areas have not been overwritten, its file and line number locations are good, etc. With bcopy, dmalloc will make sure that the destination string has enough space to store the number of bytes specified.

For all of the arguments checked, if the pointer is not in the heap then it is ignored since dmalloc does not know anything about it.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4 Generating a Core File on Errors

If the error-abort debug token has been enabled, when the library detects any problems with the heap memory, it will immediately attempt to dump a core file. See section Description of the Debugging Tokens. Core files are a complete copy of the program and it's state and can be used by a debugger to see specifically what is going on when the error occurred. See section Using Dmalloc With a Debugger. By default, the low, medium, and high arguments to the library utility enable the error-abort token. You can disable this feature by entering dmalloc -m error-abort (-m for minus) to remove the error-abort token and your program will just log errors and continue. You can also use the error-dump token which tries to dump core when it sees an error but still continue running. See section Description of the Debugging Tokens.

When a program dumps core, the system writes the program and all of its memory to a file on disk usually named `core'. If your program is called `foo' then your system may dump core as `foo.core'. If you are not getting a `core' file, make sure that your program has not changed to a new directory meaning that it may have written the core file in a different location. Also insure that your program has write privileges over the directory that it is in otherwise it will not be able to dump a core file. Core dumps are often security problems since they contain all program memory so systems often block their being produced. You will want to check your user and system's core dump size ulimit settings.

The library by default uses the abort function to dump core which may or may not work depending on your operating system. If the following program does not dump core then this may be the problem. See KILL_PROCESS definition in `settings.dist'.

 
main()
{
  abort();
}

If abort does work then you may want to try the following setting in `settings.dist'. This code tries to generate a segmentation fault by dereferencing a NULL pointer.

 
#define KILL_PROCESS    { int *_int_p = 0L; *_int_p = 1; }

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.5 Additional Non-standard Routines

The library has a number of variables that are not a standard part of most malloc libraries:

Variable: int dmalloc_errno

This variable stores the internal dmalloc library error number like errno does for the system calls. It can be passed to dmalloc_strerror() (see below) to get a string version of the error. It will have a value of zero if the library has not detected any problems.

Variable: char* dmalloc_logpath

This variable can be used to set the dmalloc log filename. The env variable DMALLOC_LOGFILE overrides this variable.

Additionally the library provides a number of non-standard malloc routines:

Function: void dmalloc_shutdown ( void )

This function shuts the library down and logs the final statistics and information especially the non-freed memory pointers. The library has code to support auto-shutdown if your system has the on_exit() call, atexit() call, or compiler destructor support (see `conf.h'). If you do not have these, then dmalloc_shutdown should be called right before exit() or as the last function in main().

 
main()
{
        …
        dmalloc_shutdown();
        exit(0);
}
Function: int dmalloc_verify ( char * pnt )

This function verifies individual memory pointers that are suspect of memory problems. To check the entire heap pass in a NULL or 0 pointer. The routine returns DMALLOC_VERIFY_ERROR or DMALLOC_VERIFY_NOERROR.

NOTE: `dmalloc_verify()' can only check the heap with the functions that have been enabled. For example, if fence-post checking is not enabled, `dmalloc_verify()' cannot check the fence-post areas in the heap.

Function: unsigned-int dmalloc_debug ( const unsigned int flags )

This routine sets the debug functionality flags and returns the previous flag value. It is helpful in server or cgi-bin programs where environmental variables cannot be used. See section Debugging Memory in a Server or Cgi-Bin Process. For instance, if debugging should never be enabled for a program, a call to dmalloc_debug(0) as the first call in main() will disable all the memory debugging from that point on.

NOTE: you cannot add or remove certain flags such as signal handlers since they are setup at initialization time only.

NOTE: you can also use dmalloc_debug_setup below.

Function: unsigned-int dmalloc_debug_current ( void )

This routine returns the current debug functionality value value. This allows you to save a copy of the debug dmalloc settings to be changed and then restored later.

Function: void dmalloc_debug_setup ( const char * options_str )

This routine sets the global debugging functionality as an option string. Normally this would be passed in in the DMALLOC_OPTIONS environmental variable. This is here to override the env or for circumstances where modifying the environment is not possible or does not apply such as servers or cgi-bin programs. See section Debugging Memory in a Server or Cgi-Bin Process.

Some examples:

 
/*
 * debug tokens high, threaded lock-on at 20,
 * log to dmalloc.%p (pid)
 */
dmalloc_debug_setup("debug=0x4f46d03,lockon=20,log=dmalloc.%p");

/*
 * turn on some debug tokens directly and log to the
 * file 'logfile'
 */
dmalloc_debug_setup(
  "log-stats,log-non-free,check-fence,log=logfile");
Function: int dmalloc_examine ( const DMALLOC_PNT pnt, DMALLOC_SIZE * user_size_p, DMALLOC_SIZE * total_size_p, char ** file_p, int * line_p, DMALLOC_PNT * ret_addr_p, unsigned long * user_mark_p, unsigned long * seen_p )

This function returns the size of a pointer's allocation as well as the total size given including administrative overhead, file and line or the return-address from where it was allocated, the last pointer when the pointer was "used", and the number of times the pointer has been "seen". It will return DMALLOC_NOERROR or DMALLOC_ERROR depending on whether pnt is good or not.

NOTE: This function is certainly not provided by most if not all other malloc libraries.

Function: void dmalloc_track ( const dmalloc_track_t track_func )

Register an allocation tracking function which will be called each time an allocation occurs. Pass in NULL to disable. To take a look at what information is provided, see the dmalloc_track_t function typedef in dmalloc.h.

Function: unsigned-long dmalloc_mark ( void )

Return to the caller the current "mark" which can be used later to log the pointers which have changed since this mark with the dmalloc_log_changed function. Multiple marks can be saved and used.

This is very useful when using the library with a server which does not exit. You can then save a mark before a transaction or event happens and then check to see what has changed using the dmalloc_log_changed function below. See section Debugging Memory in a Server or Cgi-Bin Process.

If you LOG_ITERATION enabled in your `settings.h' file then the entries in the log file will be prepended with the number of memory transactions that the library has handled so far. You can also enable LOG_PNT_ITERATION in `settings.h' to store the memory transaction number with each pointer.

Function: unsigned-long dmalloc_memory_allocated ( void )

Return to the caller the total number of bytes that have been allocated by the library. This is not the current in use but the total number of bytes returned by allocation functions.

Function: unsigned-int dmalloc_page_size ( void )

Return to the caller the memory page-size being used by the library. This should be the same value as the one returned by the getpagesize() function, if available.

Function: unsigned-long dmalloc_count_changed ( const unsigned long mark, const int not_freed_b, const int free_b )

Count the pointers that have changed since the mark which was returned by dmalloc_mark. If not_freed_b is set to non-0 then count the pointers that have not been freed. If free_b is set to non-0 then count the pointers that have been freed.

This can be used in conjunction with the dmalloc_mark() function to help servers which never exit ensure that transactions or events are not leaking memory. See section Debugging Memory in a Server or Cgi-Bin Process.

 
unsigned long mark = dmalloc_mark() ;
…
assert(dmalloc_count_changed(mark, 1, 0) == 0) ;
Function: void dmalloc_log_stats ( void )

This routine outputs the current dmalloc statistics to the log file.

Function: void dmalloc_log_unfreed ( void )

This function logs the unfreed-memory information to the log file. This is also useful to log the currently allocated points to the log file to be compared against another dump later on.

Function: void dmalloc_log_changed ( const unsigned long mark, const int not_freed_b, const int freed_b, const int details_b )

Log the pointers that have changed since the mark which was returned by dmalloc_mark. If not_freed_b is set to non-0 then log the pointers that have not been freed. If free_b is set to non-0 then log the pointers that have been freed. If details_b set to non-0 then log the individual pointers that have changed otherwise just log the summaries.

This can be used in conjunction with the dmalloc_mark() function to help servers which never exit find transactions or events which are leaking memory. See section Debugging Memory in a Server or Cgi-Bin Process.

Function: void dmalloc_vmessage ( const char * format, va_list args )

Write a message into the dmalloc logfile using vprintf-like arguments.

Function: void dmalloc_message ( const char * format, ... )

Write a message into the dmalloc logfile using printf-like arguments.

Function: void dmalloc_get_stats ( DMALLOC_PNT * heap_low_p, DMALLOC_PNT * heap_high_p, unsigned long * total_space_p, unsigned long * user_space_p, unsigned long * current_allocated_p, unsigned long * current_pnt_np, unsigned long * max_allocated_p, unsigned long * max_pnt_np, unsigned long * max_one_p)

This function return a number of statistics about the current heap. The pointers heap_low_p and heap_high_p will be set to the low and high spots in the heap. total_space_p will be set to the total space in the heap including user space, administrative space, and overhead. user_space_p will be set to the space given to the user process (allocated and free space). current_allocated_p will be set to the current allocated space given to the user process. current_pnt_np will be set to the current number of pointers allocated by the user process. max_allocated_p will be set to the maximum allocated space given to the user process. max_pnt_np will be set to the maximum number of pointers allocated by the user process. max_on_p will be set to the maximum space allocated with one call by the user process.

Function: const-char* dmalloc_strerror ( const int error_number )

This function returns the string representation of the error value in error_number (which probably should be dmalloc_errno). This allows the logging of more verbose memory error messages.

You can also display the string representation of an error value by a call to the `dmalloc' program with a `-e #' option. See section Dmalloc Utility Program.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6 Description of the Internal Error Codes

The following error codes are defined in `error_val.h'. They are used by the library to indicate a detected problem. They can be caused by the user (`ERROR_TOO_BIG') or can indicate an internal library problem (`ERROR_SLOT_CORRUPT'). The `dmalloc' utility can give you the string version of the error with the -e argument:

 
$ dmalloc -e 60
dmalloc: dmalloc_errno value '60' = 
   'pointer is not on block boundary'

Here are the error codes set by the library. They are non contiguous on purpose because I add and delete codes all of the time and there are sections for various error-code types.

1 (ERROR_NONE) no error

No error. It is good coding practice to set the no-error code to be non-0 value because it forces you to set it explicitly.

2 (INVALID_ERROR)

Invalid error number. If the library outputs this error then your dmalloc utility may be out of date with the library you linked against. This will be returned with all error codes not listed here.

10 (ERROR_BAD_SETUP) initialization and setup failed

Bad setup value. This is currently unused but it is intended to report on invalid setup configuration information.

11 (ERROR_IN_TWICE) malloc library has gone recursive

Library went recursive. This usually indicates that you are not using the threaded version of the library. Or if you are then you are not using the `-o' "lock-on" option. See section Using the Library with a Thread Package.

13 (ERROR_LOCK_NOT_CONFIG) thread locking has not been configured

Thread locking has not been configured. This indicates that you attempted to use the `-o' "lock-on" option without linking with the thread version of the library. You should probably be using -ldmallocth not -ldmalloc when you are linking. Or you should include …/lib/libdmallocth.a on your compilation line.

20 (ERROR_IS_NULL) pointer is null

Pointer is null. The program passed a NULL (0L) pointer to free and you have the error-free-null token enabled.

21 (ERROR_NOT_IN_HEAP) pointer is not pointing to heap data space

Pointer is not pointing to heap data space. This means that the program passed an out-of-bounds pointer to free or realloc. This could be someone trying to work with a wild pointer or trying to free a pointer from a different source than malloc.

22 (ERROR_NOT_FOUND) cannot locate pointer in heap

Cannot locate pointer in heap. The user passed in a pointer which the heap did not know about. Either this pointer was allocated by some other mechanism (like mmap or sbrk directly) or it is a random invalid pointer.

In some rare circumstances, sometimes seen with shared libraries, there can be two separate copies of the dmalloc library in a program. Each one does not know about the pointers allocated by the other.

23 (ERROR_IS_FOUND) found pointer the user was looking for

This indicates that the pointer specified in the address part of the environmental variable was discovered by the library. See section Environment Variable Name and Features. This error is useful so you can put a breakpoint in a debugger to find where a particular address was allocated. See section Using Dmalloc With a Debugger.

24 (ERROR_BAD_FILE) possibly bad .c filename pointer

A possibly invalid filename was discovered in the dmalloc administrative sections. This could indicate some corruption of the internal tables. It also could mean that you have a source file whose name is longer than 100 characters. See MAX_FILE_LENGTH in the `settings.dist' file.

25 (ERROR_BAD_LINE) possibly bad .c file line-number

A line-number was out-of-bounds in the dmalloc administrative sections. This could indicate some corruption of the internal tables. It also could mean that you have a source file containing more than 30000 lines of code. See MAX_LINE_NUMBER in the `settings.dist' file.

26 (ERROR_UNDER_FENCE) failed UNDER picket-fence magic-number check

This indicates that a pointer had its lower bound picket-fence magic number overwritten. If the check-fence token is enabled, the library writes magic values above and below allocations to protect against overflow. Most likely this is because a pointer below it went past its allocate and wrote into the next pointer's space.

27 (ERROR_OVER_FENCE) failed OVER picket-fence magic-number check

This indicates that a pointer had its upper bound picket-fence magic space overwritten. If the check-fence token is enabled, the library writes magic values above and below allocations to protect against overflow. Most likely this is because an array or string allocation wrote past the end of the allocation.

Check for improper usage of strcat, sprintf, strcpy, and any other functions which work with strings and do not protect themselves by tracking the size of the string. These functions should always be replaced with: strncat, snprintf, strncpy, and others.

28 (ERROR_WOULD_OVERWRITE) use of pointer would exceed allocation

This error is generated by the function pointer checking code usually enabled with the check-funcs token. Dmalloc overloads a number of string and memory copying functions and verifies that the buffers (if allocated in the heap) would not be overwritten by the function.

30 (ERROR_NOT_START_BLOCK) pointer is not to start of memory block

This indicates that the user passed in a pointer to be freed or reallocated that was not at the start of the allocation. You would get this error, for example, if you allocate and get pointer X but then try to free X+1.

40 (ERROR_BAD_SIZE) invalid allocation size

This error indicates that a size value in the internal structures of the library were corrupted. This could be a random pointer problem, pointer overflow, or some other corruption.

41 (ERROR_TOO_BIG) largest maximum allocation size exceeded

An allocation asked for memory larger than the configured maximum. This is a user configured setting. See LARGEST_ALLOCATION in the `settings.dist' file. It is used to protect against wild allocation sizes. If you have super large allocation sizes then you should tune the LARGEST_ALLOCATION value appropriately.

43 (ERROR_ALLOC_FAILED) could not grow heap by allocating memory

The library could not allocate more heap space and the program has run out of memory. This could indicate that you've overflowed some system imposed limit. On many operation systems, the ulimit call can tune system defaults. The library uses a lot more memory compared to the system malloc library because it stores a lot more information about the allocated pointers.

NOTE: This also may be due to an inability of your operating system to use the mmap system call to allocate memory. You may need to force the USE_MMAP setting to be 0. Please use the forums at URL http://dmalloc.com/ to report issues with this.

45 (ERROR_OVER_LIMIT) over user specified allocation limit

The library has allocated more memory than was specified in the memory-limit environmental variable. See section Environment Variable Name and Features.

60 (ERROR_NOT_ON_BLOCK) pointer is not on block boundary

The user tried to free or realloc a pointer that was not pointing to a block boundary. You would get this error, for example, if you allocate and get pointer X but then try to free X+1.

61 (ERROR_ALREADY_FREE) tried to free previously freed pointer

The user tried to free a pointer than has already been freed. This is a very common mistake and can lead to serious problems. It can be because a destructor is being called twice for some reason. Although tracking down the specific source is highly recommended, it is good to set pointers to NULL (0L) after you free them as a rule.

67 (ERROR_FREE_OVERWRITTEN) free space has been overwritten

If either the free-blank or check-blank tokens are enabled then the library will overwrite memory when it is freed with the "dmalloc-free" byte (hex 0xdf, octal 0337, decimal 223). If the program writes into this space, then the library will detect the write and trigger this error. This could indicate that the program is using a pointer after it has been freed.

70 (ERROR_ADMIN_LIST) bad admin structure list

An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption.

72 (ERROR_ADDRESS_LIST) internal address list corruption

An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption.

73 (ERROR_SLOT_CORRUPT) internal memory slot corruption

An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.7 How to Disable the library

If you would like to disable the library's detailed checking features during a particularly allocation intensive section of code, you can do something like the following:

 
        unsigned int dmalloc_flags;
        …
        /* turn off all debug flags and save a copy of old value */
        dmalloc_flags = dmalloc_debug(0);

        /* section of a lot of allocations */
        …
        /* end of section */

        /* restore the dmalloc flag setting */
        dmalloc_debug(dmalloc_flags);

When you are finished with the development and debugging sessions, you may want to disable the dmalloc library and put in its place either the system's memory-allocation routines, gnu-malloc, or maybe your own. Attempts have been made to make this a reasonably painless process. The ease of the extraction depends heavily on how many of the library's features your made use of during your coding.

Reasonable suggestions are welcome as to how to improve this process while maintaining the effectiveness of the debugging.

  • If you want to totally disable the dmalloc library then you will need to recompile all the C files that include `dmalloc.h' while defining DMALLOC_DISABLE. This will cause the dmalloc macros to not be applied. See section Macros Providing File and Line Information.
     
    cc -g -DDMALLOC_DISABLE file.c
    

    An alternative is to surround the dmalloc.h inclusion or any direct dmalloc references with an #ifdef DMALLOC and then just remove the -DDMALLOC.

     
    #ifdef DMALLOC
    #include "dmalloc.h"
    #endif
    
    main()
    {
      …
    
    #ifdef DMALLOC
      dmalloc_verify(0L);
    #endif
      return 0;
    }
    
     
    // to get dmalloc information
    $ cc -DDMALLOC main.c
    
    // without dmalloc information
    $ cc main.c
    
  • If you compiled any of your source modules with DMALLOC_FUNC_CHECK defined then you must first recompile all those modules without the flag enabled.

    If you have disabled dmalloc with the DMALLOC_DISABLED flag or never included `dmalloc.h' in any of your C files, then you will not need to recompile your sources when you need to disable the library.

    If you get unresolved references like _dmalloc_malloc or _dmalloc_bcopy then something was not disabled as it should have been.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.8 Using the Library with C++

For those people using the C++ language, the library tries to configure and build `libdmallocxx.a' library. This library should be linked into your C++ programs instead of `libdmalloc.a'.

Dmalloc is not as good with C++ as C because the dynamic memory routines in C++ are new() and delete() as opposed to malloc() and free(). Since new and delete are usually not used as functions but rather as x = new type, there is no easy way for dmalloc to pass in file and line information unfortunately. The `libdmallocxx.a' library provides the file `dmallocc.cc' which effectively redirects new to the more familiar malloc and delete to the more familiar free.

NOTE: The author is not a C++ hacker so feedback in the form of other hints and ideas for C++ users would be much appreciated.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9 Using Dmalloc With a Debugger

Here are a number of possible scenarios for using the dmalloc library to track down problems with your program.

You should first enable a logfile filename and turn on a set of debug features. You can use dmalloc -l logfile low to accomplish this. If you are interested in having the error messages printed to your terminal as well, enable the print-messages token by typing dmalloc -p print-messages afterwards. See section Dmalloc Utility Program.

Now you can enter your debugger (I use the excellent GNU debugger gdb), and put a break-point in dmalloc_error() which is the internal error routine for the library. When your program is run, it will stop there if a memory problem is detected.

If you are using GDB, I would recommend adding the contents of `dmalloc.gdb' in the `contrib' subdirectory to your `.gdbinit' file in your home directory. This enables the dmalloc command which will prompt you for the arguments to the dmalloc command and will set a break point in dmalloc_error() automatically.

If you are using shared libraries, you may want to execute the following commands initially to load in dmalloc and other library symbols:

 
(gdb) sharedlibrary
(gdb) add-shared-symbol-files

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9.1 Diagnosing General Problems with a Debugger

If your program stops at the dmalloc_error() routine then one of a number of problems could be happening. Incorrect arguments could have been passed to a malloc call: asking for negative number of bytes, trying to realloc a non-heap pointer, etc.. There also could be a problem with the system's allocations: you've run out of memory, some other function in your program is using the heap allocation functions mmap or sbrk, etc.. However, it is most likely that some code that has been executed was naughty.

To get more information about the problem, first print via the debugger the dmalloc_errno variable to get the library's internal error code. You can suspend your debugger and run dmalloc -e value-returned-from-print to get an English translation of the error. A number of the error messages are designed to indicate specific problems with the library administrative structures and may not be user-friendly.

If the problem was due to the arguments or system allocations then the source of the problem has been found. However, if some code did something wrong, you may have some more work to do to locate the actual problem. The check-heap token should be enabled and the interval setting disabled or set to a low value so that the library can find the problem as close as possible to its source. The code that was execute right before the library halted, can then be examined closely for irregularities. See section Description of the Debugging Tokens, See section Dmalloc Utility Program.

You may also want to put calls to dmalloc_verify(0) in your code before the section which generated the error. This should locate the problem faster by checking the library's structures at that point. See section Additional Non-standard Routines.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9.2 Tracking Down Non-Freed Memory

So you've run your program, examined the log-file and discovered (to your horror) some un-freed memory. Memory leaks can become large problems since even the smallest and most insignificant leak can starve the program given the right circumstances.

 
not freed: '0x45008' (12 bytes) from 'ra=0x1f8f4'
not freed: '0x45028' (12 bytes) from 'unknown'
not freed: '0x45048' (10 bytes) from 'argv.c:1077'
  known memory not freed: 1 pointer, 10 bytes
unknown memory not freed: 2 pointers, 24 bytes

Above you will see a sample of some non-freed memory messages from the logfile. In the first line the `0x45008' is the pointer that was not freed, the `12 bytes' is the size of the unfreed block, and the `ra=0x1f8f4' or return-address shows where the allocation originated from. See section Translating Return Addresses into Code Locations.

The systems which cannot provide return-address information show `unknown' instead, as in the 2nd line in the sample above.

The `argv.c:1077' information from the 3rd line shows the file and line number which allocated the memory which was not freed. This information comes from the calls from C files which included `dmalloc.h'. See section Macros Providing File and Line Information.

At the bottom of the sample it totals the memory for you and breaks it down to known memory (those calls which supplied the file/line information) and unknown (the rest).

Often, you may allocate memory in via strdup() or another routine, so the logfile listing where in the strdup routine the memory was allocated does not help locate the true source of the memory leak - the routine that called strdup. Without a mechanism to trace the calling stack, there is no way for the library to see who the caller of the caller (so to speak) was.

However, there is a way to track down unfreed memory in this circumstance. You need to compile the library with STORE_SEEN_COUNT defined in `conf.h'. The library will then record how many times a pointer has been allocated or freed. It will display the unfreed memory as:

 
not freed: '0x45008|s3' (12 bytes) from 'ra=0x1f8f4'

The STORE_SEEN_COUNT option adds a `|s#' qualifier to the address. This means that the address in question was seen `#' many times. In the above example, the address `0x45008' was seen `3' times. The last time it was allocated, it was not freed.

How can a pointer be "seen" 3 times? Let say you strdup a string of 12 characters and get address `0x45008' - this is #1 time the pointer is seen. You then free the pointer (seen #2) but later strdup another 12 character string and it gets the `0x45008' address from the free list (seen #3).

So to find out who is allocating this particular 12 bytes the 3rd time, try dmalloc -a 0x45008:3. The library will stop the program the third time it sees the `0x45008' address. You then enter a debugger and put a break point at dmalloc_error. Run the program and when the breakpoint is reached you can examine the stack frame to determine who called strdup to allocate the pointer.

To not bother with the STORE_SEEN_COUNT feature, you can also run your program with the never-reuse token enabled. This token will cause the library to never reuse memory that has been freed. Unique addresses are always generated. This should be used with caution since it may cause your program to run out of memory.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9.3 Diagnosing Fence-Post Overwritten Memory

For a definition of fence-posts please see the "Features" section. See section General Features of the Library.

To detect fence-post overruns, you need to enable the `check-fence' token. See section Description of the Debugging Tokens. This pads your allocations with some extra bytes at the front and the end and watches the space to make sure that they don't get overwritten. NOTE: The library cannot detect if this space gets read, only written.

If you have encountered a fence-post memory error, the logfile should be able to tell you the offending address.

 
free: failed UNDER picket-fence magic-number checking: 
pointer '0x1d008' from 'dmalloc_t.c:427'
Dump of proper fence-bottom bytes: '\e\253\300\300\e\253\300\300'
Dump of '0x1d008'-8: '\e\253\300\300WOW!\003\001pforger\023\001\123'

The above sample shows that the pointer `0x1d008' has had its lower fence-post area overwritten. This means that the code wrote below the bottom of the address or above the address right below this one. In the sample, the string that did it was `WOW!'.

The library first shows you what the proper fence-post information should look like, and then shows what the pointer's bad information was. If it cannot print the character, it will display the value as `\ddd' where ddd are three octal digits.

By enabling the check-heap debugging token and assigning the interval setting to a low number, you should be able to locate approximately when this problem happened. See section Description of the Debugging Tokens, See section Dmalloc Utility Program.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9.4 Translating Return Addresses into Code Locations

The following gdb commands help you translate the return-addresses (ra=) entries in the logfile into locations in your code. I've provided a `ra_info.pl' perl script in the `contrib/' directory with the dmalloc sources which seems to work well with gdb. But, if you need to do it manually, here are the commands in gdb to use.

 
# you may need to add the following commands to load in shared libraries
(gdb) sharedlibrary
(gdb) add-shared-symbol-files

(gdb) x 0x10234d
0x10234d <_findbuf+132>: 0x7fffceb7

(gdb) info line *(0x82cc)
Line 1092 of argv.c starts at pc 0x7540 and ends at 0x7550.

In the above example, gdb was used to find that the two non-freed memory pointers were allocated in _findbuf() and in file argv.c line 1092 respectively. The `x address' (for examine) can always be used on the return-addresses but the `info line *(address)' will only work if that file was compiled using the -g option and has not been stripped. This limitation may not be true in later versions of gdb.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.10 Using the Library with a Thread Package

Threads are special operating system facilities which allow your programs to have multiple threads of execution (hence the name). In effect your program can be doing a number of things "at the same time". This allows you to take full advantage of modern operating system scheduling and multi-processor hardware. If I've already lost you or if any of the terminology below does not make sense, see manuals about POSIX threads (pthreads) before going any further. O'Reilly publishes a pretty good pthreads manual for example.

To use dmalloc with your threaded program, you will first need to make sure that you are linking with `libdmallocth.a' which is the threaded version of the library. The support for threads in dmalloc should be adequate for most if not all testing scenarios. It provides support for mutex locking itself to protect against race conditions that result in multiple simultaneous execution. One of the major problems is that most thread libraries uses malloc themselves. Since all of dmalloc's initialization happens when a call to malloc is made, we may be attempting to initialize or lock the mutex while the thread library is booting up. A very bad thing since thread libraries don't expect to recurse.

The solution to this problem is to have the library not initialize or lock its mutex variable until after a certain number of allocation calls have been completed. If the library does not wait before initializing the locks, the thread library will probably core dump. If it waits too long then it can't protect itself from multiple execution and it will abort or other bad things might happen. You adjust the number of times to wait at runtime with the `lock-on' option to the dmalloc program (for example dmalloc -o 20). See section Dmalloc Utility Program. Times values between 5 and 30 are probably good although operating systems will vary significantly. You know its too low if your program immediately core dumps and too high if the dmalloc library says its gone recursive although with low values, you might get either problem.

An additional complexity is when we are initializing the lock before mutex locking around the library. As mentioned, the initialization itself may generate a malloc call causing the library to go recursive and the pthread library to possibly core dump. With the THREAD_INIT_LOCK setting defined in `settings.h', you can tune how many times before we start locking to try and initialize the mutex lock. It defaults to 2 which seems to work for me. If people need to have this runtime configurable or would like to present an alternative default, please let me know.

So to use dmalloc with a threaded program, follow the following steps carefully.

  1. Follow the installation instructions on how to configure, make, and install the library but make sure to add the --enable-threads argument to configure. See section How to Install the Library.
  2. Typing make should be enough to build the threaded versions of the libraries including `libdmallocth.a'.
  3. Link the dmalloc threaded library into your program. The dmalloc library should probably be placed at or near the end of the library list.
  4. Enable the debugging options that you need by typing dmalloc -l logfile -i 100 low (for example). dmalloc --usage will provide verbose usage info for the dmalloc program. See section Dmalloc Utility Program.
  5. Enable the "lock-on" option (for example dmalloc -o 20). As explained above, you may have to try different values before getting it right. Values between 5 and 30 are probably good.
  6. If you get a dmalloc error #13 `thread locking has not been configured' then you have not compiled you program with the threaded version of dmalloc or there was a problem building it.
  7. If everything works, you should be able to run your program, have it not immediately crash, and the dmalloc library should not complain about recursion.

If you have any specific questions or would like addition information posted in this section, please let me know. Experienced thread programmers only please.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.11 Using the library with Cygwin environment.

The Cygwin environment is a Linux-like environment for Windows. It provides Linux look and feel as well as a programming environment. See URL http://www.cygwin.com/ for more details.

Cygwin uses the GetEnvironmentVariableA function to read in environmental variables instead of getenv. This functions are used to get the value of the `DMALLOC_OPTIONS' variable which sets the debugging options. See section Environment Variable Name and Features.

As of right now, dmalloc is not detecting the GetEnvironmentVariableA function correctly so you may need to tune the `conf.h' file to get it to work. See the sections on HAVE_GETENVIRONMENTVARIABLEA and GETENV_SAVE settings. Feedback is welcome here.

If you still have problems reading in the environmental variables, you can work around this issue. You can add some code into the main function in your program to initialize the dmalloc flags yourself. Here is a code sample:

 
main(int argc, char **argv)
{
#ifdef DMALLOC
  /*
   * Get environ variable DMALLOC_OPTIONS and pass the settings string
   * on to dmalloc_debug_setup to setup the dmalloc debugging flags.
   */
  dmalloc_debug_setup(getenv("DMALLOC_OPTIONS"));
#endif

  /* rest of code in main starts here */
  …
}

The #ifdef is just a good idea. I means that when debugging with dmalloc you need to compile your code with -DDMALLOC. When you are done debugging you can remove the flag and the call to dmalloc_debug_setup will be removed.

Please let me know if there is a better way to do this.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.12 Debugging Memory in a Server or Cgi-Bin Process

There are some specified challenges when trying to debug allocations in processes which do not startup, run, and then shutdown. Server processes (often called daemons) are those that are started (often at system boot time) and run perpetually. Other processes which are difficult to debug are CGI programs which are spawned by web servers or when you want to start debugging inside of a child process.

  1. Build your server or cgi-bin program with the dmalloc library like any other program. See section Getting Started with the Library.
  2. Add code into your program to enable the library flags to perform the memory checks that you require. Since these programs often do not run from the command line, you cannot use the dmalloc utility program and modify the process environment. See section Dmalloc Utility Program. The library provides a couple of functions to set the debugging flags when a program is running.
  3. To set the memory debugging flags, use the dmalloc_debug_setup function which takes a string in the same format of the `DMALLOC_OPTIONS' environmental variable. See section Environment Variable Name and Features. Use the dmalloc utility with the -n no-changes argument to see the appropriate settings for the `DMALLOC_OPTIONS' environmental variable.
     
    > dmalloc -n -l logfile high
    Outputed:
    DMALLOC_OPTIONS=debug=0x4f4ed03,log=logfile
    export DMALLOC_OPTIONS
    

    So if you want to turn on high debugging and log to the file `logfile' then you would copy the above `DMALLOC_OPTIONS' value into a call to dmalloc_debug_setup. Notice that I have surrounded the dmalloc code with an #ifdef DMALLOC so you'll have to compile using the -DDMALLOC flag.

     
    main()
    {
    #ifdef DMALLOC
      /* set the 'high' flags */
      dmalloc_debug_setup("debug=0x4f47d03,log=logfile");
    #endif
      …
    }
    

    Please note that the dmalloc_debug_setup function does not know about high, low, or other debug tokens but needs the actual flag values.

  4. For earlier versions of the library (before 5.0.0) without dmalloc_debug_setup, the dmalloc_debug function is available to set the flags directly, but it cannot adjust the logfile name and the other environment settings. You can use the dmalloc utility program to see what the numerical equivalent of the high token.
     
    > dmalloc -n high
    Outputed:
    DMALLOC_OPTIONS=debug=0x4f4ed03
    export DMALLOC_OPTIONS
    

    You can then take the 0x4f4ed03 hexadecimal number and call dmalloc_debug with that number.

     
    main()
    {
    #ifdef DMALLOC
      /* set the 'high' flags */
      dmalloc_debug(0x4f4ed03);
    #endif
      …
    }
    
  5. Even with the settings enabled, you may have problems getting the logfile to be written if your program is running as `nobody' or another user without permissions for security reasons. This is especially true for cgi-bin programs. In this case you should specify a full path to your malloc logfile in a world writable directory (ex. dmalloc_debug_setup("debug=0x4f47d03,log=/var/tmp/malloc");). Watch for programs which change into other directories and which may cause logfiles specified as relative or local paths to be dropped in other locations. You may always want to use a full path logfile.
  6. Once you have your settings enabled and your log is being generated, you may now want to check out how your process is doing in terms of unfreed memory. Since it is not shutting down, the automatic unfreed log entries are not being dropped to the logfile. By using the dmalloc_mark and dmalloc_log_changed functions, you can set a mark point at a certain place inside of your program, and then later see whether there are any unfreed pointers since the mark.
     
    main()
    {
    #ifdef DMALLOC
      /* set the 'high' flags */
      dmalloc_debug_setup("debug=0x4f47d03,log=logfile");
    #endif
    
      while (1) {
        /* accept a connection from a client */
        accept_connection();
    
        while (1) {
    #ifdef DMALLOC
          unsigned long mark;
          /* get the current dmalloc position */
          mark = dmalloc_mark() ;
    #endif
          /* process the connection */
          if (process_connection() != PROCESS_OK) {
            break;
          }
    #ifdef DMALLOC
          /*
           * log unfreed pointers that have been added to
           * the heap since mark
           */
          dmalloc_log_changed(mark,
                              1 /* log unfreed pointers */,
                              0 /* do not log freed pointers */,
                              1 /* log each pnt otherwise summary */);
    #endif
        }
        /* close the connection with the client */
        close_connection();
      }
      …
    }
    

    Usually you would set the mark after the initializations and before each transaction is processed. Then for each transaction you can use dmalloc_log_changed to show the unfreed memory. See section Additional Non-standard Routines.

  7. You can also use the dmalloc_log_stats function to dump general information about the heap. Also, remember that you can use the dmalloc_message and dmalloc_vmessage routines to annotate the dmalloc logfile with details to help you debug memory problems. See section Additional Non-standard Routines.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.13 Explanation of the Logfile Output

Most of time you will be using the logfile output from library as the sole information source for diagnosing problems in and getting statistics for your program.

 
1098918225: 3: Dmalloc version 'Version 5.5.2'
1098918225: 3: flags = 0x4f4e503, logfile '/tmp/dmalloc.log'
1098918225: 3: interval = 500, addr = 0, seen # = 0, limit = 0
1098918225: 3: starting time = 1098918225
1098918225: 3: process pid = 32406
1098918226: 4: WARNING: tried to free(0) from foo.c:708'
1098918228: 20: *** free: at 'unknown' pnt '0xed310080|s2': \
            size 12, alloced at 'bar.c:102'
1098918230: 50: ERROR: heap_check: free space was overwritten (err 67)
1098918230: 50: error details: checking free pointer
1098918230: 50: pointer '0x291c5' from 'unknown' prev access 'foo.c:787'

Here is a short example of some logfile information. Each of the lines are prefixed by the time (in epoch seconds since 1/1/1970) and the iteration or call count which is the number of times the library has been called from malloc, free, verify, etc.. In the above example, the first 5 log entries where written at epoch 1098918225 or `Wed Oct 27 19:03:45 2004 EST' and they were generated by the 3rd call to the library. See the `settings.dist' file entries to tune what elements appear on each line: LOG_TIME_NUMBER, LOG_ITERATION, LOG_PID, etc.. You can convert the epoch seconds to a date from the command line with the following perl code: perl -e 'print localtime($ARGV[0])."\n";' epoch-seconds-number

The first 5 lines of the sample logfile contain header information for all logfiles. They show the version number and URL for the library as well as all of the settings that the library is currently using. These settings are tuned using the dmalloc utility program. See section Dmalloc Utility Program. The 5th line of is the process-id that generated the logfile.

The 6th line in the above example is what causes the logfile to be opened and the header to be written. It is a warning that tells you that you tried to free a 0L pointer at a certain location. You can disable these warnings by setting `ALLOW_FREE_NULL_MESSAGE' to 0 in `settings.dist'.

Line 7 is an example of a transaction log that you get when you enable the log-trans debug token. See section Description of the Debugging Tokens. This line shows that a call to free was made from an unknown location. It is unknown because the file in question did not include `dmalloc.h' to get file/line-number information. The call to free was freeing the pointer address 0xed310080 which we have "seen" 2 times (s2). We saw the pointer when it was allocated and then we are seeing it again when it was freed. Because the library is reusing pointers (reclaiming freed memory) the seen count helps to track how many times a pointer was used. The last part of the line shows that the pointer to be freed was allocated by `bar.c' line 102.

Lines 8-10 is the next problem that the library caught and this one is an error. It happened 5 seconds from the start of the log (1098918230) and at the 50th call into the library. It shows that an allocation that had been freed then was overwritten. This may imply that someone tried to use memory after it was freed or that there was a loose pointer reference. The last two lines give more details about when the error was discovered, the address of the offending pointer, and when the pointer was previous accessed, in this case freed. To discover where this problem is happening, you can use a debugger. See section Using Dmalloc With a Debugger.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.14 Various Other Hints That May Help

One of the problems that is often seen is that a program crashes in the libc memory code and you suspect a heap memory problem but both dmalloc and maybe valgrind don't show any problems. One of the big problems with debugging is that it is very difficult to do it without effecting how the program is run. Sometimes errors are due to subtle race conditions that are only seen when the program is running at full speed - not slowed down by debugging code.

This is especially true with threaded code which is often heavily affected when used with dmalloc and valgrind. Older versions of valgrid (maybe current) forced all threads into a single virtual system by design, which often masks reentrance bugs.

One way to work through these issues is to run with the library with very few debugging flags enabled. Many memory problems are fence-post areas so start with dmalloc checking just the fence post and error logging enabled:

 
dmalloc -d 0 -l dmalloc.log -p log-stats -p log-non-free -p check-fence -p check-funcs 

This enabled a small number of checks and should cause your program to run at close to full speed. The library has never been optimized for speed so some performance penalties will be felt.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4. Dmalloc Utility Program

The dmalloc program is designed to assist in the setting of the environment variable `DMALLOC_OPTIONS'. See section Environment Variable Name and Features. It is designed to print the shell commands necessary to make the appropriate changes to the environment. Unfortunately, it cannot make the changes on its own so the output from dmalloc should be sent through the eval shell command which will do the commands.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1 Using a Shell Alias with the Utility

The dmalloc program is designed to assist in the setting of the environment variable `DMALLOC_OPTIONS'. See section Environment Variable Name and Features. It is designed to print the shell commands necessary to make the appropriate changes to the environment. Unfortunately, it cannot make the changes on its own so the output from dmalloc should be sent through the eval shell command which will do the commands.

With shells that have aliasing or macro capabilities: csh, bash, ksh, tcsh, zsh, etc., setting up an alias to dmalloc to do the eval call is recommended. Bash, ksh, and zsh users should add the following to their `.bashrc', `.profile', or `.zshrc' file respectively (notice the -b option for bourne shell output):

 
function dmalloc { eval `command dmalloc -b $*`; }

If your shell does not support the command function then try:

 
function dmalloc { eval `\dmalloc -b $*`; }

or

 
function dmalloc { eval `/usr/local/bin/dmalloc -b $*`; }

If you are still using csh or tcsh, you should add the following to your `.cshrc' file (notice the -C option for c-shell output):

 
alias dmalloc 'eval `\dmalloc -C \!*`'

This allows the user to execute the dmalloc command as `dmalloc arguments'.

Users of versions of the Bourne shell (usually known as /bin/sh) that don't have command functions will need to send the output to a temporary file and the read it back in with the "." command:

 
$  dmalloc -b arguments … > /tmp/out
$  . /tmp/out

By the way, if you are looking for a shell, I heartily recommend trying out zsh. It is a bourne shell written from scratch with much the same features as tcsh without the csh crap.

NOTE: After you add the alias to the file you need to log out and log back in to have it take effect, or you can execute the above appropriate command on the command line. If you enter dmalloc runtime and see any output with DMALLOC_OPTIONS in it then the alias did not work.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2 How to Use the Dmalloc Program

The most basic usage for the program is `dmalloc [-bC] tag'. The `-b' or `-C' (either but not both flags used at a time) are for generating Bourne or C shell type commands respectively. dmalloc will try and use the SHELL environment variable to determine whether bourne or C shell commands should be generated but you may want to explicitly specify the correct flag.

The `tag' argument to dmalloc should match a line from the user's runtime configuration file or should be one of the built-in tags. See section Format of the Runtime Configuration File. If no tag is specified and no other option-commands used, dmalloc will display the current settings of the environment variable. It is useful to specify one of the verbose options when doing this.

To find out the usage for the debug malloc program try `dmalloc --usage-long'. The standardized usage message that will be displayed is one of the many features of the argv library included with this package.

It is available on the web at URL http://256.com/sources/argv/. See the documentation there for more information.

Here is a detailed list of the flags that can passed to dmalloc:

-a address

Set the `addr' part of the `DMALLOC_OPTIONS' variable to address (or alternatively address:number).

-b

Output Bourne shell type commands. Usually handled automagically.

-C

Output C shell type commands. Usually handled automagically.

-c

Clear/unset all of the settings not specified with other arguments. You can do this automatically when you set to a new tag with the -r option.

NOTE: clear will never unset the `debug' setting. Use -d 0 or a tag to `none' to achieve this.

-d bitmask

Set the `debug' part of the `DMALLOC_OPTIONS' env variable to the bitmask value which should be in hex. This is overridden (and unnecessary) if a tag is specified.

-D

List all of the debug-tokens. Useful for finding a token to be used with the -p or -m options. Use with -v or -V verbose options.

-e errno

Print the dmalloc error string that corresponds to the error number errno.

-f filename

Use this configuration file instead of the RC file `$HOME/.dmallocrc'.

-g

Output gdb type commands for using inside of the gdb debugger.

-h (or --help)

Output a help message for the utility.

-i number

Set the checking interval to number. If the check-heap token is enabled, this causes the library to only check the heap every Nth time which can significantly increase the running speed of your program. If a problem is found, however, this limits your ability to determine when the problem occurred. Try values of 50 or 100 initially.

-k

Do not reset all of the settings when a tag is specified. This specifically overrides the -r option and is provided here to override -r if it has been added to the dmalloc alias.

-l filename

Write the debugging output and other log-file information to the filename. Filename can include some of the following patterns which get expanded into strings:

%h

Gets expanded into the hostname if the gethostname() function is available.

%i

Gets expanded into the thread-id if the library has been configure to be used with threads. See section Using the Library with a Thread Package. See the end of the `settings.dist' file for settings which return the thread-id and convert it into a string.

%p

Gets expanded into the process-id if the getpid() function is available.

%t

Gets expanded into the time value in seconds if the time() function is available.

%u

Gets expanded into the user-id number if the getuid() function is available.

Some examples:

 
# logfile produced with pid extension:
#   logfile.8412  or  logfile.31451
dmalloc -l logfile.%p

# hostname and time extensions:
#   dmalloc-box1.foo.com-1055213240
dmalloc -l dmalloc-%h-%t

# if threads enabled, have thread-id extension:  log.thread32
dmalloc -l log.thread%i
-L

Write the debug-value into the environment not in hex but by individual debug-tokens in long form.

-m token(s)

Remove (minus) the debug capabilities of token(s) from the current debug setting or from the selected tag (or -d value). Multiple -m options can be specified.

-M limit

Set the memory allocation limit which will abort the program if the total memory allocations exceed this number of bytes. The limit can be a number with a k, m, or g at the end to indicate kilobyte, megabyte, and gigabyte respectively. Ex: 100k, 200m, 1g. If the limit is exceeded, this will generate an ERROR_OVER_LIMIT error. See section Description of the Internal Error Codes.

-n

Without changing the environment, output the commands resulting from the supplied options.

-o times

Set the "lock-on" period which dictates to the threaded version of the library to not initialize or lock the mutex lock around the library until after a certain number of allocation calls have been made. Some number between 2 and 30 is probably good. See the "Using With Threads" section for more information about the operation of the library with threads. See section Using the Library with a Thread Package.

-p token(s)

Add (plus) the debug capabilities of token(s) to the current debug setting or to the selected tag (or -d value). Multiple -p options can be specified.

-r

Remove (unset) all settings when using a tag. This is useful when you are returning to a standard development tag and want the logfile, address, and interval settings to be cleared automatically. If you want this behavior by default, this can be put into the dmalloc alias.

-R

Output rc shell type commands. This is not for the runtime configuration file but for the rc shell program.

-s file:line

Set the `start' part of the `DMALLOC_OPTIONS' env variable to a file-name and line-number location in the source where the library should begin more extensive heap checking. The file and line numbers for heap transactions must be working for this option to be obeyed. This is used if you are trying to locate a problem and you want the extensive checking to not happen initially because it's too slow.

-S number

Set the `start' part of the `DMALLOC_OPTIONS' env variable to an dmalloc mark number. The library will begin more extensive heap checking after this number of memory transactions. If you LOG_ITERATION enabled in your `settings.h' file then the entries in the log file will be prepended with the number of memory transactions that the library has handled so far. This number can be used to delay the start of the fine grained heap checking which can be very slow.

--start-size size

Set the `start' part of the `DMALLOC_OPTIONS' env variable to a number of bytes. The library will begin more extensive heap checking after this amount of memory has been allocated by the library. This allows you to start the slow and detailed checking of the library later in the program execution. You can use patterns like 250m, 1g, or 102k to mean 250 megabytes, 1 gigabyte, and 102 kilobytes respectively.

-t

List all of the tags in the rc-file. Use with -v or -V verbose options.

-u (or --usage)

Output the usage information for the utility.

-v

Give verbose output. Especially useful when dumping current settings or listing all of the tags.

-V

Give very verbose output for outputting even more details about settings.

--version

Output the version string for the utility. Please note that the version of the library that is installed or has been linked into your application may be different from the utility version.

If no arguments are specified, dmalloc dumps out the current settings that you have for the environment variable. For example:

 
Debug-Flags  '0x40005c7' (runtime)
Address      0x1f008, count = 3
Interval     100
Logpath      'malloc'
Start-File   not-set

With a -v option and no arguments, dmalloc dumps out the current settings in a verbose manner. For example:

 
Debug-Flags  '0x40005c7' (runtime)
   log-stats, log-non-free, log-bad-space, check-fence, catch-null
Address      0x1f008, count = 10
Interval     100
Logpath      'malloc'
Start-File   not-set

Here are some examples of dmalloc usage:

 
# start tough debugging, check the heap every 100 times,
# send the log information to file 'logfile'
dmalloc high -i 100 -l logfile

# find out what error code 20 is (from the logfile)
dmalloc -e 20

# cause the library to halt itself when it sees the address 0x34238
# for the 6th time.
dmalloc -a 0x34238:6

# send the log information to file 'logfile' with the time in seconds
# as an extension.
dmalloc -l logfile.%t

# return to the normal 'runtime' settings and clear out all
# other settings
dmalloc -c runtime

# enable basic 'low' settings plus (-p) the logging of
# transactions (log-trans) to file 'logfile'
dmalloc low -p log-trans -l logfile

# print out the current settings with Very-verbose output
dmalloc -V

# list the available debug malloc tokens with Very-verbose output
dmalloc -DV

# list the available tags from the rc file with verbose output
dmalloc -tv

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3 Environment Variable Name and Features

An environment variable is a variable that is part of the user's working environment and is shared by all the programs. The `DMALLOC_OPTIONS' variable is used by the dmalloc library to enable or disable the memory debugging features, at runtime. NOTE: you can also use the dmalloc_debug_setup function to set the option string. It can be set either by hand or with the help of the dmalloc program. See section Dmalloc Utility Program.

To set it by hand, Bourne shell (sh, bash, ksh, or zsh) users should use:

 
DMALLOC_OPTIONS=value
export DMALLOC_OPTIONS

C shell (csh or tcsh) users need to invoke:

 
setenv DMALLOC_OPTIONS value

The value in the above examples is a comma separated list of tokens each having a corresponding value. The tokens are described below:

debug

This should be set to a value in hexadecimal which corresponds to the functionality token values added together. See section Description of the Debugging Tokens. For instance, if the user wanted to enable the logging of memory transactions (value `0x008') and wanted to check fence-post memory (value `0x400') then `debug' should be set to `0x408' (`0x008' + `0x400').

NOTE: You don't have to worry about remembering all the hex values of the tokens because the dmalloc program automates the setting of this variable especially.

NOTE: You can also specify the debug tokens directly, separated by commas. See section Description of the Debugging Tokens. If `debug' and the tokens are both used, the token values will be added to the debug value.

lockon

Set this to a number which is the "lock-on" period. This dictates to the threaded version of the library to not initialize or lock the mutex lock around the library until after a certain number of allocation calls have been made. See the "Using With Threads" section for more information about the operation of the library with threads. See section Using the Library with a Thread Package.

log

Set this to a filename so that if `debug' has logging enabled, the library can log transactions, administration information, and/or errors to the file so memory problems and usage can be tracked.

To get different logfiles for different processes, you can assign `log' to a string with %d in it (for instance `logfile.%d'). This will be replaced with the pid of the running process (for instance `logfile.2451').

WARNING: it is easy to core dump any program with dmalloc, if you send in a format with arguments other than the one %d.

addr

When this is set to a hex address (taken from the dmalloc log-file for instance) dmalloc will abort when it finds itself either allocating or freeing that address.

The address can also have an `:number' argument. For instance, if it was set it to `0x3e45:10', the library will kill itself the 10th time it sees address `0x3e45'. By setting the number argument to 0, the program will never stop when it sees the address. This is useful for logging all activity on the address and makes it easier to track down specific addresses not being freed.

This works well in conjunction with the STORE_SEEN_COUNT option. See section Tracking Down Non-Freed Memory.

NOTE: dmalloc will also log all activity on this address along with a count.

inter

By setting this to a number X, dmalloc will only check the heap every X times. This means a number of debugging features can be enabled while still running the program within a finite amount of time.

A setting of `100' works well with reasonably memory intensive programs. This of course means that the library will not catch errors exactly when they happen but possibly 100 library calls later.

start

Set this to a number X and dmalloc will begin checking the heap after X times. This means the intensive debugging can be started after a certain point in a program.

`start' also has the format `file:line'. For instance, if it is set to `dmalloc_t.c:126' dmalloc will start checking the heap after it sees a dmalloc call from the `dmalloc_t.c' file, line number 126. If you use `dmalloc_t.c:0', with a 0 line number, then dmalloc will start checking the heap after it sees a call from anywhere in the `dmalloc_t.c' file.

This allows the intensive debugging to be started after a certain routine or file has been reached in the program.

Some examples are:

 
# turn on transaction and stats logging and set
# 'logfile' as the log-file
setenv DMALLOC_OPTIONS log-trans,log-stats,log=logfile

# enable debug flags 0x1f as well as heap-checking and
# set the interval to be 100
setenv DMALLOC_OPTIONS debug=0x1f,check-heap,inter=100

# enable 'logfile' as the log-file, watch for
# address '0x1234', and start checking when we see
# file.c line 123
setenv DMALLOC_OPTIONS log=logfile,addr=0x1234,start=file.c:123

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4 Description of the Debugging Tokens

The below tokens and their corresponding descriptions are for the setting of the debug library setting in the environment variable. See section Environment Variable Name and Features. They should be specified in the user's `.dmallocrc' file. See section Format of the Runtime Configuration File.

Each token, when specified, enables a specific debugging feature. For instance, if you have the log-stats token enabled, the library will log general statistics to the logfile.

To get this information on the fly, use dmalloc -DV. This will print out the Debug tokens in Very-verbose mode. See section Dmalloc Utility Program.

none

No debugging functionality

log-stats

Log general statistics when dmalloc_shutdown or dmalloc_log_stats is called.

log-non-free

Log non-freed memory pointers when dmalloc_shutdown or dmalloc_log_unfreed is called.

log-known

Log only known memory pointers that have not been freed. Pointers which do not have file/line or return-address information will not be logged.

log-trans

Log general memory transactions (quite verbose).

log-admin

Log administrative information (quite verbose).

log-bad-space

Log actual bytes in and around bad pointers.

log-nonfree-space

Log actual bytes in non-freed pointers.

log-elapsed-time

Log elapsed-time for allocated pointers (see `conf.h').

log-current-time

Log current-time for allocated pointers (see `conf.h').

check-fence

Check fence-post memory areas.

check-heap

Verify heap administrative structure.

check-blank

Check to see if space that was blanked when a pointer was allocated or when it was freed has been overwritten. If this is enabled then it will enable free-blank and alloc-blank automatically.

check-funcs

Check the arguments of some functions (mostly string operations) looking for bad pointers.

check-shutdown

Check all of the pointers in the heap when the program exits.

catch-signals

Shutdown the library automatically on SIGHUP, SIGINT, or SIGTERM. This will cause the library to dump its statistics (if requested) when you press control-c on the program (for example).

realloc-copy

Always copy data to a new pointer when realloc.

free-blank

Write special "dmalloc-free" byte (hexadecimal 0xdf, octal 0337, decimal 223) into space when it is freed. You can set this to be something else in the `settings.dist' file. This ensures that your program is not using memory after it has been freed. You can check to see if areas have been improperly overwritten with the check-blank token. If the free space has been overwritten, then ERROR_FREE_OVERWRITTEN is triggered. See section Description of the Internal Error Codes.

error-abort

Abort the program (and dump core) on errors. See error-dump below. See section Generating a Core File on Errors.

alloc-blank

Write special "dmalloc-alloc" byte (hexadecimal 0xda, octal 0332, decimal 218) into space when it is allocated. You can set this to be something else in the `settings.dist' file. If you are not using calloc this will overwrite the user space with the special bytes ensuring that your program is initializing its dynamic memory appropriately. Also, if you ask for 35 bytes and the library has to give you a block of 64 because of rounding issues, it will overwrite the extra memory with the special byte. You can then check to see if the extra areas have been improperly overwritten by enabling the check-blank token.

print-messages

Log any errors and messages to the screen via standard-error.

catch-null

Abort the program immediately if the library fails to get more heap space from the heap allocation routine mmap or sbrk.

never-reuse

Have the heap never use space that has been used before and freed. See section Tracking Down Non-Freed Memory. WARNING: This should be used with caution since you may run out of heap space.

error-dump

Dump core on error and then continue. Later core dumps overwrite earlier ones if the program encounters more than one error. See error-abort above. See section Generating a Core File on Errors.

NOTE: This will only work if your system supports the fork system call and the configuration utility was able to fork without going recursive.

error-free-null

By default the library will not generate an error when a program tries to free a NULL pointer. By enabling this token, you can change this behavior so an error is reported. See also the ALLOW_FREE_NULL and ALLOW_FREE_NULL_MESSAGE settings in the `settings.h' file to change the default behavior.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5 Format of the Runtime Configuration File

By using a RC File (or runtime configuration file) you can alias tags to combinations of debug tokens. See section Description of the Debugging Tokens.

NOTE: For beginning users, the dmalloc program has a couple of tags built into it so it is not necessary for you to setup a RC file:

runtime

Enables basic runtime tests including fence-post checking, null handling, and logging of any errors.

low

Runtime settings plus minimal checking of heap structures and overwriting of allocated and freed space.

medium

Low settings plus checking of all heap structures on each memory call, always relocates block on realloc, and aborts on errors. You may want to use -i option to the dmalloc utility. See section Dmalloc Utility Program.

high

Medium settings plus checking of overwritten freed and allocated memory and checking of arguments to a number of common functions. You may want to use -i option to the dmalloc utility. See section Dmalloc Utility Program.

For expert users, a sample `dmallocrc' file has been provided but you are encouraged to roll your own combinations. The name of default rc-file is `$HOME/.dmallocrc'. The `$HOME' environment variable should be set by the system to point to your home-directory.

The file should contain lines in the general form of:

 
tag     token1, token2, …

`tag' is to be matched with the tag argument passed to the dmalloc program, while `token1, token2, …' are debug capability tokens. See section Dmalloc Utility Program, Description of the Debugging Tokens.

A line can be finished with a `\' meaning it continues onto the next line. Lines beginning with `#' are treated as comments and are ignored along with empty lines.

Here is an example of a `.dmallocrc' file:

 
#
# Dmalloc runtime configuration file for the debug malloc library
#

# no debugging
none    none

# basic debugging
debug1  log-stats, log-non-free, check-fence

# more logging and some heap checking
debug2  log-stats, log-non-free, log-trans, \
        check-fence, check-heap, error-abort

# good utilities
debug3  log-stats, log-non-free, log-trans, \
        log-admin, check-fence, check-heap, realloc-copy, \
        free-blank, error-abort

…

For example, with the above file installed, you can type dmalloc debug1 after setting up your shell alias. See section Dmalloc Utility Program. This enables the logging of statistics, the logging of non-freed memory, and the checking of fence-post memory areas.

Enter dmalloc none to disable all memory debugging features.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5. Information on the Source Code


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1 Definition of Terms and other Information

Here are a couple definitions and other information for those interested in "picking the brain" of the library. The code is a little ugly here and there and it conforms to the Gray-Watson handbook of coding standards only.

bblock

basic block containing 2 ^ BASIC_BLOCK bytes of info

bblock_adm

administration for a set of basic blocks

dblock

divided block containing some base 2 number of blocks smaller than a basic block.

dblock_adm

administration for a set of divided blocks

chunk

some anonymous amount of memory

For more information about administration structures, see the code and comments from `chunk_loc.h'.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.2 General Compatibility Concerns

  • Realloc() backwards compatibility with being able to realloc from the last freed block is not supported. The author is interested to know who is using this (cough, cough) feature and for what reason.
  • Realloc() of a NULL pointer is supported in which case the library will just make a call to malloc(). This can be disabled with the help of the ALLOW_REALLOC_NULL manual compilation option in the `settings.h' file to adjust the library's default behavior.
  • Some systems allow free(0) to not be an error for some reason. Since 0 is not a valid address returned by the malloc call, it is debatable that this should be allowed. See `settings.h' for the ALLOW_FREE_NULL manual compilation option to adjust the library's default behavior.
  • Aside from possibly being slower than the system's memory allocation functions, the library should be fully compatible with the standard memory routines. If this is not the case, please bring this to my attention.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.3 Issues Important for Porting the Library

General portability issues center around:

  • mmap, sbrk, or compatible function usages. The library does support a preallocated memory chunk heap. See the INTERNAL_MEMORY_SPACE define in the `settings.dist' file.
  • The locating of the caller's address from the dmalloc functions. This is useful in locating problems from dmalloc functions called from C files which did not include `dmalloc.h': C library calls for instance.

    See `return.h' for the available architecture/compiler combinations. You may want to examine the assembly code from gcc (GNUs superior c-compiler) version 2+ being run on the following code. It should give you a good start on building a hack for your box.

     
    static char * x;
    
    a()
    {
            x = __builtin_return_address(0);
    }
    
    main()
    {
            a();
    }
    

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6. Some Solutions to Common Problems

This section provides some answers to some common problems and questions. Please send me mail with any additions to this list - either problems you are still having or tips that you would like to pass on.

When diagnosing a problem, if possible, always make sure you are running the most up to date version of Dmalloc available from the home page at URL http://dmalloc.com/. Problems are often fixed and a new release can be published before people encounter them.

`Why does my program run so slow?'

This library has never been (and maybe never will be) optimized for space nor speed. Some of its features make it unable to use some of the organizational methods of other more efficient heap libraries.

If you have the check-heap token enabled, your program might run slow or seem to hang. This is because by default, the library will run a full check of the heap with every memory allocation or free. You can have the library check itself less frequently by using the -i option to the dmalloc utility. See section Dmalloc Utility Program. If you are using the high token and you need your program to run faster, try the medium or low tokens which don't check as many heap features and so run faster although they will not catch as many problems. See section Format of the Runtime Configuration File.

`Why was a log-file not produced after I ran my program?'

This could be caused by a number of different problems.

  1. Are you sure you followed all of the items in the "Getting Started" section? Please review them if there is any doubt. See section Getting Started with the Library.
  2. Use the env or printenv commands to make sure that the `DMALLOC_OPTIONS' variable is set in your exported environment. See section Environment Variable Name and Features.
  3. Make sure that your program has been compiled correctly with the dmalloc library. The ident program should show chunk.c and other dmalloc files compiled into your program. You can also do strings -a your-program | grep chunk.c and look for something like `$Id: chunk.c,v 1.152 1999/08/25 12:37:01 gray Exp $' with different versions and date information. If this doesn't show up then chances are dmalloc was not linked into your program.
  4. If your program changes its working directory, it may write the dmalloc log-file somewhere else in the filesystem. You will need to check both where the program was started and to where it might change directory.
  5. The logfile is only produced when dmalloc_shutdown() is called. By default it will be called when exit() gets called. If you are running your program and press Control-C under Unix the program will stop immediately and dmalloc_shutdown() will not get called. You can either setup a signal handler for SIGINTR and call exit yourself, or you can enable the catch-signals token. See section Description of the Debugging Tokens.
  6. If your program is segfaulting or otherwise crashing when it exits, the exit() routine may not being called. You will have to resolve these issues so the dmalloc library can gracefully exit and write its log file.
  7. You may want to call dmalloc_log_stats() and dmalloc_log_unfreed() (or dmalloc_log_changed()) directly to have the library write its log file. Some system modules may not have shutdown if you call this before exit() so extra unfreed memory may be reported.
`I don't see any information about my non-freed (leaked) memory?'

The library will not (by default) report on "unknown" non-freed memory. Unknown means memory that does not have associated file and line information.

This will be necessary if you are not including `dmalloc.h' in all of your C files or if you are interested in tracking leaks in system functions.

`Dmalloc is returning the error "malloc library has gone recursive"'

This most likely indicates that you are using the Dmalloc library within a threaded application and two threads are trying to use the dmalloc library at once. Please see the section of the manual about threads for more information about properly configuring the library. See section Using the Library with a Thread Package.

If you are not using threads, then your program could have caught a signal while within Dmalloc, which then in turn called a memory allocation routine. It is unwise to allocate memory on the heap in most signal handlers. Lastly, some functions called by the library may call memory routines that it does not anticipate. If you think this the case, please report the problem and include a stack trace, operating system version/type, and the version of Dmalloc you are using.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Index of Concepts

Jump to:   %   -   .   0   1   2   3   4   6   7  
A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   Z  
Index Entry Section

%
%h4.2 How to Use the Dmalloc Program
%i4.2 How to Use the Dmalloc Program
%p4.2 How to Use the Dmalloc Program
%t4.2 How to Use the Dmalloc Program
%u4.2 How to Use the Dmalloc Program

-
-disable-cxx2.1 How to Install the Library
-enable-shlib2.1 How to Install the Library
-enable-threads2.1 How to Install the Library

.
.dmallocrc file4.5 Format of the Runtime Configuration File

0
0332 character4.4 Description of the Debugging Tokens
0337 character4.4 Description of the Debugging Tokens
0xda character4.4 Description of the Debugging Tokens
0xdf character4.4 Description of the Debugging Tokens

1
1, error code3.6 Description of the Internal Error Codes
10, error code3.6 Description of the Internal Error Codes
11, error code3.6 Description of the Internal Error Codes
13, error code3.6 Description of the Internal Error Codes

2
2, error code3.6 Description of the Internal Error Codes
20, error code3.6 Description of the Internal Error Codes
21, error code3.6 Description of the Internal Error Codes
218 character4.4 Description of the Debugging Tokens
22, error code3.6 Description of the Internal Error Codes
223 character4.4 Description of the Debugging Tokens
23, error code3.6 Description of the Internal Error Codes
24, error code3.6 Description of the Internal Error Codes
25, error code3.6 Description of the Internal Error Codes
26, error code3.6 Description of the Internal Error Codes
27, error code3.6 Description of the Internal Error Codes
28, error code3.6 Description of the Internal Error Codes

3
30, error code3.6 Description of the Internal Error Codes
332 character4.4 Description of the Debugging Tokens
337 character4.4 Description of the Debugging Tokens

4
40, error code3.6 Description of the Internal Error Codes
41, error code3.6 Description of the Internal Error Codes
43, error code3.6 Description of the Internal Error Codes
45, error code3.6 Description of the Internal Error Codes

6
60, error code3.6 Description of the Internal Error Codes
61, error code3.6 Description of the Internal Error Codes
67, error code3.6 Description of the Internal Error Codes

7
70, error code3.6 Description of the Internal Error Codes
72, error code3.6 Description of the Internal Error Codes
73, error code3.6 Description of the Internal Error Codes

A
abort3.4 Generating a Core File on Errors
address list error3.6 Description of the Internal Error Codes
address locating4.3 Environment Variable Name and Features
address setting4.3 Environment Variable Name and Features
admin list error3.6 Description of the Internal Error Codes
alias, shell2.2 Getting Started with the Library
alias, shell4.1 Using a Shell Alias with the Utility
alloc failed error3.6 Description of the Internal Error Codes
alloc-blank4.4 Description of the Debugging Tokens
allocation basics2.3 Basic Description of Terms and Functions
allocation macros3.1 Macros Providing File and Line Information
Allocation of zeros2.3.2 Functionality Supported by All Malloc Libraries
ALLOW_FREE_NULL4.4 Description of the Debugging Tokens
ALLOW_FREE_NULL settings.h option5.2 General Compatibility Concerns
ALLOW_FREE_NULL_MESSAGE3.13 Explanation of the Logfile Output
ALLOW_FREE_NULL_MESSAGE4.4 Description of the Debugging Tokens
ALLOW_REALLOC_NULL settings.h option5.2 General Compatibility Concerns
already free error3.6 Description of the Internal Error Codes
ANSI-C compiler2.1 How to Install the Library
argument checking3.3 Checking of Function Arguments
assembly hacks3.2 Getting Caller Address Information
atexit2.2 Getting Started with the Library
atexit function3.5 Additional Non-standard Routines
authorDebug Malloc Library
automatic shutdown2.2 Getting Started with the Library

B
bad admin structure list3.6 Description of the Internal Error Codes
bad file error3.6 Description of the Internal Error Codes
bad line error3.6 Description of the Internal Error Codes
bad setup error3.6 Description of the Internal Error Codes
bad size error3.6 Description of the Internal Error Codes
bash shell2.2 Getting Started with the Library
bash shell4.1 Using a Shell Alias with the Utility
bash usage4.3 Environment Variable Name and Features
basic allocation information2.3 Basic Description of Terms and Functions
basic definitions2.3.1 General Memory Terms and Concepts
beginning2.2 Getting Started with the Library
blank space4.4 Description of the Debugging Tokens
blank space4.4 Description of the Debugging Tokens
blanking memory4.4 Description of the Debugging Tokens
blanking memory4.4 Description of the Debugging Tokens
bounds checking2.4 General Features of the Library
Bourne shell usage4.3 Environment Variable Name and Features
building the library2.1 How to Install the Library

C
C shell usage4.3 Environment Variable Name and Features
c++ usage3.8 Using the Library with C++
caller address translation3.9.4 Translating Return Addresses into Code Locations
caller's address3.2 Getting Caller Address Information
calloc2.3.2 Functionality Supported by All Malloc Libraries
cannot locate pointer in heap3.6 Description of the Internal Error Codes
catch-null4.4 Description of the Debugging Tokens
catch-signals4.4 Description of the Debugging Tokens
cgi-bin process debugging3.12 Debugging Memory in a Server or Cgi-Bin Process
cgi-bin usage of dmalloc3.12 Debugging Memory in a Server or Cgi-Bin Process
changed memory log3.5 Additional Non-standard Routines
check-blank3.6 Description of the Internal Error Codes
check-blank4.4 Description of the Debugging Tokens
check-fence4.4 Description of the Debugging Tokens
check-funcs4.4 Description of the Debugging Tokens
check-heap2.5 How the Library Checks Your Program
check-heap4.4 Description of the Debugging Tokens
check-heap6. Some Solutions to Common Problems
check-shutdown4.4 Description of the Debugging Tokens
checking arguments3.3 Checking of Function Arguments
checking bounds2.4 General Features of the Library
checkpoint memory usage3.5 Additional Non-standard Routines
child process debugging3.12 Debugging Memory in a Server or Cgi-Bin Process
clearing memory4.4 Description of the Debugging Tokens
clearing memory4.4 Description of the Debugging Tokens
comma separated tokens in env variable4.3 Environment Variable Name and Features
common problems6. Some Solutions to Common Problems
compatibility5.2 General Compatibility Concerns
compiling the library2.1 How to Install the Library
conf.h file2.1 How to Install the Library
configuration file4.5 Format of the Runtime Configuration File
configure script2.1 How to Install the Library
configuring the library2.1 How to Install the Library
constancy verification2.4 General Features of the Library
copying1. Library Copying and Licensing Conditions
core dump2.4 General Features of the Library
core dump3.4 Generating a Core File on Errors
core dump4.4 Description of the Debugging Tokens
core dump4.4 Description of the Debugging Tokens
core dump, none3.4 Generating a Core File on Errors
core file3.4 Generating a Core File on Errors
could not grow heap by allocating memory3.6 Description of the Internal Error Codes
count changed3.5 Additional Non-standard Routines
count number of bytes changed since mark3.5 Additional Non-standard Routines
cpp2.4 General Features of the Library
csh shell2.2 Getting Started with the Library
csh shell4.1 Using a Shell Alias with the Utility
csh usage4.3 Environment Variable Name and Features
current debug value3.5 Additional Non-standard Routines
cygwin3.11 Using the library with Cygwin environment.

D
da character4.4 Description of the Debugging Tokens
daemon process debugging3.12 Debugging Memory in a Server or Cgi-Bin Process
debug setting4.3 Environment Variable Name and Features
debug tokens4.4 Description of the Debugging Tokens
debugger3.4 Generating a Core File on Errors
debugger usage with dmalloc3.9 Using Dmalloc With a Debugger
debugging cgi-bin processes3.12 Debugging Memory in a Server or Cgi-Bin Process
debugging child processes3.12 Debugging Memory in a Server or Cgi-Bin Process
debugging daemon processes3.12 Debugging Memory in a Server or Cgi-Bin Process
debugging server processes3.12 Debugging Memory in a Server or Cgi-Bin Process
decimal 218 character4.4 Description of the Debugging Tokens
decimal 223 character4.4 Description of the Debugging Tokens
delay heap checking4.2 How to Use the Dmalloc Program
delay heap checking4.2 How to Use the Dmalloc Program
delay heap checking4.2 How to Use the Dmalloc Program
destructor2.2 Getting Started with the Library
df character4.4 Description of the Debugging Tokens
diagnosing errors3.9.1 Diagnosing General Problems with a Debugger
disabling library checking3.7 How to Disable the library
disabling the library3.7 How to Disable the library
dmalloc program4. Dmalloc Utility Program
dmalloc utility4. Dmalloc Utility Program
dmalloc.h file3.1 Macros Providing File and Line Information
dmalloc_debug3.7 How to Disable the library
dmalloc_debug function3.5 Additional Non-standard Routines
dmalloc_debug_current function3.5 Additional Non-standard Routines
dmalloc_debug_setup3.5 Additional Non-standard Routines
dmalloc_debug_setup function3.12 Debugging Memory in a Server or Cgi-Bin Process
dmalloc_debug_setup usage3.11 Using the library with Cygwin environment.
dmalloc_errno number3.5 Additional Non-standard Routines
dmalloc_error() routine3.9 Using Dmalloc With a Debugger
dmalloc_examine function3.5 Additional Non-standard Routines
DMALLOC_FUNC_CHECK2.2 Getting Started with the Library
DMALLOC_FUNC_CHECK flag3.3 Checking of Function Arguments
dmalloc_get_stats function3.5 Additional Non-standard Routines
dmalloc_log_changed function3.5 Additional Non-standard Routines
dmalloc_log_stats function3.5 Additional Non-standard Routines
dmalloc_log_unfreed function3.5 Additional Non-standard Routines
dmalloc_logpath variable3.5 Additional Non-standard Routines
dmalloc_mark function3.5 Additional Non-standard Routines
dmalloc_memory_allocated function3.5 Additional Non-standard Routines
dmalloc_message function3.5 Additional Non-standard Routines
DMALLOC_OPTIONS4.3 Environment Variable Name and Features
DMALLOC_OPTIONS6. Some Solutions to Common Problems
dmalloc_shutdown function3.5 Additional Non-standard Routines
DMALLOC_SIZE option2.1 How to Install the Library
dmalloc_strerror function3.5 Additional Non-standard Routines
dmalloc_t test program2.1 How to Install the Library
dmalloc_track function3.5 Additional Non-standard Routines
dmalloc_verify function3.5 Additional Non-standard Routines
dmalloc_verify() routine3.9.1 Diagnosing General Problems with a Debugger
dmalloc_vmessage function3.5 Additional Non-standard Routines
dmallocc.cc3.8 Using the Library with C++
dmallocc.cc file3.8 Using the Library with C++
dmallocrc file4.5 Format of the Runtime Configuration File
dump core2.4 General Features of the Library
dump core3.4 Generating a Core File on Errors
dump core4.4 Description of the Debugging Tokens
dump core4.4 Description of the Debugging Tokens

E
env6. Some Solutions to Common Problems
environment variable4.3 Environment Variable Name and Features
errno value is not valid3.6 Description of the Internal Error Codes
error code 103.6 Description of the Internal Error Codes
error code 113.6 Description of the Internal Error Codes
error code 133.6 Description of the Internal Error Codes
error code 203.6 Description of the Internal Error Codes
error code 213.6 Description of the Internal Error Codes
error code 223.6 Description of the Internal Error Codes
error code 233.6 Description of the Internal Error Codes
error code 243.6 Description of the Internal Error Codes
error code 253.6 Description of the Internal Error Codes
error code 263.6 Description of the Internal Error Codes
error code 273.6 Description of the Internal Error Codes
error code 283.6 Description of the Internal Error Codes
error code 303.6 Description of the Internal Error Codes
error code 403.6 Description of the Internal Error Codes
error code 413.6 Description of the Internal Error Codes
error code 433.6 Description of the Internal Error Codes
error code 453.6 Description of the Internal Error Codes
error code 603.6 Description of the Internal Error Codes
error code 613.6 Description of the Internal Error Codes
error code 673.6 Description of the Internal Error Codes
error code 703.6 Description of the Internal Error Codes
error code 723.6 Description of the Internal Error Codes
error code 733.6 Description of the Internal Error Codes
error code, 13.6 Description of the Internal Error Codes
error code, 23.6 Description of the Internal Error Codes
error codes3.6 Description of the Internal Error Codes
error message3.5 Additional Non-standard Routines
error number3.5 Additional Non-standard Routines
error-abort3.4 Generating a Core File on Errors
error-abort4.4 Description of the Debugging Tokens
error-dump3.4 Generating a Core File on Errors
error-dump4.4 Description of the Debugging Tokens
error-free-null4.4 Description of the Debugging Tokens
error-free-null token3.6 Description of the Internal Error Codes
ERROR_ADDRESS_LIST3.6 Description of the Internal Error Codes
ERROR_ADMIN_LIST3.6 Description of the Internal Error Codes
ERROR_ALLOC_FAILED3.6 Description of the Internal Error Codes
ERROR_ALREADY_FREE3.6 Description of the Internal Error Codes
ERROR_BAD_FILE3.6 Description of the Internal Error Codes
ERROR_BAD_LINE3.6 Description of the Internal Error Codes
ERROR_BAD_SETUP3.6 Description of the Internal Error Codes
ERROR_BAD_SIZE3.6 Description of the Internal Error Codes
ERROR_FREE_OVERWRITTEN3.6 Description of the Internal Error Codes
ERROR_FREE_OVERWRITTEN4.4 Description of the Debugging Tokens
ERROR_IN_TWICE3.6 Description of the Internal Error Codes
ERROR_IS_FOUND3.6 Description of the Internal Error Codes
ERROR_IS_NULL3.6 Description of the Internal Error Codes
ERROR_LOCK_NOT_CONFIG3.6 Description of the Internal Error Codes
ERROR_NONE3.6 Description of the Internal Error Codes
ERROR_NOT_FOUND3.6 Description of the Internal Error Codes
ERROR_NOT_IN_HEAP3.6 Description of the Internal Error Codes
ERROR_NOT_ON_BLOCK3.6 Description of the Internal Error Codes
ERROR_NOT_START_BLOCK3.6 Description of the Internal Error Codes
ERROR_OVER_FENCE3.6 Description of the Internal Error Codes
ERROR_OVER_LIMIT3.6 Description of the Internal Error Codes
ERROR_OVER_LIMIT4.2 How to Use the Dmalloc Program
ERROR_SLOT_CORRUPT3.6 Description of the Internal Error Codes
ERROR_TOO_BIG3.6 Description of the Internal Error Codes
ERROR_UNDER_FENCE3.6 Description of the Internal Error Codes
ERROR_WOULD_OVERWRITE3.6 Description of the Internal Error Codes
examine a pointer3.5 Additional Non-standard Routines
extensions3.5 Additional Non-standard Routines

F
failed over picket-fence magic-number check3.6 Description of the Internal Error Codes
failed under picket-fence magic-number check3.6 Description of the Internal Error Codes
faq6. Some Solutions to Common Problems
features2.4 General Features of the Library
fence-post checking2.4 General Features of the Library
fence-post errors3.9.3 Diagnosing Fence-Post Overwritten Memory
file/line numbers2.4 General Features of the Library
found pointer the user was looking for3.6 Description of the Internal Error Codes
free2.3.2 Functionality Supported by All Malloc Libraries
free null token3.6 Description of the Internal Error Codes
free overwritten error3.6 Description of the Internal Error Codes
free space has been overwritten3.6 Description of the Internal Error Codes
free-blank3.6 Description of the Internal Error Codes
free-blank4.4 Description of the Debugging Tokens
freed memory2.4 General Features of the Library
freed memory2.4 General Features of the Library

G
gcc5.3 Issues Important for Porting the Library
gdb3.9 Using Dmalloc With a Debugger
gdb with shared libraries3.9 Using Dmalloc With a Debugger
general errors3.9.1 Diagnosing General Problems with a Debugger
generating core dump3.4 Generating a Core File on Errors
get heap statistics3.5 Additional Non-standard Routines
getenv, problems with3.11 Using the library with Cygwin environment.
GETENV_SAVE conf.h option3.11 Using the library with Cygwin environment.
GetEnvironmentVariableA, using with3.11 Using the library with Cygwin environment.
gethostname function usage4.2 How to Use the Dmalloc Program
getpid function usage4.2 How to Use the Dmalloc Program
getting started2.2 Getting Started with the Library
getuid function usage4.2 How to Use the Dmalloc Program

H
hanging program6. Some Solutions to Common Problems
HAVE_GETENVIRONMENTVARIABLEA3.11 Using the library with Cygwin environment.
heap memory2.3.1 General Memory Terms and Concepts
heap statistics function3.5 Additional Non-standard Routines
help6. Some Solutions to Common Problems
hexadecimal 0xda character4.4 Description of the Debugging Tokens
hexadecimal 0xdf character4.4 Description of the Debugging Tokens
high token4.5 Format of the Runtime Configuration File
hints that may help3.14 Various Other Hints That May Help
hostname in logfile path4.2 How to Use the Dmalloc Program
how do i...6. Some Solutions to Common Problems
how to begin2.2 Getting Started with the Library
HUP signal4.4 Description of the Debugging Tokens

I
ident6. Some Solutions to Common Problems
in twice error3.6 Description of the Internal Error Codes
initialization and setup failed3.6 Description of the Internal Error Codes
installing the library2.1 How to Install the Library
INT signal4.4 Description of the Debugging Tokens
interaction count3.5 Additional Non-standard Routines
interaction count4.2 How to Use the Dmalloc Program
internal address list corruption3.6 Description of the Internal Error Codes
internal error number3.5 Additional Non-standard Routines
internal memory slot corruption3.6 Description of the Internal Error Codes
INTERNAL_MEMORY_SPACE5.3 Issues Important for Porting the Library
interval setting4.2 How to Use the Dmalloc Program
interval setting4.3 Environment Variable Name and Features
introductionDebug Malloc Library
invalid allocation size3.6 Description of the Internal Error Codes
invalid errno value3.6 Description of the Internal Error Codes
INVALID_ERROR3.6 Description of the Internal Error Codes
is found error3.6 Description of the Internal Error Codes
is null error3.6 Description of the Internal Error Codes
iteration count2.5 How the Library Checks Your Program

J
jump start2.2 Getting Started with the Library

K
kill process3.4 Generating a Core File on Errors
KILL_PROCESS3.4 Generating a Core File on Errors
ksh shell2.2 Getting Started with the Library
ksh shell4.1 Using a Shell Alias with the Utility
ksh usage4.3 Environment Variable Name and Features

L
largest maximum allocation size exceeded3.6 Description of the Internal Error Codes
leaking memory2.4 General Features of the Library
leaking memory3.9.2 Tracking Down Non-Freed Memory
libdmallocxx.a3.8 Using the Library with C++
library permissions1. Library Copying and Licensing Conditions
library utility4. Dmalloc Utility Program
library version4.2 How to Use the Dmalloc Program
license1. Library Copying and Licensing Conditions
lock on3.10 Using the Library with a Thread Package
lock on4.2 How to Use the Dmalloc Program
lock-on3.6 Description of the Internal Error Codes
lock-on not configured3.6 Description of the Internal Error Codes
lockon setting4.3 Environment Variable Name and Features
log memory changes3.5 Additional Non-standard Routines
log statistics3.5 Additional Non-standard Routines
log unfreed memory3.5 Additional Non-standard Routines
log-admin4.4 Description of the Debugging Tokens
log-bad-space4.4 Description of the Debugging Tokens
log-current-time4.4 Description of the Debugging Tokens
log-elapsed-time4.4 Description of the Debugging Tokens
log-known4.4 Description of the Debugging Tokens
log-non-free4.4 Description of the Debugging Tokens
log-nonfree-space4.4 Description of the Debugging Tokens
log-stats4.4 Description of the Debugging Tokens
log-trans4.4 Description of the Debugging Tokens
LOG_ITERATION3.5 Additional Non-standard Routines
LOG_ITERATION4.2 How to Use the Dmalloc Program
LOG_ITERATION_COUNT2.5 How the Library Checks Your Program
logfile format3.13 Explanation of the Logfile Output
logfile message writer3.5 Additional Non-standard Routines
logfile message writer3.5 Additional Non-standard Routines
logfile name3.5 Additional Non-standard Routines
logfile not produced6. Some Solutions to Common Problems
logfile setting4.3 Environment Variable Name and Features
logging information to disk4.3 Environment Variable Name and Features
logging statistics2.4 General Features of the Library
low token4.5 Format of the Runtime Configuration File

M
macros, allocation3.1 Macros Providing File and Line Information
making the library2.1 How to Install the Library
malloc2.3.2 Functionality Supported by All Malloc Libraries
malloc functions2.3.2 Functionality Supported by All Malloc Libraries
malloc library has gone recursive3.6 Description of the Internal Error Codes
mark count4.2 How to Use the Dmalloc Program
mark memory position3.5 Additional Non-standard Routines
medium token4.5 Format of the Runtime Configuration File
memalign3.1 Macros Providing File and Line Information
memory allocated function3.5 Additional Non-standard Routines
memory definitions2.3.1 General Memory Terms and Concepts
memory leaks2.4 General Features of the Library
memory leaks3.9.2 Tracking Down Non-Freed Memory
memory limit3.6 Description of the Internal Error Codes
memory limit4.2 How to Use the Dmalloc Program
memory position marker3.5 Additional Non-standard Routines
memory problems in system functions2.4 General Features of the Library
memory transaction count2.5 How the Library Checks Your Program
memory transaction count4.2 How to Use the Dmalloc Program
missing core dump3.4 Generating a Core File on Errors
mmap3.6 Description of the Internal Error Codes
mmap3.6 Description of the Internal Error Codes
mmap3.9.1 Diagnosing General Problems with a Debugger
mmap4.4 Description of the Debugging Tokens
mmap, usage without5.3 Issues Important for Porting the Library

N
name of host in logfile path4.2 How to Use the Dmalloc Program
never-reuse4.4 Description of the Debugging Tokens
no core dump3.4 Generating a Core File on Errors
no error3.6 Description of the Internal Error Codes
no logfile produced6. Some Solutions to Common Problems
none token4.4 Description of the Debugging Tokens
not found error3.6 Description of the Internal Error Codes
not in heap error3.6 Description of the Internal Error Codes
not on block boundary error3.6 Description of the Internal Error Codes
not start block error3.6 Description of the Internal Error Codes
number bytes changed since mark3.5 Additional Non-standard Routines
number of bytes allocated3.5 Additional Non-standard Routines

O
octal 332 character4.4 Description of the Debugging Tokens
octal 337 character4.4 Description of the Debugging Tokens
on_exit2.2 Getting Started with the Library
on_exit function3.5 Additional Non-standard Routines
other hints3.14 Various Other Hints That May Help
over fence error3.6 Description of the Internal Error Codes
over limit error3.6 Description of the Internal Error Codes
over user specified allocation limit error3.6 Description of the Internal Error Codes
override debug settings3.5 Additional Non-standard Routines
override debug settings3.5 Additional Non-standard Routines
overview2. Description of Features and How to Get Started
overwriting memory4.4 Description of the Debugging Tokens
overwriting memory4.4 Description of the Debugging Tokens

P
page size3.5 Additional Non-standard Routines
permissions of the library1. Library Copying and Licensing Conditions
pid in logfile path4.2 How to Use the Dmalloc Program
pointer information3.5 Additional Non-standard Routines
pointer is not on block boundary3.6 Description of the Internal Error Codes
pointer is not pointing to heap data space3.6 Description of the Internal Error Codes
pointer is not to start of memory block3.6 Description of the Internal Error Codes
pointer is null error3.6 Description of the Internal Error Codes
pointer not found error3.6 Description of the Internal Error Codes
pointer not in heap error3.6 Description of the Internal Error Codes
pointer seen count3.9.2 Tracking Down Non-Freed Memory
portability5.3 Issues Important for Porting the Library
possibly bad .c file line-number3.6 Description of the Internal Error Codes
possibly bad .c filename pointer3.6 Description of the Internal Error Codes
preallocated memory heap5.3 Issues Important for Porting the Library
print-messages4.4 Description of the Debugging Tokens
printenv6. Some Solutions to Common Problems
problems6. Some Solutions to Common Problems
process-id in logfile path4.2 How to Use the Dmalloc Program
program core3.4 Generating a Core File on Errors
programming3. How to Program with the Library
pthreads3.10 Using the Library with a Thread Package

Q
questions6. Some Solutions to Common Problems
quick start2.2 Getting Started with the Library

R
ra3.2 Getting Caller Address Information
ra_info.pl3.2 Getting Caller Address Information
ra_info.pl3.9.4 Translating Return Addresses into Code Locations
rc file4.5 Format of the Runtime Configuration File
rc shell2.2 Getting Started with the Library
reading environment, problems with3.11 Using the library with Cygwin environment.
realloc2.3.2 Functionality Supported by All Malloc Libraries
realloc-copy4.4 Description of the Debugging Tokens
recalloc3.1 Macros Providing File and Line Information
recursion3.6 Description of the Internal Error Codes
report heap statistics3.5 Additional Non-standard Routines
restoring library flags3.7 How to Disable the library
return-address2.4 General Features of the Library
return-address3.2 Getting Caller Address Information
return-address5.3 Issues Important for Porting the Library
return-address translation3.9.4 Translating Return Addresses into Code Locations
return.h file3.2 Getting Caller Address Information
runtime token4.5 Format of the Runtime Configuration File
runtime-config file4.5 Format of the Runtime Configuration File

S
sbrk3.6 Description of the Internal Error Codes
sbrk3.9.1 Diagnosing General Problems with a Debugger
sbrk4.4 Description of the Debugging Tokens
sbrk, usage without5.3 Issues Important for Porting the Library
seen count3.5 Additional Non-standard Routines
seen count3.9.2 Tracking Down Non-Freed Memory
seen count3.13 Explanation of the Logfile Output
server process debugging3.12 Debugging Memory in a Server or Cgi-Bin Process
set debug functionality flags3.5 Additional Non-standard Routines
set debug functionality flags3.5 Additional Non-standard Routines
settings.dist file2.1 How to Install the Library
settings.h file2.1 How to Install the Library
setup debug flags3.5 Additional Non-standard Routines
sh usage4.3 Environment Variable Name and Features
shared libraries with gdb3.9 Using Dmalloc With a Debugger
shell usage4.3 Environment Variable Name and Features
shutdown on signal4.4 Description of the Debugging Tokens
shutdown the library3.5 Additional Non-standard Routines
shutdown, automatic2.2 Getting Started with the Library
SIGHUP4.4 Description of the Debugging Tokens
SIGINT4.4 Description of the Debugging Tokens
signal shutdown4.4 Description of the Debugging Tokens
SIGTERM4.4 Description of the Debugging Tokens
size of memory pages3.5 Additional Non-standard Routines
slot corrupt error3.6 Description of the Internal Error Codes
slow running6. Some Solutions to Common Problems
source code5. Information on the Source Code
source definitions5.1 Definition of Terms and other Information
stack memory2.3.1 General Memory Terms and Concepts
start heap check later4.2 How to Use the Dmalloc Program
start heap check later4.2 How to Use the Dmalloc Program
start heap check later4.2 How to Use the Dmalloc Program
start setting4.3 Environment Variable Name and Features
static memory2.3.1 General Memory Terms and Concepts
statistics2.4 General Features of the Library
statistics logging3.5 Additional Non-standard Routines
STORE_SEEN_COUNT conf.h option3.9.2 Tracking Down Non-Freed Memory
strdup3.1 Macros Providing File and Line Information
string error message3.5 Additional Non-standard Routines
string of debug tokens3.5 Additional Non-standard Routines
strings6. Some Solutions to Common Problems
system memory problems2.4 General Features of the Library

T
tcsh shell2.2 Getting Started with the Library
tcsh shell4.1 Using a Shell Alias with the Utility
tcsh usage4.3 Environment Variable Name and Features
TERM signal4.4 Description of the Debugging Tokens
testing the library2.1 How to Install the Library
thread locking has not been configured3.6 Description of the Internal Error Codes
thread-id in logfile path4.2 How to Use the Dmalloc Program
threads3.10 Using the Library with a Thread Package
time function usage4.2 How to Use the Dmalloc Program
time in logfile path4.2 How to Use the Dmalloc Program
token high4.5 Format of the Runtime Configuration File
token low4.5 Format of the Runtime Configuration File
token medium4.5 Format of the Runtime Configuration File
token runtime4.5 Format of the Runtime Configuration File
tokens, debug4.4 Description of the Debugging Tokens
too big error3.6 Description of the Internal Error Codes
too slow6. Some Solutions to Common Problems
track memory calls3.5 Additional Non-standard Routines
tracking addresses4.3 Environment Variable Name and Features
transaction count3.5 Additional Non-standard Routines
transaction count4.2 How to Use the Dmalloc Program
tried to free previously freed pointer3.6 Description of the Internal Error Codes
troubleshooting6. Some Solutions to Common Problems
turning off library flags3.7 How to Disable the library

U
uid in logfile path4.2 How to Use the Dmalloc Program
under fence error3.6 Description of the Internal Error Codes
unfreed memory log3.5 Additional Non-standard Routines
usage of dmalloc in a daemon3.12 Debugging Memory in a Server or Cgi-Bin Process
usage of dmalloc in a server3.12 Debugging Memory in a Server or Cgi-Bin Process
usage of dmalloc with cgi-bin3.12 Debugging Memory in a Server or Cgi-Bin Process
usage of the utility4.2 How to Use the Dmalloc Program
use of pointer would exceed allocation3.6 Description of the Internal Error Codes
USE_MMAP conf.h option3.6 Description of the Internal Error Codes
USE_RETURN_MACROS conf.h option2.1 How to Install the Library
user-id in logfile path4.2 How to Use the Dmalloc Program
using a debugger with dmalloc3.9 Using Dmalloc With a Debugger
utility program4. Dmalloc Utility Program
utility usage4.2 How to Use the Dmalloc Program
utility version4.2 How to Use the Dmalloc Program

V
valloc3.1 Macros Providing File and Line Information
various hints3.14 Various Other Hints That May Help
verify pointers3.5 Additional Non-standard Routines
verify the heap3.5 Additional Non-standard Routines
version of library3.13 Explanation of the Logfile Output
version of utility4.2 How to Use the Dmalloc Program

W
where to begin2.2 Getting Started with the Library
why hanging6. Some Solutions to Common Problems
why running slow6. Some Solutions to Common Problems
would overwrite error3.6 Description of the Internal Error Codes
write message to logfile3.5 Additional Non-standard Routines
write message to logfile3.5 Additional Non-standard Routines

Z
zeros, allocation of2.3.2 Functionality Supported by All Malloc Libraries
zsh shell2.2 Getting Started with the Library
zsh shell4.1 Using a Shell Alias with the Utility
zsh usage4.3 Environment Variable Name and Features

Jump to:   %   -   .   0   1   2   3   4   6   7  
A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   Z  

[Top] [Contents] [Index] [ ? ]

Table of Contents


[Top] [Contents] [Index] [ ? ]

About This Document

This document was generated by Gray Watson on May, 14 2007 using texi2html 1.76.

The buttons in the navigation panels have the following meaning:

Button Name Go to From 1.2.3 go to
[ < ] Back previous section in reading order 1.2.2
[ > ] Forward next section in reading order 1.2.4
[ << ] FastBack beginning of this chapter or previous chapter 1
[ Up ] Up up section 1.2
[ >> ] FastForward next chapter 2
[Top] Top cover (top) of document  
[Contents] Contents table of contents  
[Index] Index index  
[ ? ] About about (help)  

where the Example assumes that the current position is at Subsubsection One-Two-Three of a document of the following structure:

  • 1. Section One
    • 1.1 Subsection One-One
      • ...
    • 1.2 Subsection One-Two
      • 1.2.1 Subsubsection One-Two-One
      • 1.2.2 Subsubsection One-Two-Two
      • 1.2.3 Subsubsection One-Two-Three     <== Current Position
      • 1.2.4 Subsubsection One-Two-Four
    • 1.3 Subsection One-Three
      • ...
    • 1.4 Subsection One-Four

This document was generated by Gray Watson on May, 14 2007 using texi2html 1.76.

dmalloc-5.5.2/docs/dmalloc.texi000640 001751 001751 00000417572 10622115666 016365 0ustar00graygray000000 000000 \input texinfo @c -*-texinfo-*- @c %**start of header @setfilename dmalloc.info @settitle Dmalloc Tutorial @setchapternewpage odd @headings double @c %**end of header @dircategory Libraries @direntry * Dmalloc: (dmalloc). Malloc debug library. @end direntry @c ---------------------------------------------------------------- @c $Id: dmalloc.texi,v 1.295 2007/05/14 17:23:37 gray Exp $ @c ---------------------------------------------------------------- @c ---------------------------------------------------------------- @set dmalloc_version Version 5.5.2 @set dmalloc_date May 2007 @set dmalloc_copyright Copyright 1992 to 2007 by Gray Watson. @c ---------------------------------------------------------------- @ifinfo This file is an introduction to the Dmalloc library which handles general memory heap management. @value{dmalloc_copyright} Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. @ignore Permission is granted to process this file through TeX and print the results, provided the printed document carries a copying permission notice identical to this one except for the removal of this paragraph (this paragraph not being relevant to the printed manual). @end ignore Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the chapter entitled ``Copying'' are included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the chapter entitled ``Copying'' may be included in a translation approved by the author instead of in the original English. @end ifinfo @titlepage @title Debug Malloc Library @subtitle @value{dmalloc_version} @subtitle @value{dmalloc_date} @author Gray Watson @page @value{dmalloc_copyright} Published by Gray Watson Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the chapter entitled ``Copying'' are included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the chapter entitled ``Copying'' may be included in a translation approved by the author instead of in the original English. @end titlepage @c -------------------------------- @node Top, Copying, (dir), (dir) @top Debug Malloc Library @ifinfo @value{dmalloc_version} -- @value{dmalloc_date} @end ifinfo @cindex introduction @cindex author The debug memory allocation or @dfn{dmalloc} library has been designed as a drop in replacement for the system's @code{malloc}, @code{realloc}, @code{calloc}, @code{free} and other memory management routines while providing powerful debugging facilities configurable at runtime. These facilities include such things as memory-leak tracking, fence-post write detection, file/line number reporting, and general logging of statistics. The library is reasonably portable having been run successfully on at least the following operating systems: AIX, DGUX, Free/Net/OpenBSD, GNU/Hurd, HPUX, Irix, Linux, Mac OSX, NeXT, OSF/DUX, SCO, Solaris, Ultrix, Unixware, MS Windows, and Unicos on a Cray T3E. It also provides support for the debugging of threaded programs. @xref{Using With Threads}. The package includes the library, configuration scripts, debug utility application, test program, and documentation. Online documentation as well as the full source is available at URL @uref{http://dmalloc.com/}. Details on the library's mailing list are available there as well. Please use the forums at URL @uref{http://dmalloc.com/} to discuss any problems or to request features. If you are still having problems, the author can be reached via his home page at URL @uref{http://256.com/gray/} with questions or feedback. Please include the version number of the library that you are using, your machine and operating system types, and the value of the DMALLOC_OPTIONS environment variable. Gray Watson. @menu * Copying:: Library copying and licensing conditions. * Overview:: Description of features and how to get started. * Programming:: How to program with the library. * Dmalloc Program:: How to use the library's utility. * Source Code:: Information on the source code. * Troubleshooting:: Some solutions to common problems. * Index of Concepts:: Index of concepts in the manual. @end menu @c ---------------------------------------------------------------------------- @node Copying, Overview, Top, Top @chapter Library Copying and Licensing Conditions @cindex copying @cindex license @cindex library permissions @cindex permissions of the library @value{dmalloc_copyright} Permission to use, copy, modify, and distribute this software for any purpose and without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies, and that the name of Gray Watson not be used in advertising or publicity pertaining to distribution of the document or software without specific, written prior permission. Gray Watson makes no representations about the suitability of the software described herein for any purpose. It is provided ``as is'' without express or implied warranty. @c ---------------------------------------------------------------------------- @node Overview, Programming, Copying, Top @chapter Description of Features and How to Get Started @cindex overview @menu * Installation:: How to install the library. * Getting Started:: Getting started with the library. * Allocation Basics:: Basic description of terms and functions. * Features:: General features of the library. * How It Works:: How the library checks your program. @end menu @c -------------------------------- @node Installation, Getting Started, Overview, Overview @section How to Install the Library @cindex installing the library @cindex compiling the library @cindex building the library @cindex configuring the library @cindex making the library To configure, compile, and install the library, follow these steps carefully. @enumerate @item Make sure you have downloaded the latest version of the library available from the home page at URL @uref{http://dmalloc.com/}. @item The release files have a @file{.tgz} file extension which means that they are a tar'd gzip'd directory of files. You will need to ungzip and then untar the release file into your source work directory. You may have to rename the file to @file{.tar.gz} to get some old zip programs to handle the file correctly. @cindex settings.dist file @item You may want to edit or at least review the settings in @file{settings.dist} to tune specific features of the library. The @file{configure} script will copy this file to @file{settings.h} which is where you should be adding per-architecture settings. @cindex configure script @cindex --disable-cxx @cindex --enable-threads @cindex --enable-shlib @cindex conf.h file @item Type @kbd{sh ./configure} to configure the library. You may want to first examine the @file{config.help} file for some information about configure. You may want to use the @kbd{--disable-cxx} option if you do not want the Makefile to build the C++ version of dmalloc. You may want to use the @kbd{--enable-threads} option to build the threaded version of dmalloc. You may want to use the @kbd{--enable-shlib} option to build the shared versions of the dmalloc libraries. @kbd{sh ./configure --help} lists the available options to configure. Configure should generate the @file{Makefile} and configuration files automatically. @item You may want to examine the @file{Makefile} and @file{conf.h} files created by configure to make sure it did its job correctly. @cindex settings.h file @item You might want to tune the settings in @file{settings.h} file to tune the library to the local architecture. This file contains relevant settings if you are using pthreads or another thread library. @xref{Using With Threads}. The @file{configure} script created this file from the @file{settings.dist} file. Any permanent changes to these settings should made to the @file{settings.dist} file. You then can run @file{config.status} to re-create the @file{settings.h} file. @cindex DMALLOC_SIZE option @item The @code{DMALLOC_SIZE} variable gets auto-configured in @file{dmalloc.h.2} but it may not generate correct settings for all systems. You may have to alter the definitions in this file to get things to stop complaining when you go to compile about the size arguments to malloc routines. Comments on this please. @item Typing @kbd{make} should be enough to build @file{libdmalloc.a}, and @file{dmalloc} program. If it does not work, please see if there are any notes in the contrib directory about your system-type. If not and you figure your problem out, please send me some notes so future users can profit from your experiences. @cindex USE_RETURN_MACROS conf.h option @emph{NOTE}: You may experience some errors compiling some of the @file{return.h} assembly macros which attempt to determine the callers address for logging purposes. @xref{Portability}. You may want to first try disabling any compiler optimization flags. If this doesn't work then you may need to disable the @samp{USE_RETURN_MACROS} variable in the @file{settings.h} file. @cindex ANSI-C compiler @emph{NOTE}: The code is dependent on an ANSI-C compiler. If the configure script gives the @samp{WARNING} that you do not have an ANSI-C compiler, you may still be able to add some sort of option to your compiler to make it ANSI. If there such is an option, please send it to the author so it can be added to the configure script. @item If you use threads and did not add the @kbd{--enable-threads} argument to configure, typing @kbd{make threads} should be enough to build @file{libdmallocth.a} which is the threaded version of the library. This may or may not work depending on the configuration scripts ability to detect your local thread functionality. Feel free to send me mail with improvements. See the section of the manual on threads for more information about the operation of the library with your threaded program. @xref{Using With Threads}. @item If you have a C++ compiler installed, the library should have automatically built @file{libdmallocxx.a} which is the C++ version of the library. If it was not done automatically, you can build it by typing @kbd{make cxx}. You should link this library into your C++ programs instead of @file{libdmalloc.a}. See the @file{dmallocc.cc} C++ file which contains basic code to overload the @code{new}, @code{new[]}, @code{delete}, and @code{delete[]} C++ operators. My apologies on the minimal C++ support. I am still living in a mostly C world. Any help improving this interface without sacrificing portability would be appreciated. @cindex testing the library @cindex dmalloc_t test program @item Typing @kbd{make light} should build and run the @file{dmalloc_t} test program through a set of light trials. By default this will execute @file{dmalloc_t} 5 times -- each time will execute 10,000 malloc operations in a very random manner. Anal folks can type @kbd{make heavy} to up the ante. Use @kbd{dmalloc_t --usage} for the list of all @file{dmalloc_t} options. @item Typing @kbd{make install} should install the @file{libdmalloc.a} library in @file{/usr/local/lib}, the @file{dmalloc.h} include file in @file{/usr/local/include}, and the @file{dmalloc} utility in @file{/usr/local/bin}. You may also want to type @kbd{make installth} to install the thread library into place and/or @kbd{make installcc} to install the C++ library into place. You may have specified a @samp{--prefix=PATH} option to configure in which case @samp{/usr/local} will have been replaced with @samp{PATH}. @end enumerate See the ``Getting Started'' section to get up and running with the library. @xref{Getting Started}. @c -------------------------------- @node Getting Started, Allocation Basics, Installation, Overview @section Getting Started with the Library @cindex quick start @cindex getting started @cindex jump start @cindex how to begin @cindex where to begin @cindex beginning This section should give you a quick idea on how to get going. Basically, you need to do the following things to make use of the library: @enumerate @item Make sure you have downloaded the latest version of the library available from the home page at URL @uref{http://dmalloc.com/}. @item Follow the installation instructions on how to configure, make, and install the library (i.e. type: @kbd{make install}). @xref{Installation}. @cindex automatic shutdown @cindex shutdown, automatic @cindex on_exit @cindex atexit @cindex destructor @item You need to make sure that the library configuration and build process above was able to locate one of the @code{on_exit} function, @code{atexit} function, or had compiler destructor support. If one of these functions or support is available then the dmalloc library should be able to automatically shut itself down when the program exits. This causes the memory statistics and unfreed information to be dumped to the log file. However, if your system has none of the above, then you will need to call @code{dmalloc_shutdown} yourself before your program exits. @cindex alias, shell @cindex bash shell @cindex ksh shell @cindex zsh shell @item To get the dmalloc utility to work you need to add an alias for dmalloc to your shell's runtime configuration file if supported. The idea is to have the shell capture the dmalloc program's output and adjust the environment. After you add the alias to the shell config file you need to log out and log back in to have it take effect, or you can execute the appropriate command below on the command line directly. After you setup the alias, if you enter @kbd{dmalloc runtime} and see any output with DMALLOC_OPTIONS in it then the alias did not take effect. Bash, ksh, and zsh (@uref{http://www.zsh.org/}) users should add the following to their @file{.bashrc}, @file{.profile}, or @file{.zshrc} file respectively (notice the @kbd{-b} option for bourne shell output): @example function dmalloc @{ eval `command dmalloc -b $*`; @} @end example If your shell does not support the @code{command} function then try: @example function dmalloc @{ eval `\dmalloc -b $*`; @} @end example or @example function dmalloc @{ eval `/usr/local/bin/dmalloc -b $*`; @} @end example @cindex csh shell @cindex tcsh shell If you are still using csh or tcsh, you should add the following to your @file{.cshrc} file (notice the @kbd{-C} option for c-shell output): @example alias dmalloc 'eval `\dmalloc -C \!*`' @end example @cindex rc shell If you are using rc shell, you should add the following to your @file{.rcrc} file (notice the @kbd{-R} option for rc-shell output): @example fn dmalloc @{eval `@{/usr/local/bin/dmalloc $*@}@} @end example @item Although not necessary, you may want to include @file{dmalloc.h} in your C files and recompile. This will allow the library to report the file/line numbers of calls that generate problems. @xref{Allocation Macros}. It should be inserted at the @emph{bottom} of your include files as to not conflict with wother includes. You may want to ifdef it as well and compile with @kbd{cc -DDMALLOC @dots{}}: @example /* other includes above ^^^ */ #ifdef DMALLOC #include "dmalloc.h" #endif @end example @cindex DMALLOC_FUNC_CHECK @item Another optional task is to compile all of your source with the @file{dmalloc.h} with the @code{DMALLOC_FUNC_CHECK} compilation flag. This willallow the library to check all of the arguments of a number of common string and utility routines. @xref{Argument Checking}. @example cc -DDMALLOC -DDMALLOC_FUNC_CHECK file.c @end example @item Link the dmalloc library into your program. The dmalloc library should probably be placed at or near the end of the library list. @item Enable the debugging features by typing @kbd{dmalloc -l logfile -i 100 low} (for example). You should not see any messages printed by the dmalloc utility (see NOTE below). This will: @itemize @bullet @item Set the malloc logfile name to @file{logfile} (@kbd{-l logfile}). For programs which change directories, you may want to specify the full path to your logfile. @item Have the library check itself every 100 iterations (@kbd{-i 100}). This controls how fast your program will run. Larger numbers check the heap less and so it will run faster. Lower numbers will be more likely to catch memory problems. @item Enable a number of debug features (@kbd{low}). You can also try @kbd{runtime} for minimal checking or @kbd{medium} or @kbd{high} for more extensive heap verification. @item By default, the low, medium, and high values enable the @code{error-abort} token which will cause the library to abort and usually dump core immediately upon seeing an error. @xref{Dumping Core}. You can disable this feature by entering @kbd{dmalloc -m error-abort} (-m for minus) to remove the @code{error-abort} token and your program will just log errors and continue. @end itemize @kbd{dmalloc --usage} will provide verbose usage info for the dmalloc program. @xref{Dmalloc Program}. You may also want to install the @file{dmallocrc} file in your home directory as @file{.dmallocrc}. This allows you to add your own combination of debug tokens. @xref{RC File}. @emph{NOTE}: The output from the dmalloc utility should be captured by your shell. If you see a bunch of stuff which includes the string @code{DMALLOC_OPTIONS} then the alias you should have created above is not working and he environmental variables are not being set. Make sure you've logged out and back in to have the alias take effect. @item Run your program, examine the logfile that should have been created by @code{dmalloc_shutdown}, and use its information to help debug your program. @end enumerate @c -------------------------------- @node Allocation Basics, Features, Getting Started, Overview @section Basic Description of Terms and Functions @cindex allocation basics @cindex basic allocation information @menu * Basic Definitions:: General memory terms and concepts. * Malloc Functions:: Functionality supported by all malloc libs. @end menu @c -------------------------------- @node Basic Definitions, Malloc Functions, Allocation Basics, Allocation Basics @subsection General Memory Terms and Concepts @cindex basic definitions @cindex memory definitions Any program can be divided into 2 logical parts: text and data. Text is the actual program code in machine-readable format and data is the information that the text operates on when it is executing. The data, in turn, can be divided into 3 logical parts according to where it is stored: @dfn{static}, @dfn{stack}, and @dfn{heap}. @cindex static memory Static data is the information whose storage space is compiled into the program. @example /* global variables are allocated as static data */ int numbers[10]; main() @{ @dots{} @} @end example @cindex stack memory Stack data is data allocated at runtime to hold information used inside of functions. This data is managed by the system in the space called stack space. @example void foo() @{ /* this local variable is stored on the stack */ float total; @dots{} @} main() @{ foo(); @} @end example @cindex heap memory Heap data is also allocated at runtime and provides a programmer with dynamic memory capabilities. @example main() @{ /* the address is stored on the stack */ char * string; @dots{} /* * Allocate a string of 10 bytes on the heap. Store the * address in string which is on the stack. */ string = (char *)malloc(10); @dots{} /* de-allocate the heap memory now that we're done with it */ (void)free(string); @dots{} @} @end example It is the heap data that is managed by this library. Although the above is an example of how to use the malloc and free commands, it is not a good example of why using the heap for runtime storage is useful. Consider this: You write a program that reads a file into memory, processes it, and displays results. You would like to handle files with arbitrary size (from 10 bytes to 1.2 megabytes and more). One problem, however, is that the entire file must be in memory at one time to do the calculations. You don't want to have to allocate 1.2 megabytes when you might only be reading in a 10 byte file because it is wasteful of system resources. Also, you are worried that your program might have to handle files of more than 1.2 megabytes. A solution: first check out the file's size and then, using the heap-allocation routines, get enough storage to read the entire file into memory. The program will only be using the system resources necessary for the job and you will be guaranteed that your program can handle any sized file. @c -------------------------------- @node Malloc Functions,, Basic Definitions, Allocation Basics @subsection Functionality Supported by All Malloc Libraries @cindex malloc functions All malloc libraries support 4 basic memory allocation commands. These include @dfn{malloc}, @dfn{calloc}, @dfn{realloc}, and @dfn{free}. For more information about their capabilities, check your system's manual pages -- in unix, do a @code{man 3 malloc}. @cindex malloc @deftypefun void *malloc ( unsigned int @var{size} ) Usage: @code{pnt = (type *)malloc(size)} The malloc routine is the basic memory allocation routine. It allocates an area of @code{size} bytes. It will return a pointer to the space requested. @end deftypefun @deftypefun void *calloc ( unsigned int @var{number}, unsigned int@var{size} ) @cindex calloc @cindex Allocation of zeros @cindex zeros, allocation of Usage: @code{pnt = (type *)calloc(number, size)} The calloc routine allocates a certain @code{number} of items, each of @code{size} bytes, and returns a pointer to the space. It is appropriate to pass in a @code{sizeof(type)} value as the size argument. Also, calloc nulls the space that it returns, assuring that the memory is all zeros. @end deftypefun @deftypefun void *realloc ( void *@var{old_pnt}, unsigned int @var{new_size} ) @cindex realloc Usage: @code{new_pnt = (type *)realloc(old_pnt, new_size)} The realloc function expands or shrinks the memory allocation in @code{old_pnt} to @code{new_size} number of bytes. Realloc copies as much of the information from @code{old_pnt} as it can into the @code{new_pnt} space it returns, up to @code{new_size} bytes. If there is a problem allocating this memory, 0L will be returned. If the @code{old_pnt} is 0L then realloc will do the equivalent of a @code{malloc(new_size)}. If @code{new_size} is 0 and @code{old_pnt} is not 0L, then it will do the equivalent of @code{free(old_pnt)} and will return 0L. @end deftypefun @deftypefun void free ( void *@var{pnt} ) @cindex free Usage: @code{free(pnt)} The free routine releases allocation in @code{pnt} which was returned by malloc, calloc, or realloc back to the heap. This allows other parts of the program to re-use memory that is not needed anymore. It guarantees that the process does not grow too big and swallow a large portion of the system resources. @end deftypefun @emph{WARNING}: there is a quite common myth that all of the space that is returned by malloc libraries has already been cleared. @emph{Only} the @code{calloc} routine will zero the memory space it returns. @c -------------------------------- @node Features, How It Works, Allocation Basics, Overview @section General Features of the Library @cindex features The debugging features that are available in this debug malloc library can be divided into a couple basic classifications: @table @asis @item file and line number information @cindex file/line numbers @cindex cpp One of the nice things about a good debugger is its ability to provide the file and line number of an offending piece of code. This library attempts to give this functionality with the help of @dfn{cpp}, the C preprocessor. @xref{Allocation Macros}. @item return-address information @cindex return-address To debug calls to the library from external sources (i.e. those files that could not use the allocation macros), some facilities have been provided to supply the caller's address. This address, with the help of a debugger, can help you locate the source of a problem. @xref{Return Address}. @item fence-post (i.e. bounds) checking @cindex fence-post checking @cindex bounds checking @cindex checking bounds @dfn{Fence-post} memory is the area immediately above or below memory allocations. It is all too easy to write code that accesses above or below an allocation -- especially when dealing with arrays or strings. The library can write special values in the areas around every allocation so it will notice when these areas have been overwritten. @xref{Fence-Post Overruns}. @emph{NOTE}: The library cannot notice when the program @emph{reads} from these areas, only when it writes values. Also, fence-post checking will increase the amount of memory the program allocates. @item heap-constancy verification @cindex constancy verification The administration of the library is reasonably complex. If any of the heap-maintenance information is corrupted, the program will either crash or give unpredictable results. By enabling heap-consistency checking, the library will run through its administrative structures to make sure all is in order. This will mean that problems will be caught faster and diagnosed better. The drawback of this is, of course, that the library often takes quite a long time to do this. It is suitable to enable this only during development and debugging sessions. @emph{NOTE}: the heap checking routines cannot guarantee that the tests will not cause a segmentation-fault if the heap administration structures are properly (or improperly if you will) overwritten. In other words, the tests will verify that everything is okay but may not inform the user of problems in a graceful manner. @item logging statistics @cindex logging statistics @cindex statistics @cindex memory leaks @cindex leaking memory One of the reasons why the debug malloc library was initially developed was to track programs' memory usage -- specifically to locate @dfn{memory leaks} which are places where allocated memory is never getting freed. @xref{Memory Leaks}. The library has a number of logging capabilities that can track un-freed memory pointers as well as runtime memory usage, memory transactions, administrative actions, and final statistics. @item examining freed memory @cindex freed memory @cindex freed memory Another common problem happens when a program frees a memory pointer but goes on to use it again by mistake. This can lead to mysterious crashes and unexplained problems. To combat this, the library can write special values into a block of memory after it has been freed. This serves two purposes: it will make sure that the program will get garbage data if it trying to access the area again, and it will allow the library to verify the area later for signs of overwriting. @end table If any of the above debugging features detect an error, the library will try to recover. If logging is enabled then an error will be logged with as much information as possible. The error messages that the library displays are designed to give the most information for developers. If the error message is not understood, then it is most likely just trying to indicate that a part of the heap has been corrupted. @cindex dump core @cindex core dump The library can be configured to quit immediately when an error is detected and to dump a core file or memory-image. This can be examined with a debugger to determine the source of the problem. The library can either stop after dumping core or continue running. @xref{Dumping Core}. @cindex system memory problems @cindex memory problems in system functions @emph{NOTE}: do not be surprised if the library catches problems with your system's routines. It took me hours to finally come to the conclusion that the localtime call, included in SunOS release 4.1, overwrites one of its fence-post markers. @c -------------------------------- @node How It Works,, Features, Overview @section How the Library Checks Your Program This is one of the newer sections of the library implying that it is incomplete. If you have any questions or issues that you'd like to see handled here, please let me know. The dmalloc library replaces the heap library calls normally found in your system libraries with its own versions. When you make a call to malloc (for example), you are calling dmalloc's version of the memory allocation function. When you allocate memory with these functions, the dmalloc library keeps track of a number of pieces of debugging information about your pointer including: where it was allocated, exactly how much memory was requested, when the call was made, etc.. This information can then be verified when the pointer is freed or reallocated and the details can be logged on any errors. Whenever you reallocate or free a memory address, the dmalloc library always performs a number of checks on the pointer to make sure that it is valid and has not been corrupted. You can configure the library to perform additional checks such as detected fence-post writing. The library can also be configured to overwrite memory with non-zeros (only if calloc is not called) when it is allocated and erase the memory when the pointers are freed. @cindex check-heap In addition to per-pointer checks, you can configure the library to perform complete heap checks. These complete checks verify all internal heap structures and include walking all of the known allocated pointers to verify each one in turn. You need this level of checking to find random pointers in your program which got corrupted but that won't be freed for a while. To turn on these checks, you will need to enable the @code{check-heap} debug token. @xref{Debug Tokens}. By default this will cause the heap to be fully checked each and every time dmalloc is called whether it is a malloc, free, realloc, or another dmalloc overloaded function. Performing a full heap check can take a good bit of CPU and it may be that you will want to run it sporadically. This can be accomplished in a couple different ways including the '-i' interval argument to the dmalloc utility. @xref{Dmalloc Program}. This will cause the check to be run every N-th time. For instance, 'dmalloc -i 3' will cause the heap to be checked before every 3rd call to a memory function. Values of 100 or even 1000 for high memory usage programs are more useful than smaller ones. @cindex LOG_ITERATION_COUNT @cindex iteration count @cindex memory transaction count You can also cause the program to start doing detailed heap checking after a certain point. For instance, with 'dmalloc -s 1000' option, you can tell the dmalloc library to enable the heap checks after the 1000th memory call. Examine the dmalloc log file produced and use the iteration count if you have @code{LOG_ITERATION_COUNT} enabled in your @file{settings.h} file. The start option can also have the format @samp{file:line}. For instance, if it is set to @samp{dmalloc_t.c:126}, dmalloc will start checking the heap after it sees a dmalloc call from the @file{dmalloc_t.c} file, line number 126. If you use @samp{dmalloc_t.c:0}, with a 0 line number, then dmalloc will start checking the heap after it sees a call from anywhere in the @file{dmalloc_t.c} file. @c ---------------------------------------------------------------------------- @node Programming, Dmalloc Program, Overview, Top @chapter How to Program with the Library @cindex programming @menu * Allocation Macros:: Macros providing file and line information. * Return Address:: Getting caller address information. * Argument Checking:: Checking of function arguments. * Dumping Core:: Generating a core file on errors for debugging. * Extensions:: Additional non-standard routines. * Error Codes:: Description of the internal error numbers. * Disabling the Library:: How to disable the library. * Using With C++:: Using the library with C++. * Using With a Debugger:: Using a debugger with the library. * Using With Threads:: Using the library with a thread package. * Using With Cygwin:: Using the library with Cygwin environment. * Debugging A Server:: Debugging memory in a server or cgi-bin process. * Logfile Details:: Explanation of the Logfile Output. * Other Hints:: Various other hints that may help. @end menu @c -------------------------------- @node Allocation Macros, Return Address, Programming, Programming @section Macros Providing File and Line Information @cindex allocation macros @cindex macros, allocation @cindex dmalloc.h file By including @file{dmalloc.h} in your C files, your calls to malloc, calloc, realloc, recalloc, memalign, valloc, strdup, and free are replaced with calls to _dmalloc_malloc, _dmalloc_realloc, and _dmalloc_free with various flags. Additionally the library replaces calls to xmalloc, xcalloc, xrealloc, xrecalloc, xmemalign, xvalloc, xstrdup, and xfree with associated calls. These macros use the c-preprocessor @code{__FILE__} and @code{__LINE__} macros which get replaced at compilation time with the current file and line-number of the source code in question. The routines use this information to produce verbose reports on memory problems. @example not freed: '0x38410' (22 bytes) from 'dmalloc_t.c:92' @end example This line from a log file shows that memory was not freed from file @file{dmalloc_t.c} line 92. @xref{Memory Leaks}. @cindex recalloc @cindex memalign @cindex valloc @cindex strdup You may notice some non standard memory allocation functions in the above list. Recalloc is a routine like realloc that reallocates previously allocated memory to a new size. If the new memory size is larger than the old, recalloc initializes the new space to all zeros. This may or may not be supported natively by your operating system. Memalign is like malloc but should insure that the returned pointer is aligned to a certain number of specified bytes. Currently, the memalign function is not supported by the library. It defaults to returning possibly non-aligned memory for alignment values less than a block-size. Valloc is like malloc but insures that the returned pointer will be aligned to a page boundary. This may or may not be supported natively by your operating system but is fully supported by the library. Strdup is a string duplicating routine which takes in a null terminated string pointer and returns an allocated copy of the string that will need to be passed to free later to deallocate. The X versions of the standard memory functions (xmalloc, xfree, etc.) will print out an error message to standard error and will stop if the library is unable to allocate any additional memory. It is useful to use these routines instead of checking everywhere in your program for allocation routines returning NULL pointers. @emph{WARNING}: If you are including the @file{dmalloc.h} file in your sources, it is recommended that it be at the end of your include file list because dmalloc uses macros and may try to change declarations of the malloc functions if they come after it. @c -------------------------------- @node Return Address, Argument Checking, Allocation Macros, Programming @section Getting Caller Address Information @cindex caller's address @cindex return-address @cindex return.h file @cindex ra Even though the allocation macros can provide file/line information for some of your code, there are still modules which either you can't include @file{dmalloc.h} (such as library routines) or you just don't want to. You can still get information about the routines that call dmalloc function from the return-address information. To accomplish this, you must be using this library on one of the supported architecture/compilers. @xref{Portability}. @cindex assembly hacks The library attempts to use some assembly hacks to get the return-address or the address of the line that called the dmalloc function. If you have unfreed memory that does not have associated file and line information, you might see the following non-freed memory messages. @example not freed: '0x38410' (22 bytes) from 'ra=0xdd2c' not freed: '0x38600' (10232 bytes) from 'ra=0x10234d' not freed: '0x38220' (137 bytes) from 'ra=0x82cc' @end example @cindex ra_info.pl With the help of a debugger, these return-addresses (or ra) can then be identified. I've provided a @file{ra_info.pl} perl script in the @file{contrib/} directory with the dmalloc sources which seems to work well with gdb. You can also use manual methods for gdb to find the return-address location. @xref{Translate Return Addresses}. @c -------------------------------- @node Argument Checking, Dumping Core, Return Address, Programming @section Checking of Function Arguments @cindex argument checking @cindex checking arguments @cindex DMALLOC_FUNC_CHECK flag One potential problem with the library and its multitude of checks and diagnoses is that they only get performed when a dmalloc function is called. One solution this is to include @file{dmalloc.h} and compile your source code with the @code{DMALLOC_FUNC_CHECK} flag defined and enable the @code{check-funcs} token. @xref{Debug Tokens}. @example cc -DDMALLOC -DDMALLOC_FUNC_CHECK file.c @end example @emph{NOTE}: Once you have compiled your source with DMALLOC_FUNC_CHECK enabled, you will have to recompile with it off to disconnect the library. @xref{Disabling the Library}. @emph{WARNING}: You should be sure to have @file{dmalloc.h} included at the end of your include file list because dmalloc uses macros and may try to change declarations of the checked functions if they come after it. When this is defined dmalloc will override a number of functions and will insert a routine which knows how to check its own arguments and then call the real function. Dmalloc can check such functions as @code{bcopy}, @code{index}, @code{strcat}, and @code{strcasecmp}. For the full list see the end of @file{dmalloc.h}. When you call @code{strlen}, for instance, dmalloc will make sure the string argument's fence-post areas have not been overwritten, its file and line number locations are good, etc. With @code{bcopy}, dmalloc will make sure that the destination string has enough space to store the number of bytes specified. For all of the arguments checked, if the pointer is not in the heap then it is ignored since dmalloc does not know anything about it. @c -------------------------------- @node Dumping Core, Extensions, Argument Checking, Programming @section Generating a Core File on Errors @cindex dump core @cindex core dump @cindex generating core dump @cindex error-abort @cindex error-dump @cindex debugger If the @code{error-abort} debug token has been enabled, when the library detects any problems with the heap memory, it will immediately attempt to dump a core file. @xref{Debug Tokens}. Core files are a complete copy of the program and it's state and can be used by a debugger to see specifically what is going on when the error occurred. @xref{Using With a Debugger}. By default, the low, medium, and high arguments to the library utility enable the @code{error-abort} token. You can disable this feature by entering @kbd{dmalloc -m error-abort} (-m for minus) to remove the @code{error-abort} token and your program will just log errors and continue. You can also use the @code{error-dump} token which tries to dump core when it sees an error but still continue running. @xref{Debug Tokens}. @cindex core file @cindex program core @cindex no core dump @cindex core dump, none @cindex missing core dump When a program dumps core, the system writes the program and all of its memory to a file on disk usually named @file{core}. If your program is called @file{foo} then your system may dump core as @file{foo.core}. If you are not getting a @file{core} file, make sure that your program has not changed to a new directory meaning that it may have written the core file in a different location. Also insure that your program has write privileges over the directory that it is in otherwise it will not be able to dump a core file. Core dumps are often security problems since they contain all program memory so systems often block their being produced. You will want to check your user and system's core dump size ulimit settings. @cindex abort @cindex kill process @cindex KILL_PROCESS The library by default uses the @code{abort} function to dump core which may or may not work depending on your operating system. If the following program does not dump core then this may be the problem. See @code{KILL_PROCESS} definition in @file{settings.dist}. @example main() @{ abort(); @} @end example If @code{abort} does work then you may want to try the following setting in @file{settings.dist}. This code tries to generate a segmentation fault by dereferencing a @code{NULL} pointer. @example #define KILL_PROCESS @{ int *_int_p = 0L; *_int_p = 1; @} @end example @c -------------------------------- @node Extensions, Error Codes, Dumping Core, Programming @section Additional Non-standard Routines @cindex extensions The library has a number of variables that are not a standard part of most malloc libraries: @c -------------------------------- @cindex dmalloc_errno number @cindex internal error number @cindex error number @deftypevar int dmalloc_errno This variable stores the internal dmalloc library error number like errno does for the system calls. It can be passed to @code{dmalloc_strerror()} (see below) to get a string version of the error. It will have a value of zero if the library has not detected any problems. @end deftypevar @c -------------------------------- @cindex dmalloc_logpath variable @cindex logfile name @deftypevar char* dmalloc_logpath This variable can be used to set the dmalloc log filename. The env variable @code{DMALLOC_LOGFILE} overrides this variable. @c -------------------------------- @end deftypevar Additionally the library provides a number of non-standard malloc routines: @c -------------------------------- @cindex dmalloc_shutdown function @cindex shutdown the library @deftypefun void dmalloc_shutdown ( void ) @cindex atexit function @cindex on_exit function This function shuts the library down and logs the final statistics and information especially the non-freed memory pointers. The library has code to support auto-shutdown if your system has the @code{on_exit()} call, @code{atexit()} call, or compiler destructor support (see @file{conf.h}). If you do not have these, then @code{dmalloc_shutdown} should be called right before @code{exit()} or as the last function in @code{main()}. @example main() @{ @dots{} dmalloc_shutdown(); exit(0); @} @end example @end deftypefun @c -------------------------------- @cindex dmalloc_verify function @cindex verify pointers @cindex verify the heap @deftypefun int dmalloc_verify ( char * @var{pnt} ) This function verifies individual memory pointers that are suspect of memory problems. To check the entire heap pass in a NULL or 0 pointer. The routine returns DMALLOC_VERIFY_ERROR or DMALLOC_VERIFY_NOERROR. @emph{NOTE}: @samp{dmalloc_verify()} can only check the heap with the functions that have been enabled. For example, if fence-post checking is not enabled, @samp{dmalloc_verify()} cannot check the fence-post areas in the heap. @end deftypefun @c -------------------------------- @cindex dmalloc_debug function @cindex override debug settings @cindex set debug functionality flags @deftypefun unsigned-int dmalloc_debug ( const unsigned int @var{flags} ) This routine sets the debug functionality flags and returns the previous flag value. It is helpful in server or cgi-bin programs where environmental variables cannot be used. @xref{Debugging A Server}. For instance, if debugging should never be enabled for a program, a call to @code{dmalloc_debug(0)} as the first call in @code{main()} will disable all the memory debugging from that point on. @emph{NOTE}: you cannot add or remove certain flags such as signal handlers since they are setup at initialization time only. @emph{NOTE}: you can also use @code{dmalloc_debug_setup} below. @end deftypefun @c -------------------------------- @cindex dmalloc_debug_current function @cindex current debug value @deftypefun unsigned-int dmalloc_debug_current ( void ) This routine returns the current debug functionality value value. This allows you to save a copy of the debug dmalloc settings to be changed and then restored later. @end deftypefun @c -------------------------------- @cindex dmalloc_debug_setup @cindex override debug settings @cindex set debug functionality flags @cindex setup debug flags @cindex string of debug tokens @deftypefun void dmalloc_debug_setup ( const char * @var{options_str} ) This routine sets the global debugging functionality as an option string. Normally this would be passed in in the DMALLOC_OPTIONS environmental variable. This is here to override the env or for circumstances where modifying the environment is not possible or does not apply such as servers or cgi-bin programs. @xref{Debugging A Server}. Some examples: @example /* * debug tokens high, threaded lock-on at 20, * log to dmalloc.%p (pid) */ dmalloc_debug_setup("debug=0x4f46d03,lockon=20,log=dmalloc.%p"); /* * turn on some debug tokens directly and log to the * file 'logfile' */ dmalloc_debug_setup( "log-stats,log-non-free,check-fence,log=logfile"); @end example @end deftypefun @c -------------------------------- @cindex dmalloc_examine function @cindex examine a pointer @cindex pointer information @deftypefun int dmalloc_examine ( const DMALLOC_PNT @var{pnt}, DMALLOC_SIZE * @var{user_size_p}, DMALLOC_SIZE * @var{total_size_p}, char ** @var{file_p}, int * @var{line_p}, DMALLOC_PNT * @var{ret_addr_p}, unsigned long * @var{user_mark_p}, unsigned long * @var{seen_p} ) @cindex seen count This function returns the size of a pointer's allocation as well as the total size given including administrative overhead, file and line or the return-address from where it was allocated, the last pointer when the pointer was "used", and the number of times the pointer has been "seen". It will return DMALLOC_NOERROR or DMALLOC_ERROR depending on whether pnt is good or not. @emph{NOTE}: This function is @emph{certainly} not provided by most if not all other malloc libraries. @end deftypefun @c -------------------------------- @cindex dmalloc_track function @cindex track memory calls @deftypefun void dmalloc_track ( const dmalloc_track_t @var{track_func} ) Register an allocation tracking function which will be called each time an allocation occurs. Pass in NULL to disable. To take a look at what information is provided, see the dmalloc_track_t function typedef in dmalloc.h. @end deftypefun @c -------------------------------- @cindex dmalloc_mark function @cindex memory position marker @cindex mark memory position @cindex LOG_ITERATION @cindex interaction count @cindex transaction count @deftypefun unsigned-long dmalloc_mark ( void ) Return to the caller the current "mark" which can be used later to log the pointers which have changed since this mark with the @code{dmalloc_log_changed} function. Multiple marks can be saved and used. This is very useful when using the library with a server which does not exit. You can then save a mark before a transaction or event happens and then check to see what has changed using the @code{dmalloc_log_changed} function below. @xref{Debugging A Server}. If you @code{LOG_ITERATION} enabled in your @file{settings.h} file then the entries in the log file will be prepended with the number of memory transactions that the library has handled so far. You can also enable @code{LOG_PNT_ITERATION} in @file{settings.h} to store the memory transaction number with each pointer. @end deftypefun @c -------------------------------- @cindex dmalloc_memory_allocated function @cindex memory allocated function @cindex number of bytes allocated @deftypefun unsigned-long dmalloc_memory_allocated ( void ) Return to the caller the total number of bytes that have been allocated by the library. This is not the current in use but the total number of bytes returned by allocation functions. @end deftypefun @c -------------------------------- @cindex page size @cindex size of memory pages @deftypefun unsigned-int dmalloc_page_size ( void ) Return to the caller the memory page-size being used by the library. This should be the same value as the one returned by the @code{getpagesize()} function, if available. @end deftypefun @c -------------------------------- @cindex count changed @cindex count number of bytes changed since mark @cindex number bytes changed since mark @deftypefun unsigned-long dmalloc_count_changed ( const unsigned long @var{mark}, const int @var{not_freed_b}, const int @var{free_b} ) Count the pointers that have changed since the mark which was returned by @code{dmalloc_mark}. If @code{not_freed_b} is set to non-0 then count the pointers that have not been freed. If @code{free_b} is set to non-0 then count the pointers that have been freed. This can be used in conjunction with the @code{dmalloc_mark()} function to help servers which never exit ensure that transactions or events are not leaking memory. @xref{Debugging A Server}. @example unsigned long mark = dmalloc_mark() ; @dots{} assert(dmalloc_count_changed(mark, 1, 0) == 0) ; @end example @end deftypefun @c -------------------------------- @cindex dmalloc_log_stats function @cindex log statistics @cindex statistics logging @deftypefun void dmalloc_log_stats ( void ) This routine outputs the current dmalloc statistics to the log file. @end deftypefun @c -------------------------------- @cindex dmalloc_log_unfreed function @cindex log unfreed memory @cindex unfreed memory log @deftypefun void dmalloc_log_unfreed ( void ) This function logs the unfreed-memory information to the log file. This is also useful to log the currently allocated points to the log file to be compared against another dump later on. @end deftypefun @c -------------------------------- @cindex dmalloc_log_changed function @cindex changed memory log @cindex checkpoint memory usage @cindex log memory changes @deftypefun void dmalloc_log_changed ( const unsigned long @var{mark}, const int @var{not_freed_b}, const int @var{freed_b}, const int @var{details_b} ) Log the pointers that have changed since the mark which was returned by @code{dmalloc_mark}. If @code{not_freed_b} is set to non-0 then log the pointers that have not been freed. If @code{free_b} is set to non-0 then log the pointers that have been freed. If @code{details_b} set to non-0 then log the individual pointers that have changed otherwise just log the summaries. This can be used in conjunction with the @code{dmalloc_mark()} function to help servers which never exit find transactions or events which are leaking memory. @xref{Debugging A Server}. @end deftypefun @c -------------------------------- @cindex dmalloc_vmessage function @cindex write message to logfile @cindex logfile message writer @deftypefun void dmalloc_vmessage ( const char * @var{format}, va_list @var{args} ) Write a message into the dmalloc logfile using vprintf-like arguments. @end deftypefun @c -------------------------------- @cindex dmalloc_message function @cindex write message to logfile @cindex logfile message writer @deftypefun void dmalloc_message ( const char * @var{format}, @var{...} ) Write a message into the dmalloc logfile using printf-like arguments. @end deftypefun @c -------------------------------- @cindex dmalloc_get_stats function @cindex get heap statistics @cindex heap statistics function @cindex report heap statistics @deftypefun void dmalloc_get_stats ( DMALLOC_PNT * @var{heap_low_p}, DMALLOC_PNT * @var{heap_high_p}, unsigned long * @var{total_space_p}, unsigned long * @var{user_space_p}, unsigned long * @var{current_allocated_p}, unsigned long * @var{current_pnt_np}, unsigned long * @var{max_allocated_p}, unsigned long * @var{max_pnt_np}, unsigned long * @var{max_one_p}) This function return a number of statistics about the current heap. The pointers @code{heap_low_p} and @code{heap_high_p} will be set to the low and high spots in the heap. @code{total_space_p} will be set to the total space in the heap including user space, administrative space, and overhead. @code{user_space_p} will be set to the space given to the user process (allocated and free space). @code{current_allocated_p} will be set to the current allocated space given to the user process. @code{current_pnt_np} will be set to the current number of pointers allocated by the user process. @code{max_allocated_p} will be set to the maximum allocated space given to the user process. @code{max_pnt_np} will be set to the maximum number of pointers allocated by the user process. @code{max_on_p} will be set to the maximum space allocated with one call by the user process. @end deftypefun @c -------------------------------- @cindex dmalloc_strerror function @cindex string error message @cindex error message @deftypefun const-char* dmalloc_strerror ( const int @var{error_number} ) This function returns the string representation of the error value in @code{error_number} (which probably should be dmalloc_errno). This allows the logging of more verbose memory error messages. You can also display the string representation of an error value by a call to the @file{dmalloc} program with a @samp{-e #} option. @xref{Dmalloc Program}. @end deftypefun @c -------------------------------- @node Error Codes, Disabling the Library, Extensions, Programming @section Description of the Internal Error Codes @cindex error codes The following error codes are defined in @file{error_val.h}. They are used by the library to indicate a detected problem. They can be caused by the user (@samp{ERROR_TOO_BIG}) or can indicate an internal library problem (@samp{ERROR_SLOT_CORRUPT}). The @file{dmalloc} utility can give you the string version of the error with the @code{-e} argument: @example $ dmalloc -e 60 dmalloc: dmalloc_errno value '60' = 'pointer is not on block boundary' @end example Here are the error codes set by the library. They are non contiguous on purpose because I add and delete codes all of the time and there are sections for various error-code types. @table @code @c -------------------------------- @cindex 1, error code @cindex error code, 1 @cindex no error @cindex ERROR_NONE @item 1 (ERROR_NONE) no error No error. It is good coding practice to set the no-error code to be non-0 value because it forces you to set it explicitly. @c -------------------------------- @cindex 2, error code @cindex error code, 2 @cindex invalid errno value @cindex errno value is not valid @cindex INVALID_ERROR @item 2 (INVALID_ERROR) Invalid error number. If the library outputs this error then your dmalloc utility may be out of date with the library you linked against. This will be returned with all error codes not listed here. @c -------------------------------- @cindex 10, error code @cindex error code 10 @cindex initialization and setup failed @cindex bad setup error @cindex ERROR_BAD_SETUP @item 10 (ERROR_BAD_SETUP) initialization and setup failed Bad setup value. This is currently unused but it is intended to report on invalid setup configuration information. @c -------------------------------- @cindex lock-on @cindex recursion @cindex in twice error @cindex 11, error code @cindex error code 11 @cindex malloc library has gone recursive @cindex ERROR_IN_TWICE @item 11 (ERROR_IN_TWICE) malloc library has gone recursive Library went recursive. This usually indicates that you are not using the threaded version of the library. Or if you are then you are not using the @samp{-o} "lock-on" option. @xref{Using With Threads}. @c -------------------------------- @cindex lock-on not configured @cindex 13, error code @cindex error code 13 @cindex thread locking has not been configured @cindex ERROR_LOCK_NOT_CONFIG @item 13 (ERROR_LOCK_NOT_CONFIG) thread locking has not been configured Thread locking has not been configured. This indicates that you attempted to use the @samp{-o} "lock-on" option without linking with the thread version of the library. You should probably be using @code{-ldmallocth} @emph{not} @code{-ldmalloc} when you are linking. Or you should include @code{@dots{}/lib/libdmallocth.a} on your compilation line. @c -------------------------------- @cindex error-free-null token @cindex free null token @cindex 20, error code @cindex error code 20 @cindex pointer is null error @cindex is null error @cindex ERROR_IS_NULL @item 20 (ERROR_IS_NULL) pointer is null Pointer is null. The program passed a NULL (0L) pointer to @code{free} and you have the @code{error-free-null} token enabled. @c -------------------------------- @cindex pointer not in heap error @cindex not in heap error @cindex 21, error code @cindex error code 21 @cindex pointer is not pointing to heap data space @cindex ERROR_NOT_IN_HEAP @item 21 (ERROR_NOT_IN_HEAP) pointer is not pointing to heap data space Pointer is not pointing to heap data space. This means that the program passed an out-of-bounds pointer to @code{free} or @code{realloc}. This could be someone trying to work with a wild pointer or trying to free a pointer from a different source than @code{malloc}. @c -------------------------------- @cindex not found error @cindex pointer not found error @cindex 22, error code @cindex error code 22 @cindex cannot locate pointer in heap @cindex ERROR_NOT_FOUND @cindex mmap @cindex sbrk @item 22 (ERROR_NOT_FOUND) cannot locate pointer in heap Cannot locate pointer in heap. The user passed in a pointer which the heap did not know about. Either this pointer was allocated by some other mechanism (like @code{mmap} or @code{sbrk} directly) or it is a random invalid pointer. In some rare circumstances, sometimes seen with shared libraries, there can be two separate copies of the dmalloc library in a program. Each one does not know about the pointers allocated by the other. @c -------------------------------- @cindex 23, error code @cindex error code 23 @cindex found pointer the user was looking for @cindex is found error @cindex ERROR_IS_FOUND @item 23 (ERROR_IS_FOUND) found pointer the user was looking for This indicates that the pointer specified in the address part of the environmental variable was discovered by the library. @xref{Environment Variable}. This error is useful so you can put a breakpoint in a debugger to find where a particular address was allocated. @xref{Using With a Debugger}. @c -------------------------------- @cindex 24, error code @cindex error code 24 @cindex possibly bad .c filename pointer @cindex bad file error @cindex ERROR_BAD_FILE @item 24 (ERROR_BAD_FILE) possibly bad .c filename pointer A possibly invalid filename was discovered in the dmalloc administrative sections. This could indicate some corruption of the internal tables. It also could mean that you have a source file whose name is longer than 100 characters. See @code{MAX_FILE_LENGTH} in the @file{settings.dist} file. @c -------------------------------- @cindex 25, error code @cindex error code 25 @cindex possibly bad .c file line-number @cindex bad line error @cindex ERROR_BAD_LINE @item 25 (ERROR_BAD_LINE) possibly bad .c file line-number A line-number was out-of-bounds in the dmalloc administrative sections. This could indicate some corruption of the internal tables. It also could mean that you have a source file containing more than @code{30000} lines of code. See @code{MAX_LINE_NUMBER} in the @file{settings.dist} file. @c -------------------------------- @cindex 26, error code @cindex error code 26 @cindex failed under picket-fence magic-number check @cindex under fence error @cindex ERROR_UNDER_FENCE @item 26 (ERROR_UNDER_FENCE) failed UNDER picket-fence magic-number check This indicates that a pointer had its lower bound picket-fence magic number overwritten. If the @code{check-fence} token is enabled, the library writes magic values above and below allocations to protect against overflow. Most likely this is because a pointer below it went past its allocate and wrote into the next pointer's space. @c -------------------------------- @cindex 27, error code @cindex error code 27 @cindex failed over picket-fence magic-number check @cindex over fence error @cindex ERROR_OVER_FENCE @item 27 (ERROR_OVER_FENCE) failed OVER picket-fence magic-number check This indicates that a pointer had its upper bound picket-fence magic space overwritten. If the @code{check-fence} token is enabled, the library writes magic values above and below allocations to protect against overflow. Most likely this is because an array or string allocation wrote past the end of the allocation. Check for improper usage of @code{strcat}, @code{sprintf}, @code{strcpy}, and any other functions which work with strings and do not protect themselves by tracking the size of the string. These functions should @emph{always} be replaced with: @code{strncat}, @code{snprintf}, @code{strncpy}, and others. @c -------------------------------- @cindex 28, error code @cindex error code 28 @cindex use of pointer would exceed allocation @cindex would overwrite error @cindex ERROR_WOULD_OVERWRITE @item 28 (ERROR_WOULD_OVERWRITE) use of pointer would exceed allocation This error is generated by the function pointer checking code usually enabled with the @code{check-funcs} token. Dmalloc overloads a number of string and memory copying functions and verifies that the buffers (if allocated in the heap) would not be overwritten by the function. @c -------------------------------- @cindex 30, error code @cindex error code 30 @cindex pointer is not to start of memory block @cindex not start block error @cindex ERROR_NOT_START_BLOCK @item 30 (ERROR_NOT_START_BLOCK) pointer is not to start of memory block This indicates that the user passed in a pointer to be freed or reallocated that was not at the start of the allocation. You would get this error, for example, if you allocate and get pointer @code{X} but then try to free @code{X+1}. @c -------------------------------- @cindex 40, error code @cindex error code 40 @cindex invalid allocation size @cindex bad size error @cindex ERROR_BAD_SIZE @item 40 (ERROR_BAD_SIZE) invalid allocation size This error indicates that a size value in the internal structures of the library were corrupted. This could be a random pointer problem, pointer overflow, or some other corruption. @c -------------------------------- @cindex 41, error code @cindex error code 41 @cindex largest maximum allocation size exceeded @cindex too big error @cindex ERROR_TOO_BIG @item 41 (ERROR_TOO_BIG) largest maximum allocation size exceeded An allocation asked for memory larger than the configured maximum. This is a user configured setting. See @code{LARGEST_ALLOCATION} in the @file{settings.dist} file. It is used to protect against wild allocation sizes. If you have super large allocation sizes then you should tune the @code{LARGEST_ALLOCATION} value appropriately. @c -------------------------------- @cindex 43, error code @cindex error code 43 @cindex could not grow heap by allocating memory @cindex alloc failed error @cindex ERROR_ALLOC_FAILED @item 43 (ERROR_ALLOC_FAILED) could not grow heap by allocating memory The library could not allocate more heap space and the program has run out of memory. This could indicate that you've overflowed some system imposed limit. On many operation systems, the @code{ulimit} call can tune system defaults. The library uses a lot more memory compared to the system malloc library because it stores a lot more information about the allocated pointers. @cindex mmap @cindex USE_MMAP conf.h option @emph{NOTE}: This also may be due to an inability of your operating system to use the @code{mmap} system call to allocate memory. You may need to force the @code{USE_MMAP} setting to be 0. Please use the forums at URL @uref{http://dmalloc.com/} to report issues with this. @c -------------------------------- @cindex 45, error code @cindex error code 45 @cindex memory limit @cindex over user specified allocation limit error @cindex over limit error @cindex ERROR_OVER_LIMIT @item 45 (ERROR_OVER_LIMIT) over user specified allocation limit The library has allocated more memory than was specified in the memory-limit environmental variable. @xref{Environment Variable}. @c -------------------------------- @cindex 60, error code @cindex error code 60 @cindex pointer is not on block boundary @cindex not on block boundary error @cindex ERROR_NOT_ON_BLOCK @item 60 (ERROR_NOT_ON_BLOCK) pointer is not on block boundary The user tried to free or realloc a pointer that was not pointing to a block boundary. You would get this error, for example, if you allocate and get pointer @code{X} but then try to free @code{X+1}. @c -------------------------------- @cindex 61, error code @cindex error code 61 @cindex tried to free previously freed pointer @cindex already free error @cindex ERROR_ALREADY_FREE @item 61 (ERROR_ALREADY_FREE) tried to free previously freed pointer The user tried to free a pointer than has already been freed. This is a very common mistake and can lead to serious problems. It can be because a destructor is being called twice for some reason. Although tracking down the specific source is highly recommended, it is good to set pointers to NULL (0L) after you free them as a rule. @c -------------------------------- @cindex 67, error code @cindex error code 67 @cindex free space has been overwritten @cindex free overwritten error @cindex ERROR_FREE_OVERWRITTEN @cindex free-blank @cindex check-blank @item 67 (ERROR_FREE_OVERWRITTEN) free space has been overwritten If either the @code{free-blank} or @code{check-blank} tokens are enabled then the library will overwrite memory when it is freed with the ``dmalloc-free'' byte (hex 0xdf, octal 0337, decimal 223). If the program writes into this space, then the library will detect the write and trigger this error. This could indicate that the program is using a pointer after it has been freed. @c -------------------------------- @cindex 70, error code @cindex error code 70 @cindex bad admin structure list @cindex admin list error @cindex ERROR_ADMIN_LIST @item 70 (ERROR_ADMIN_LIST) bad admin structure list An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption. @c -------------------------------- @cindex 72, error code @cindex error code 72 @cindex internal address list corruption @cindex address list error @cindex ERROR_ADDRESS_LIST @item 72 (ERROR_ADDRESS_LIST) internal address list corruption An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption. @c -------------------------------- @cindex 73, error code @cindex error code 73 @cindex internal memory slot corruption @cindex slot corrupt error @cindex ERROR_SLOT_CORRUPT @item 73 (ERROR_SLOT_CORRUPT) internal memory slot corruption An internal corruption in the library's administrative structures has been detected. This could be a random pointer problem, pointer overflow, or some other corruption. @end table @c -------------------------------- @node Disabling the Library, Using With C++, Error Codes, Programming @section How to Disable the library @cindex disabling library checking @cindex disabling the library @cindex dmalloc_debug @cindex restoring library flags @cindex turning off library flags If you would like to disable the library's detailed checking features during a particularly allocation intensive section of code, you can do something like the following: @example unsigned int dmalloc_flags; @dots{} /* turn off all debug flags and save a copy of old value */ dmalloc_flags = dmalloc_debug(0); /* section of a lot of allocations */ @dots{} /* end of section */ /* restore the dmalloc flag setting */ dmalloc_debug(dmalloc_flags); @end example When you are finished with the development and debugging sessions, you may want to disable the dmalloc library and put in its place either the system's memory-allocation routines, gnu-malloc, or maybe your own. Attempts have been made to make this a reasonably painless process. The ease of the extraction depends heavily on how many of the library's features your made use of during your coding. Reasonable suggestions are welcome as to how to improve this process while maintaining the effectiveness of the debugging. @itemize @bullet @item If you want to @emph{totally} disable the dmalloc library then you will need to recompile all the C files that include @file{dmalloc.h} while defining @code{DMALLOC_DISABLE}. This will cause the dmalloc macros to not be applied. @xref{Allocation Macros}. @example cc -g -DDMALLOC_DISABLE file.c @end example An alternative is to surround the @code{dmalloc.h} inclusion or any direct dmalloc references with an @code{#ifdef DMALLOC} and then just remove the -DDMALLOC. @example #ifdef DMALLOC #include "dmalloc.h" #endif main() @{ @dots{} #ifdef DMALLOC dmalloc_verify(0L); #endif return 0; @} @end example @example // to get dmalloc information $ cc -DDMALLOC main.c // without dmalloc information $ cc main.c @end example @item If you compiled any of your source modules with @code{DMALLOC_FUNC_CHECK} defined then you must first recompile all those modules without the flag enabled. If you have disabled dmalloc with the @code{DMALLOC_DISABLED} flag or never included @file{dmalloc.h} in any of your C files, then you will not need to recompile your sources when you need to disable the library. If you get unresolved references like @code{_dmalloc_malloc} or @code{_dmalloc_bcopy} then something was not disabled as it should have been. @end itemize @c -------------------------------- @node Using With C++, Using With a Debugger, Disabling the Library, Programming @section Using the Library with C++ @cindex c++ usage @cindex dmallocc.cc file @cindex libdmallocxx.a For those people using the C++ language, the library tries to configure and build @file{libdmallocxx.a} library. This library should be linked into your C++ programs instead of @file{libdmalloc.a}. @cindex dmallocc.cc Dmalloc is not as good with C++ as C because the dynamic memory routines in C++ are @code{new()} and @code{delete()} as opposed to @code{malloc()} and @code{free()}. Since new and delete are usually not used as functions but rather as @code{x = new type}, there is no easy way for dmalloc to pass in file and line information unfortunately. The @file{libdmallocxx.a} library provides the file @file{dmallocc.cc} which effectively redirects @code{new} to the more familiar @code{malloc} and @code{delete} to the more familiar @code{free}. @emph{NOTE}: The author is not a C++ hacker so feedback in the form of other hints and ideas for C++ users would be much appreciated. @c -------------------------------- @node Using With a Debugger, Using With Threads, Using With C++, Programming @section Using Dmalloc With a Debugger @cindex debugger usage with dmalloc @cindex using a debugger with dmalloc Here are a number of possible scenarios for using the dmalloc library to track down problems with your program. You should first enable a logfile filename and turn on a set of debug features. You can use @kbd{dmalloc -l logfile low} to accomplish this. If you are interested in having the error messages printed to your terminal as well, enable the @code{print-messages} token by typing @kbd{dmalloc -p print-messages} afterwards. @xref{Dmalloc Program}. @cindex gdb @cindex dmalloc_error() routine Now you can enter your debugger (I use the @emph{excellent} GNU debugger gdb), and put a break-point in @code{dmalloc_error()} which is the internal error routine for the library. When your program is run, it will stop there if a memory problem is detected. If you are using GDB, I would recommend adding the contents of @file{dmalloc.gdb} in the @file{contrib} subdirectory to your @file{.gdbinit} file in your home directory. This enables the @code{dmalloc} command which will prompt you for the arguments to the dmalloc command and will set a break point in @code{dmalloc_error()} automatically. @cindex shared libraries with gdb @cindex gdb with shared libraries If you are using shared libraries, you may want to execute the following commands initially to load in dmalloc and other library symbols: @example (gdb) sharedlibrary (gdb) add-shared-symbol-files @end example @menu * General Errors:: Diagnosing general problems with a debugger. * Memory Leaks:: Tracking down non-freed memory. * Fence-Post Overruns:: Diagnosing fence-post overwritten memory. * Translate Return Addresses:: Convert ra return-addresses into a location. @end menu @c -------------------------------- @node General Errors, Memory Leaks, Using With a Debugger, Using With a Debugger @subsection Diagnosing General Problems with a Debugger @cindex diagnosing errors @cindex general errors @cindex mmap @cindex sbrk If your program stops at the @code{dmalloc_error()} routine then one of a number of problems could be happening. Incorrect arguments could have been passed to a malloc call: asking for negative number of bytes, trying to realloc a non-heap pointer, etc.. There also could be a problem with the system's allocations: you've run out of memory, some other function in your program is using the heap allocation functions @code{mmap} or @code{sbrk}, etc.. However, it is most likely that some code that has been executed was naughty. To get more information about the problem, first print via the debugger the dmalloc_errno variable to get the library's internal error code. You can suspend your debugger and run @kbd{dmalloc -e value-returned-from-print} to get an English translation of the error. A number of the error messages are designed to indicate specific problems with the library administrative structures and may not be user-friendly. If the problem was due to the arguments or system allocations then the source of the problem has been found. However, if some code did something wrong, you may have some more work to do to locate the actual problem. The @code{check-heap} token should be enabled and the interval setting disabled or set to a low value so that the library can find the problem as close as possible to its source. The code that was execute right before the library halted, can then be examined closely for irregularities. @xref{Debug Tokens}, @xref{Dmalloc Program}. @cindex dmalloc_verify() routine You may also want to put calls to @code{dmalloc_verify(0)} in your code before the section which generated the error. This should locate the problem faster by checking the library's structures at that point. @xref{Extensions}. @c -------------------------------- @node Memory Leaks, Fence-Post Overruns, General Errors, Using With a Debugger @subsection Tracking Down Non-Freed Memory @cindex memory leaks @cindex leaking memory So you've run your program, examined the log-file and discovered (to your horror) some un-freed memory. Memory leaks can become large problems since even the smallest and most insignificant leak can starve the program given the right circumstances. @example not freed: '0x45008' (12 bytes) from 'ra=0x1f8f4' not freed: '0x45028' (12 bytes) from 'unknown' not freed: '0x45048' (10 bytes) from 'argv.c:1077' known memory not freed: 1 pointer, 10 bytes unknown memory not freed: 2 pointers, 24 bytes @end example Above you will see a sample of some non-freed memory messages from the logfile. In the first line the @samp{0x45008} is the pointer that was not freed, the @samp{12 bytes} is the size of the unfreed block, and the @samp{ra=0x1f8f4} or return-address shows where the allocation originated from. @xref{Translate Return Addresses}. The systems which cannot provide return-address information show @samp{unknown} instead, as in the 2nd line in the sample above. The @samp{argv.c:1077} information from the 3rd line shows the file and line number which allocated the memory which was not freed. This information comes from the calls from C files which included @file{dmalloc.h}. @xref{Allocation Macros}. At the bottom of the sample it totals the memory for you and breaks it down to known memory (those calls which supplied the file/line information) and unknown (the rest). Often, you may allocate memory in via @code{strdup()} or another routine, so the logfile listing where in the @code{strdup} routine the memory was allocated does not help locate the true source of the memory leak -- the routine that called @code{strdup}. Without a mechanism to trace the calling stack, there is no way for the library to see who the caller of the caller (so to speak) was. @cindex STORE_SEEN_COUNT conf.h option @cindex pointer seen count @cindex seen count However, there is a way to track down unfreed memory in this circumstance. You need to compile the library with @code{STORE_SEEN_COUNT} defined in @file{conf.h}. The library will then record how many times a pointer has been allocated or freed. It will display the unfreed memory as: @example not freed: '0x45008|s3' (12 bytes) from 'ra=0x1f8f4' @end example The @code{STORE_SEEN_COUNT} option adds a @samp{|s#} qualifier to the address. This means that the address in question was seen @samp{#} many times. In the above example, the address @samp{0x45008} was seen @samp{3} times. The last time it was allocated, it was not freed. How can a pointer be ``seen'' 3 times? Let say you @code{strdup} a string of 12 characters and get address @samp{0x45008} -- this is #1 time the pointer is seen. You then free the pointer (seen #2) but later @code{strdup} another 12 character string and it gets the @samp{0x45008} address from the free list (seen #3). So to find out who is allocating this particular 12 bytes the 3rd time, try @kbd{dmalloc -a 0x45008:3}. The library will stop the program the third time it sees the @samp{0x45008} address. You then enter a debugger and put a break point at @code{dmalloc_error}. Run the program and when the breakpoint is reached you can examine the stack frame to determine who called @code{strdup} to allocate the pointer. To not bother with the @code{STORE_SEEN_COUNT} feature, you can also run your program with the @code{never-reuse} token enabled. This token will cause the library to never reuse memory that has been freed. Unique addresses are always generated. This should be used with caution since it may cause your program to run out of memory. @c -------------------------------- @node Fence-Post Overruns, Translate Return Addresses, Memory Leaks, Using With a Debugger @subsection Diagnosing Fence-Post Overwritten Memory @cindex fence-post errors For a definition of fence-posts please see the ``Features'' section. @xref{Features}. To detect fence-post overruns, you need to enable the @samp{check-fence} token. @xref{Debug Tokens}. This pads your allocations with some extra bytes at the front and the end and watches the space to make sure that they don't get overwritten. @emph{NOTE:} The library cannot detect if this space gets read, only written. If you have encountered a fence-post memory error, the logfile should be able to tell you the offending address. @example free: failed UNDER picket-fence magic-number checking: pointer '0x1d008' from 'dmalloc_t.c:427' Dump of proper fence-bottom bytes: '\e\253\300\300\e\253\300\300' Dump of '0x1d008'-8: '\e\253\300\300WOW!\003\001pforger\023\001\123' @end example The above sample shows that the pointer @samp{0x1d008} has had its lower fence-post area overwritten. This means that the code wrote below the bottom of the address or above the address right below this one. In the sample, the string that did it was @samp{WOW!}. The library first shows you what the proper fence-post information should look like, and then shows what the pointer's bad information was. If it cannot print the character, it will display the value as @samp{\ddd} where ddd are three octal digits. By enabling the @code{check-heap} debugging token and assigning the interval setting to a low number, you should be able to locate approximately when this problem happened. @xref{Debug Tokens}, @xref{Dmalloc Program}. @c -------------------------------- @node Translate Return Addresses,, Fence-Post Overruns, Using With a Debugger @subsection Translating Return Addresses into Code Locations @cindex ra_info.pl The following gdb commands help you translate the return-addresses (ra=) entries in the logfile into locations in your code. I've provided a @file{ra_info.pl} perl script in the @file{contrib/} directory with the dmalloc sources which seems to work well with gdb. But, if you need to do it manually, here are the commands in gdb to use. @cindex return-address translation @cindex caller address translation @example # you may need to add the following commands to load in shared libraries (gdb) sharedlibrary (gdb) add-shared-symbol-files (gdb) x 0x10234d 0x10234d <_findbuf+132>: 0x7fffceb7 (gdb) info line *(0x82cc) Line 1092 of argv.c starts at pc 0x7540 and ends at 0x7550. @end example In the above example, gdb was used to find that the two non-freed memory pointers were allocated in @code{_findbuf()} and in file argv.c line 1092 respectively. The @samp{x address} (for examine) can always be used on the return-addresses but the @samp{info line *(address)} will only work if that file was compiled using the @kbd{-g} option and has not been stripped. This limitation may not be true in later versions of gdb. @c -------------------------------- @node Using With Threads, Using With Cygwin, Using With a Debugger, Programming @section Using the Library with a Thread Package @cindex threads @cindex pthreads Threads are special operating system facilities which allow your programs to have multiple threads of execution (hence the name). In effect your program can be doing a number of things ``at the same time''. This allows you to take full advantage of modern operating system scheduling and multi-processor hardware. If I've already lost you or if any of the terminology below does not make sense, see manuals about POSIX threads (pthreads) before going any further. O'Reilly publishes a pretty good pthreads manual for example. To use dmalloc with your threaded program, you will first need to make sure that you are linking with @file{libdmallocth.a} which is the threaded version of the library. The support for threads in dmalloc should be adequate for most if not all testing scenarios. It provides support for mutex locking itself to protect against race conditions that result in multiple simultaneous execution. One of the major problems is that most thread libraries uses malloc themselves. Since all of dmalloc's initialization happens when a call to malloc is made, we may be attempting to initialize or lock the mutex while the thread library is booting up. A very bad thing since thread libraries don't expect to recurse. @cindex lock on The solution to this problem is to have the library not initialize or lock its mutex variable until after a certain number of allocation calls have been completed. If the library does not wait before initializing the locks, the thread library will probably core dump. If it waits too long then it can't protect itself from multiple execution and it will abort or other bad things might happen. You adjust the number of times to wait at runtime with the @samp{lock-on} option to the dmalloc program (for example @kbd{dmalloc -o 20}). @xref{Dmalloc Program}. Times values between 5 and 30 are probably good although operating systems will vary significantly. You know its too low if your program immediately core dumps and too high if the dmalloc library says its gone recursive although with low values, you might get either problem. An additional complexity is when we are initializing the lock before mutex locking around the library. As mentioned, the initialization itself may generate a malloc call causing the library to go recursive and the pthread library to possibly core dump. With the THREAD_INIT_LOCK setting defined in @file{settings.h}, you can tune how many times before we start locking to try and initialize the mutex lock. It defaults to 2 which seems to work for me. If people need to have this runtime configurable or would like to present an alternative default, please let me know. So to use dmalloc with a threaded program, follow the following steps carefully. @enumerate @item Follow the installation instructions on how to configure, make, and install the library but make sure to add the @kbd{--enable-threads} argument to configure. @xref{Installation}. @item Typing @kbd{make} should be enough to build the threaded versions of the libraries including @file{libdmallocth.a}. @item Link the dmalloc threaded library into your program. The dmalloc library should probably be placed at or near the end of the library list. @item Enable the debugging options that you need by typing @kbd{dmalloc -l logfile -i 100 low} (for example). @kbd{dmalloc --usage} will provide verbose usage info for the dmalloc program. @xref{Dmalloc Program}. @item Enable the ``lock-on'' option (for example @kbd{dmalloc -o 20}). As explained above, you may have to try different values before getting it right. Values between 5 and 30 are probably good. @item If you get a dmalloc error #13 @samp{thread locking has not been configured} then you have not compiled you program with the threaded version of dmalloc or there was a problem building it. @item If everything works, you should be able to run your program, have it not immediately crash, and the dmalloc library should not complain about recursion. @end enumerate If you have any specific questions or would like addition information posted in this section, please let me know. Experienced thread programmers only please. @c -------------------------------- @node Using With Cygwin, Debugging A Server, Using With Threads, Programming @section Using the library with Cygwin environment. @cindex cygwin The Cygwin environment is a Linux-like environment for Windows. It provides Linux look and feel as well as a programming environment. See URL @uref{http://www.cygwin.com/} for more details. @cindex reading environment, problems with @cindex getenv, problems with @cindex GetEnvironmentVariableA, using with Cygwin uses the @code{GetEnvironmentVariableA} function to read in environmental variables instead of @code{getenv}. This functions are used to get the value of the @samp{DMALLOC_OPTIONS} variable which sets the debugging options. @xref{Environment Variable}. @cindex HAVE_GETENVIRONMENTVARIABLEA @cindex GETENV_SAVE conf.h option As of right now, dmalloc is not detecting the @code{GetEnvironmentVariableA} function correctly so you may need to tune the @file{conf.h} file to get it to work. See the sections on @code{HAVE_GETENVIRONMENTVARIABLEA} and @code{GETENV_SAVE} settings. Feedback is welcome here. If you still have problems reading in the environmental variables, you can work around this issue. You can add some code into the @code{main} function in your program to initialize the dmalloc flags yourself. Here is a code sample: @cindex dmalloc_debug_setup usage @example main(int argc, char **argv) @{ #ifdef DMALLOC /* * Get environ variable DMALLOC_OPTIONS and pass the settings string * on to dmalloc_debug_setup to setup the dmalloc debugging flags. */ dmalloc_debug_setup(getenv("DMALLOC_OPTIONS")); #endif /* rest of code in main starts here */ @dots{} @} @end example The @code{#ifdef} is just a good idea. I means that when debugging with dmalloc you need to compile your code with @code{-DDMALLOC}. When you are done debugging you can remove the flag and the call to @code{dmalloc_debug_setup} will be removed. Please let me know if there is a better way to do this. @c -------------------------------- @node Debugging A Server, Logfile Details, Using With Cygwin, Programming @section Debugging Memory in a Server or Cgi-Bin Process @cindex cgi-bin process debugging @cindex cgi-bin usage of dmalloc @cindex child process debugging @cindex daemon process debugging @cindex debugging cgi-bin processes @cindex debugging child processes @cindex debugging daemon processes @cindex debugging server processes @cindex server process debugging @cindex usage of dmalloc in a daemon @cindex usage of dmalloc in a server @cindex usage of dmalloc with cgi-bin There are some specified challenges when trying to debug allocations in processes which do not startup, run, and then shutdown. Server processes (often called daemons) are those that are started (often at system boot time) and run perpetually. Other processes which are difficult to debug are CGI programs which are spawned by web servers or when you want to start debugging inside of a child process. @enumerate @item Build your server or cgi-bin program with the dmalloc library like any other program. @xref{Getting Started}. @item Add code into your program to enable the library flags to perform the memory checks that you require. Since these programs often do not run from the command line, you cannot use the dmalloc utility program and modify the process environment. @xref{Dmalloc Program}. The library provides a couple of functions to set the debugging flags when a program is running. @cindex dmalloc_debug_setup function @item To set the memory debugging flags, use the @code{dmalloc_debug_setup} function which takes a string in the same format of the @samp{DMALLOC_OPTIONS} environmental variable. @xref{Environment Variable}. Use the dmalloc utility with the @code{-n} no-changes argument to see the appropriate settings for the @samp{DMALLOC_OPTIONS} environmental variable. @example > dmalloc -n -l logfile high Outputed: DMALLOC_OPTIONS=debug=0x4f4ed03,log=logfile export DMALLOC_OPTIONS @end example So if you want to turn on @kbd{high} debugging and log to the file @file{logfile} then you would copy the above @samp{DMALLOC_OPTIONS} value into a call to @code{dmalloc_debug_setup}. Notice that I have surrounded the dmalloc code with an @code{#ifdef DMALLOC} so you'll have to compile using the @code{-DDMALLOC} flag. @example main() @{ #ifdef DMALLOC /* set the 'high' flags */ dmalloc_debug_setup("debug=0x4f47d03,log=logfile"); #endif @dots{} @} @end example @emph{Please note} that the @code{dmalloc_debug_setup} function does not know about @code{high}, @code{low}, or other debug tokens but needs the actual flag values. @item For earlier versions of the library (before 5.0.0) without @code{dmalloc_debug_setup}, the @code{dmalloc_debug} function is available to set the flags directly, but it cannot adjust the logfile name and the other environment settings. You can use the dmalloc utility program to see what the numerical equivalent of the @kbd{high} token. @example > dmalloc -n high Outputed: DMALLOC_OPTIONS=debug=0x4f4ed03 export DMALLOC_OPTIONS @end example You can then take the @code{0x4f4ed03} hexadecimal number and call @code{dmalloc_debug} with that number. @example main() @{ #ifdef DMALLOC /* set the 'high' flags */ dmalloc_debug(0x4f4ed03); #endif @dots{} @} @end example @item Even with the settings enabled, you may have problems getting the logfile to be written if your program is running as @samp{nobody} or another user without permissions for security reasons. This is especially true for cgi-bin programs. In this case you should specify a full path to your malloc logfile in a world writable directory (ex. @code{dmalloc_debug_setup("debug=0x4f47d03,log=/var/tmp/malloc");}). Watch for programs which change into other directories and which may cause logfiles specified as relative or local paths to be dropped in other locations. You may always want to use a full path logfile. @item Once you have your settings enabled and your log is being generated, you may now want to check out how your process is doing in terms of unfreed memory. Since it is not shutting down, the automatic unfreed log entries are not being dropped to the logfile. By using the @code{dmalloc_mark} and @code{dmalloc_log_changed} functions, you can set a mark point at a certain place inside of your program, and then later see whether there are any unfreed pointers since the mark. @example main() @{ #ifdef DMALLOC /* set the 'high' flags */ dmalloc_debug_setup("debug=0x4f47d03,log=logfile"); #endif while (1) @{ /* accept a connection from a client */ accept_connection(); while (1) @{ #ifdef DMALLOC unsigned long mark; /* get the current dmalloc position */ mark = dmalloc_mark() ; #endif /* process the connection */ if (process_connection() != PROCESS_OK) @{ break; @} #ifdef DMALLOC /* * log unfreed pointers that have been added to * the heap since mark */ dmalloc_log_changed(mark, 1 /* log unfreed pointers */, 0 /* do not log freed pointers */, 1 /* log each pnt otherwise summary */); #endif @} /* close the connection with the client */ close_connection(); @} @dots{} @} @end example Usually you would set the mark after the initializations and before each transaction is processed. Then for each transaction you can use @code{dmalloc_log_changed} to show the unfreed memory. @xref{Extensions}. @item You can also use the @code{dmalloc_log_stats} function to dump general information about the heap. Also, remember that you can use the @code{dmalloc_message} and @code{dmalloc_vmessage} routines to annotate the dmalloc logfile with details to help you debug memory problems. @xref{Extensions}. @end enumerate @c -------------------------------- @node Logfile Details, Other Hints, Debugging A Server, Programming @section Explanation of the Logfile Output @cindex logfile format Most of time you will be using the logfile output from library as the sole information source for diagnosing problems in and getting statistics for your program. @example 1098918225: 3: Dmalloc version '@value{dmalloc_version}' 1098918225: 3: flags = 0x4f4e503, logfile '/tmp/dmalloc.log' 1098918225: 3: interval = 500, addr = 0, seen # = 0, limit = 0 1098918225: 3: starting time = 1098918225 1098918225: 3: process pid = 32406 1098918226: 4: WARNING: tried to free(0) from foo.c:708' 1098918228: 20: *** free: at 'unknown' pnt '0xed310080|s2': \ size 12, alloced at 'bar.c:102' 1098918230: 50: ERROR: heap_check: free space was overwritten (err 67) 1098918230: 50: error details: checking free pointer 1098918230: 50: pointer '0x291c5' from 'unknown' prev access 'foo.c:787' @end example Here is a short example of some logfile information. Each of the lines are prefixed by the time (in epoch seconds since 1/1/1970) and the iteration or call count which is the number of times the library has been called from malloc, free, verify, etc.. In the above example, the first 5 log entries where written at epoch 1098918225 or @samp{Wed Oct 27 19:03:45 2004 EST} and they were generated by the 3rd call to the library. See the @file{settings.dist} file entries to tune what elements appear on each line: LOG_TIME_NUMBER, LOG_ITERATION, LOG_PID, etc.. You can convert the epoch seconds to a date from the command line with the following perl code: @code{perl -e 'print localtime($ARGV[0])."\n";' epoch-seconds-number} @cindex version of library The first 5 lines of the sample logfile contain header information for all logfiles. They show the version number and URL for the library as well as all of the settings that the library is currently using. These settings are tuned using the dmalloc utility program. @xref{Dmalloc Program}. The 5th line of is the process-id that generated the logfile. @cindex ALLOW_FREE_NULL_MESSAGE The 6th line in the above example is what causes the logfile to be opened and the header to be written. It is a warning that tells you that you tried to free a 0L pointer at a certain location. You can disable these warnings by setting @samp{ALLOW_FREE_NULL_MESSAGE} to 0 in @file{settings.dist}. @cindex seen count Line 7 is an example of a transaction log that you get when you enable the @code{log-trans} debug token. @xref{Debug Tokens}. This line shows that a call to free was made from an unknown location. It is unknown because the file in question did not include @file{dmalloc.h} to get file/line-number information. The call to free was freeing the pointer address @code{0xed310080} which we have ``seen'' 2 times (s2). We saw the pointer when it was allocated and then we are seeing it again when it was freed. Because the library is reusing pointers (reclaiming freed memory) the seen count helps to track how many times a pointer was used. The last part of the line shows that the pointer to be freed was allocated by @file{bar.c} line 102. Lines 8-10 is the next problem that the library caught and this one is an error. It happened 5 seconds from the start of the log (1098918230) and at the 50th call into the library. It shows that an allocation that had been freed then was overwritten. This may imply that someone tried to use memory after it was freed or that there was a loose pointer reference. The last two lines give more details about when the error was discovered, the address of the offending pointer, and when the pointer was previous accessed, in this case freed. To discover where this problem is happening, you can use a debugger. @xref{Using With a Debugger}. @c -------------------------------- @node Other Hints,, Logfile Details, Programming @section Various Other Hints That May Help @cindex other hints @cindex hints that may help @cindex various hints One of the problems that is often seen is that a program crashes in the @code{libc} memory code and you suspect a heap memory problem but both dmalloc and maybe valgrind don't show any problems. One of the big problems with debugging is that it is very difficult to do it without effecting how the program is run. Sometimes errors are due to subtle race conditions that are only seen when the program is running at full speed -- not slowed down by debugging code. This is especially true with threaded code which is often heavily affected when used with dmalloc and valgrind. Older versions of valgrid (maybe current) forced all threads into a single virtual system by design, which often masks reentrance bugs. One way to work through these issues is to run with the library with very few debugging flags enabled. Many memory problems are fence-post areas so start with dmalloc checking just the fence post and error logging enabled: @example dmalloc -d 0 -l dmalloc.log -p log-stats -p log-non-free -p check-fence -p check-funcs @end example This enabled a small number of checks and should cause your program to run at close to full speed. The library has never been optimized for speed so some performance penalties will be felt. @c ---------------------------------------------------------------------------- @node Dmalloc Program, Source Code, Programming, Top @chapter Dmalloc Utility Program @cindex dmalloc program @cindex dmalloc utility @cindex utility program @cindex library utility The dmalloc program is designed to assist in the setting of the environment variable @samp{DMALLOC_OPTIONS}. @xref{Environment Variable}. It is designed to print the shell commands necessary to make the appropriate changes to the environment. Unfortunately, it cannot make the changes on its own so the output from dmalloc should be sent through the @code{eval} shell command which will do the commands. @menu * Shell Alias:: Using a shell alias with the utility. * Utility Usage:: How to use the dmalloc program. * Environment Variable:: Environment variable name and features. * Debug Tokens:: Description of the debugging tokens. * RC File:: Format of the runtime configuration file. @end menu @c -------------------------------- @node Shell Alias, Utility Usage, Dmalloc Program, Dmalloc Program @section Using a Shell Alias with the Utility The dmalloc program is designed to assist in the setting of the environment variable @samp{DMALLOC_OPTIONS}. @xref{Environment Variable}. It is designed to print the shell commands necessary to make the appropriate changes to the environment. Unfortunately, it cannot make the changes on its own so the output from dmalloc should be sent through the @code{eval} shell command which will do the commands. @cindex alias, shell @cindex bash shell @cindex ksh shell @cindex zsh shell With shells that have aliasing or macro capabilities: csh, bash, ksh, tcsh, zsh, etc., setting up an alias to dmalloc to do the eval call is recommended. Bash, ksh, and zsh users should add the following to their @file{.bashrc}, @file{.profile}, or @file{.zshrc} file respectively (notice the @kbd{-b} option for bourne shell output): @example function dmalloc @{ eval `command dmalloc -b $*`; @} @end example If your shell does not support the @code{command} function then try: @example function dmalloc @{ eval `\dmalloc -b $*`; @} @end example or @example function dmalloc @{ eval `/usr/local/bin/dmalloc -b $*`; @} @end example @cindex tcsh shell @cindex csh shell If you are @emph{still} using csh or tcsh, you should add the following to your @file{.cshrc} file (notice the @kbd{-C} option for c-shell output): @example alias dmalloc 'eval `\dmalloc -C \!*`' @end example This allows the user to execute the dmalloc command as @samp{dmalloc arguments}. Users of versions of the Bourne shell (usually known as /bin/sh) that don't have command functions will need to send the output to a temporary file and the read it back in with the ``.'' command: @example $ dmalloc -b arguments @dots{} > /tmp/out $ . /tmp/out @end example By the way, if you are looking for a shell, I heartily recommend trying out zsh. It is a bourne shell written from scratch with much the same features as tcsh without the csh crap. @emph{NOTE}: After you add the alias to the file you need to log out and log back in to have it take effect, or you can execute the above appropriate command on the command line. If you enter @kbd{dmalloc runtime} and see any output with DMALLOC_OPTIONS in it then the alias did not work. @c -------------------------------- @node Utility Usage, Environment Variable, Shell Alias, Dmalloc Program @section How to Use the Dmalloc Program @cindex utility usage @cindex usage of the utility The most basic usage for the program is @samp{dmalloc [-bC] tag}. The @samp{-b} or @samp{-C} (either but not both flags used at a time) are for generating Bourne or C shell type commands respectively. dmalloc will try and use the @code{SHELL} environment variable to determine whether bourne or C shell commands should be generated but you may want to explicitly specify the correct flag. The @samp{tag} argument to dmalloc should match a line from the user's runtime configuration file or should be one of the built-in tags. @xref{RC File}. If no tag is specified and no other option-commands used, dmalloc will display the current settings of the environment variable. It is useful to specify one of the verbose options when doing this. To find out the usage for the debug malloc program try @samp{dmalloc --usage-long}. The standardized usage message that will be displayed is one of the many features of the argv library included with this package. It is available on the web at URL @uref{http://256.com/sources/argv/}. See the documentation there for more information. Here is a detailed list of the flags that can passed to dmalloc: @table @code @item -a address Set the @samp{addr} part of the @samp{DMALLOC_OPTIONS} variable to address (or alternatively address:number). @item -b Output Bourne shell type commands. Usually handled automagically. @item -C Output C shell type commands. Usually handled automagically. @item -c Clear/unset all of the settings not specified with other arguments. You can do this automatically when you set to a new tag with the @kbd{-r} option. @emph{NOTE}: clear will never unset the @samp{debug} setting. Use @kbd{-d 0} or a tag to @samp{none} to achieve this. @item -d bitmask Set the @samp{debug} part of the @samp{DMALLOC_OPTIONS} env variable to the bitmask value which should be in hex. This is overridden (and unnecessary) if a tag is specified. @item -D List all of the debug-tokens. Useful for finding a token to be used with the @kbd{-p} or @kbd{-m} options. Use with @kbd{-v} or @kbd{-V} verbose options. @item -e errno Print the dmalloc error string that corresponds to the error number errno. @item -f filename Use this configuration file instead of the RC file @file{$HOME/.dmallocrc}. @item -g Output gdb type commands for using inside of the gdb debugger. @item -h (or --help) Output a help message for the utility. @item -i number @cindex interval setting Set the checking interval to number. If the @code{check-heap} token is enabled, this causes the library to only check the heap every Nth time which can @emph{significantly} increase the running speed of your program. If a problem is found, however, this limits your ability to determine when the problem occurred. Try values of 50 or 100 initially. @item -k Do not reset all of the settings when a tag is specified. This specifically overrides the @kbd{-r} option and is provided here to override @kbd{-r} if it has been added to the dmalloc alias. @item -l filename Write the debugging output and other log-file information to the filename. Filename can include some of the following patterns which get expanded into strings: @table @code @cindex %h @cindex gethostname function usage @cindex hostname in logfile path @cindex name of host in logfile path @item %h Gets expanded into the hostname if the @code{gethostname()} function is available. @cindex %i @cindex thread-id in logfile path @item %i Gets expanded into the thread-id if the library has been configure to be used with threads. @xref{Using With Threads}. See the end of the @file{settings.dist} file for settings which return the thread-id and convert it into a string. @cindex %p @cindex getpid function usage @cindex pid in logfile path @cindex process-id in logfile path @item %p Gets expanded into the process-id if the @code{getpid()} function is available. @cindex %t @cindex time function usage @cindex time in logfile path @item %t Gets expanded into the time value in seconds if the @code{time()} function is available. @cindex %u @cindex getuid function usage @cindex uid in logfile path @cindex user-id in logfile path @item %u Gets expanded into the user-id number if the @code{getuid()} function is available. @end table Some examples: @example # logfile produced with pid extension: # logfile.8412 or logfile.31451 dmalloc -l logfile.%p # hostname and time extensions: # dmalloc-box1.foo.com-1055213240 dmalloc -l dmalloc-%h-%t # if threads enabled, have thread-id extension: log.thread32 dmalloc -l log.thread%i @end example @item -L Write the debug-value into the environment not in hex but by individual debug-tokens in long form. @item -m token(s) Remove (minus) the debug capabilities of token(s) from the current debug setting or from the selected tag (or @kbd{-d} value). Multiple @kbd{-m} options can be specified. @cindex memory limit @cindex ERROR_OVER_LIMIT @item -M limit Set the memory allocation limit which will abort the program if the total memory allocations exceed this number of bytes. The limit can be a number with a k, m, or g at the end to indicate kilobyte, megabyte, and gigabyte respectively. Ex: 100k, 200m, 1g. If the limit is exceeded, this will generate an @code{ERROR_OVER_LIMIT} error. @xref{Error Codes}. @item -n Without changing the environment, output the commands resulting from the supplied options. @cindex lock on @item -o times Set the ``lock-on'' period which dictates to the threaded version of the library to not initialize or lock the mutex lock around the library until after a certain number of allocation calls have been made. Some number between 2 and 30 is probably good. See the ``Using With Threads'' section for more information about the operation of the library with threads. @xref{Using With Threads}. @item -p token(s) Add (plus) the debug capabilities of token(s) to the current debug setting or to the selected tag (or @kbd{-d} value). Multiple @kbd{-p} options can be specified. @item -r Remove (unset) all settings when using a tag. This is useful when you are returning to a standard development tag and want the logfile, address, and interval settings to be cleared automatically. If you want this behavior by default, this can be put into the dmalloc alias. @item -R Output rc shell type commands. This is not for the runtime configuration file but for the rc shell program. @cindex delay heap checking @cindex start heap check later @item -s file:line Set the @samp{start} part of the @samp{DMALLOC_OPTIONS} env variable to a file-name and line-number location in the source where the library should begin more extensive heap checking. The file and line numbers for heap transactions must be working for this option to be obeyed. This is used if you are trying to locate a problem and you want the extensive checking to not happen initially because it's too slow. @cindex delay heap checking @cindex start heap check later @cindex LOG_ITERATION @cindex interaction count @cindex transaction count @cindex mark count @cindex memory transaction count @item -S number Set the @samp{start} part of the @samp{DMALLOC_OPTIONS} env variable to an dmalloc mark number. The library will begin more extensive heap checking after this number of memory transactions. If you @code{LOG_ITERATION} enabled in your @file{settings.h} file then the entries in the log file will be prepended with the number of memory transactions that the library has handled so far. This number can be used to delay the start of the fine grained heap checking which can be very slow. @cindex delay heap checking @cindex start heap check later @item --start-size size Set the @samp{start} part of the @samp{DMALLOC_OPTIONS} env variable to a number of bytes. The library will begin more extensive heap checking after this amount of memory has been allocated by the library. This allows you to start the slow and detailed checking of the library later in the program execution. You can use patterns like 250m, 1g, or 102k to mean 250 megabytes, 1 gigabyte, and 102 kilobytes respectively. @item -t List all of the tags in the rc-file. Use with @kbd{-v} or @kbd{-V} verbose options. @item -u (or --usage) Output the usage information for the utility. @item -v Give verbose output. Especially useful when dumping current settings or listing all of the tags. @item -V Give very verbose output for outputting even more details about settings. @cindex utility version @cindex library version @cindex version of utility @item --version Output the version string for the utility. @emph{Please note} that the version of the library that is installed or has been linked into your application may be different from the utility version. @end table If no arguments are specified, dmalloc dumps out the current settings that you have for the environment variable. For example: @example Debug-Flags '0x40005c7' (runtime) Address 0x1f008, count = 3 Interval 100 Logpath 'malloc' Start-File not-set @end example With a -v option and no arguments, dmalloc dumps out the current settings in a verbose manner. For example: @example Debug-Flags '0x40005c7' (runtime) log-stats, log-non-free, log-bad-space, check-fence, catch-null Address 0x1f008, count = 10 Interval 100 Logpath 'malloc' Start-File not-set @end example Here are some examples of dmalloc usage: @example # start tough debugging, check the heap every 100 times, # send the log information to file 'logfile' dmalloc high -i 100 -l logfile # find out what error code 20 is (from the logfile) dmalloc -e 20 # cause the library to halt itself when it sees the address 0x34238 # for the 6th time. dmalloc -a 0x34238:6 # send the log information to file 'logfile' with the time in seconds # as an extension. dmalloc -l logfile.%t # return to the normal 'runtime' settings and clear out all # other settings dmalloc -c runtime # enable basic 'low' settings plus (-p) the logging of # transactions (log-trans) to file 'logfile' dmalloc low -p log-trans -l logfile # print out the current settings with Very-verbose output dmalloc -V # list the available debug malloc tokens with Very-verbose output dmalloc -DV # list the available tags from the rc file with verbose output dmalloc -tv @end example @c -------------------------------- @node Environment Variable, Debug Tokens, Utility Usage, Dmalloc Program @section Environment Variable Name and Features @cindex environment variable @cindex DMALLOC_OPTIONS An @dfn{environment variable} is a variable that is part of the user's working environment and is shared by all the programs. The @samp{DMALLOC_OPTIONS} variable is used by the dmalloc library to enable or disable the memory debugging features, at runtime. @emph{NOTE:} you can also use the @code{dmalloc_debug_setup} function to set the option string. It can be set either by hand or with the help of the dmalloc program. @xref{Dmalloc Program}. @cindex shell usage @cindex Bourne shell usage @cindex sh usage @cindex bash usage @cindex ksh usage @cindex zsh usage To set it by hand, Bourne shell (sh, bash, ksh, or zsh) users should use: @example DMALLOC_OPTIONS=value export DMALLOC_OPTIONS @end example @cindex C shell usage @cindex csh usage @cindex tcsh usage C shell (csh or tcsh) users need to invoke: @example setenv DMALLOC_OPTIONS value @end example The value in the above examples is a comma separated list of tokens each having a corresponding value. The tokens are described below: @table @code @item debug @cindex debug setting This should be set to a value in hexadecimal which corresponds to the functionality token values added together. @xref{Debug Tokens}. For instance, if the user wanted to enable the logging of memory transactions (value @samp{0x008}) and wanted to check fence-post memory (value @samp{0x400}) then @samp{debug} should be set to @samp{0x408} (@samp{0x008} + @samp{0x400}). @emph{NOTE}: You don't have to worry about remembering all the hex values of the tokens because the dmalloc program automates the setting of this variable especially. @cindex comma separated tokens in env variable @emph{NOTE}: You can also specify the debug tokens directly, separated by commas. @xref{Debug Tokens}. If @samp{debug} and the tokens are both used, the token values will be added to the debug value. @item lockon @cindex lockon setting Set this to a number which is the ``lock-on'' period. This dictates to the threaded version of the library to not initialize or lock the mutex lock around the library until after a certain number of allocation calls have been made. See the ``Using With Threads'' section for more information about the operation of the library with threads. @xref{Using With Threads}. @item log @cindex logfile setting @cindex logging information to disk Set this to a filename so that if @samp{debug} has logging enabled, the library can log transactions, administration information, and/or errors to the file so memory problems and usage can be tracked. To get different logfiles for different processes, you can assign @samp{log} to a string with @code{%d} in it (for instance @samp{logfile.%d}). This will be replaced with the pid of the running process (for instance @samp{logfile.2451}). @emph{WARNING}: it is easy to core dump any program with dmalloc, if you send in a format with arguments other than the one @code{%d}. @item addr @cindex address setting @cindex address locating @cindex tracking addresses When this is set to a hex address (taken from the dmalloc log-file for instance) dmalloc will abort when it finds itself either allocating or freeing that address. The address can also have an @samp{:number} argument. For instance, if it was set it to @samp{0x3e45:10}, the library will kill itself the 10th time it sees address @samp{0x3e45}. By setting the number argument to 0, the program will never stop when it sees the address. This is useful for logging all activity on the address and makes it easier to track down specific addresses not being freed. This works well in conjunction with the @code{STORE_SEEN_COUNT} option. @xref{Memory Leaks}. @emph{NOTE}: dmalloc will also log all activity on this address along with a count. @item inter @cindex interval setting By setting this to a number X, dmalloc will only check the heap every X times. This means a number of debugging features can be enabled while still running the program within a finite amount of time. A setting of @samp{100} works well with reasonably memory intensive programs. This of course means that the library will not catch errors exactly when they happen but possibly 100 library calls later. @item start @cindex start setting Set this to a number X and dmalloc will begin checking the heap after X times. This means the intensive debugging can be started after a certain point in a program. @samp{start} also has the format @samp{file:line}. For instance, if it is set to @samp{dmalloc_t.c:126} dmalloc will start checking the heap after it sees a dmalloc call from the @file{dmalloc_t.c} file, line number 126. If you use @samp{dmalloc_t.c:0}, with a 0 line number, then dmalloc will start checking the heap after it sees a call from anywhere in the @file{dmalloc_t.c} file. This allows the intensive debugging to be started after a certain routine or file has been reached in the program. @end table Some examples are: @example # turn on transaction and stats logging and set # 'logfile' as the log-file setenv DMALLOC_OPTIONS log-trans,log-stats,log=logfile # enable debug flags 0x1f as well as heap-checking and # set the interval to be 100 setenv DMALLOC_OPTIONS debug=0x1f,check-heap,inter=100 # enable 'logfile' as the log-file, watch for # address '0x1234', and start checking when we see # file.c line 123 setenv DMALLOC_OPTIONS log=logfile,addr=0x1234,start=file.c:123 @end example @c -------------------------------- @node Debug Tokens, RC File, Environment Variable, Dmalloc Program @section Description of the Debugging Tokens @cindex debug tokens @cindex tokens, debug The below tokens and their corresponding descriptions are for the setting of the debug library setting in the environment variable. @xref{Environment Variable}. They should be specified in the user's @file{.dmallocrc} file. @xref{RC File}. Each token, when specified, enables a specific debugging feature. For instance, if you have the @code{log-stats} token enabled, the library will log general statistics to the logfile. To get this information on the fly, use @kbd{dmalloc -DV}. This will print out the Debug tokens in Very-verbose mode. @xref{Dmalloc Program}. @table @code @cindex none token @item none No debugging functionality @cindex log-stats @item log-stats Log general statistics when dmalloc_shutdown or dmalloc_log_stats is called. @cindex log-non-free @item log-non-free Log non-freed memory pointers when dmalloc_shutdown or dmalloc_log_unfreed is called. @cindex log-known @item log-known Log only known memory pointers that have not been freed. Pointers which do not have file/line or return-address information will not be logged. @cindex log-trans @item log-trans Log general memory transactions (quite verbose). @cindex log-admin @item log-admin Log administrative information (quite verbose). @cindex log-bad-space @item log-bad-space Log actual bytes in and around bad pointers. @cindex log-nonfree-space @item log-nonfree-space Log actual bytes in non-freed pointers. @cindex log-elapsed-time @item log-elapsed-time Log elapsed-time for allocated pointers (see @file{conf.h}). @cindex log-current-time @item log-current-time Log current-time for allocated pointers (see @file{conf.h}). @cindex check-fence @item check-fence Check fence-post memory areas. @cindex check-heap @item check-heap Verify heap administrative structure. @cindex check-blank @item check-blank Check to see if space that was blanked when a pointer was allocated or when it was freed has been overwritten. If this is enabled then it will enable @code{free-blank} and @code{alloc-blank} automatically. @cindex check-funcs @item check-funcs Check the arguments of some functions (mostly string operations) looking for bad pointers. @cindex check-shutdown @item check-shutdown Check all of the pointers in the heap when the program exits. @cindex catch-signals @cindex signal shutdown @cindex shutdown on signal @cindex SIGHUP @cindex SIGINT @cindex SIGTERM @cindex HUP signal @cindex INT signal @cindex TERM signal @item catch-signals Shutdown the library automatically on SIGHUP, SIGINT, or SIGTERM. This will cause the library to dump its statistics (if requested) when you press control-c on the program (for example). @cindex realloc-copy @item realloc-copy Always copy data to a new pointer when realloc. @cindex blank space @cindex blanking memory @cindex overwriting memory @cindex clearing memory @cindex decimal 223 character @cindex 223 character @cindex octal 337 character @cindex 337 character @cindex 0337 character @cindex hexadecimal 0xdf character @cindex 0xdf character @cindex df character @cindex free-blank @cindex ERROR_FREE_OVERWRITTEN @item free-blank Write special ``dmalloc-free'' byte (hexadecimal @code{0xdf}, octal @code{0337}, decimal @code{223}) into space when it is freed. You can set this to be something else in the @file{settings.dist} file. This ensures that your program is not using memory after it has been freed. You can check to see if areas have been improperly overwritten with the @code{check-blank} token. If the free space has been overwritten, then @code{ERROR_FREE_OVERWRITTEN} is triggered. @xref{Error Codes}. @cindex dump core @cindex core dump @cindex error-abort @item error-abort Abort the program (and dump core) on errors. See @code{error-dump} below. @xref{Dumping Core}. @cindex blank space @cindex blanking memory @cindex overwriting memory @cindex clearing memory @cindex decimal 218 character @cindex 218 character @cindex octal 332 character @cindex 332 character @cindex 0332 character @cindex hexadecimal 0xda character @cindex 0xda character @cindex da character @cindex alloc-blank @item alloc-blank Write special ``dmalloc-alloc'' byte (hexadecimal @code{0xda}, octal @code{0332}, decimal @code{218}) into space when it is allocated. You can set this to be something else in the @file{settings.dist} file. If you are not using @code{calloc} this will overwrite the user space with the special bytes ensuring that your program is initializing its dynamic memory appropriately. Also, if you ask for 35 bytes and the library has to give you a block of 64 because of rounding issues, it will overwrite the extra memory with the special byte. You can then check to see if the extra areas have been improperly overwritten by enabling the @code{check-blank} token. @cindex print-messages @item print-messages Log any errors and messages to the screen via standard-error. @cindex mmap @cindex sbrk @cindex catch-null @item catch-null Abort the program immediately if the library fails to get more heap space from the heap allocation routine @code{mmap} or @code{sbrk}. @cindex never-reuse @item never-reuse Have the heap never use space that has been used before and freed. @xref{Memory Leaks}. @emph{WARNING}: This should be used with caution since you may run out of heap space. @cindex dump core @cindex core dump @cindex error-dump @item error-dump Dump core on error and then continue. Later core dumps overwrite earlier ones if the program encounters more than one error. See @code{error-abort} above. @xref{Dumping Core}. @emph{NOTE}: This will only work if your system supports the @code{fork} system call and the configuration utility was able to fork without going recursive. @cindex error-free-null @cindex ALLOW_FREE_NULL @cindex ALLOW_FREE_NULL_MESSAGE @item error-free-null By default the library will not generate an error when a program tries to free a NULL pointer. By enabling this token, you can change this behavior so an error is reported. See also the ALLOW_FREE_NULL and ALLOW_FREE_NULL_MESSAGE settings in the @file{settings.h} file to change the default behavior. @end table @c -------------------------------- @node RC File,, Debug Tokens, Dmalloc Program @section Format of the Runtime Configuration File @cindex rc file @cindex runtime-config file @cindex configuration file @cindex dmallocrc file @cindex .dmallocrc file By using a @dfn{RC File} (or runtime configuration file) you can alias tags to combinations of debug tokens. @xref{Debug Tokens}. @emph{NOTE}: For beginning users, the dmalloc program has a couple of tags built into it so it is not necessary for you to setup a RC file: @table @code @cindex runtime token @cindex token runtime @item runtime Enables basic runtime tests including fence-post checking, null handling, and logging of any errors. @cindex low token @cindex token low @item low Runtime settings plus minimal checking of heap structures and overwriting of allocated and freed space. @cindex medium token @cindex token medium @item medium Low settings plus checking of all heap structures on each memory call, always relocates block on realloc, and aborts on errors. You may want to use @kbd{-i} option to the dmalloc utility. @xref{Dmalloc Program}. @cindex high token @cindex token high @item high Medium settings plus checking of overwritten freed and allocated memory and checking of arguments to a number of common functions. You may want to use @kbd{-i} option to the dmalloc utility. @xref{Dmalloc Program}. @end table For expert users, a sample @file{dmallocrc} file has been provided but you are encouraged to roll your own combinations. The name of default rc-file is @file{$HOME/.dmallocrc}. The @samp{$HOME} environment variable should be set by the system to point to your home-directory. The file should contain lines in the general form of: @example tag token1, token2, @dots{} @end example @samp{tag} is to be matched with the tag argument passed to the dmalloc program, while @samp{token1, token2, @dots{}} are debug capability tokens. @xref{Dmalloc Program}, @ref{Debug Tokens}. A line can be finished with a @samp{\} meaning it continues onto the next line. Lines beginning with @samp{#} are treated as comments and are ignored along with empty lines. Here is an example of a @file{.dmallocrc} file: @example # # Dmalloc runtime configuration file for the debug malloc library # # no debugging none none # basic debugging debug1 log-stats, log-non-free, check-fence # more logging and some heap checking debug2 log-stats, log-non-free, log-trans, \ check-fence, check-heap, error-abort # good utilities debug3 log-stats, log-non-free, log-trans, \ log-admin, check-fence, check-heap, realloc-copy, \ free-blank, error-abort @dots{} @end example For example, with the above file installed, you can type @code{dmalloc debug1} after setting up your shell alias. @xref{Dmalloc Program}. This enables the logging of statistics, the logging of non-freed memory, and the checking of fence-post memory areas. Enter @code{dmalloc none} to disable all memory debugging features. @c ---------------------------------------------------------------------------- @node Source Code, Troubleshooting, Dmalloc Program, Top @chapter Information on the Source Code @cindex source code @menu * Definitions:: Definition of terms and other information. * Compatibility:: General compatibility concerns. * Portability:: Issues important for porting the library. @end menu @c -------------------------------- @node Definitions, Compatibility, Source Code, Source Code @section Definition of Terms and other Information @cindex source definitions Here are a couple definitions and other information for those interested in ``picking the brain'' of the library. The code is a little ugly here and there and it conforms to the Gray-Watson handbook of coding standards only. @table @dfn @item bblock basic block containing 2 ^ BASIC_BLOCK bytes of info @item bblock_adm administration for a set of basic blocks @item dblock divided block containing some base 2 number of blocks smaller than a basic block. @item dblock_adm administration for a set of divided blocks @item chunk some anonymous amount of memory @end table For more information about administration structures, see the code and comments from @file{chunk_loc.h}. @c -------------------------------- @node Compatibility, Portability, Definitions, Source Code @section General Compatibility Concerns @cindex compatibility @itemize @bullet @item Realloc() backwards compatibility with being able to realloc from the last freed block is @emph{not} supported. The author is interested to know who is using this (cough, cough) feature and for what reason. @cindex ALLOW_REALLOC_NULL settings.h option @item Realloc() of a NULL pointer is supported in which case the library will just make a call to malloc(). This can be disabled with the help of the @code{ALLOW_REALLOC_NULL} manual compilation option in the @file{settings.h} file to adjust the library's default behavior. @cindex ALLOW_FREE_NULL settings.h option @item Some systems allow free(0) to not be an error for some reason. Since 0 is not a valid address returned by the malloc call, it is debatable that this should be allowed. See @file{settings.h} for the @code{ALLOW_FREE_NULL} manual compilation option to adjust the library's default behavior. @item Aside from possibly being slower than the system's memory allocation functions, the library should be fully compatible with the standard memory routines. If this is @emph{not} the case, please bring this to my attention. @end itemize @c -------------------------------- @node Portability,, Compatibility, Source Code @section Issues Important for Porting the Library @cindex portability General portability issues center around: @itemize @bullet @item @cindex mmap, usage without @cindex sbrk, usage without @cindex preallocated memory heap @cindex INTERNAL_MEMORY_SPACE mmap, sbrk, or compatible function usages. The library does support a preallocated memory chunk heap. See the @code{INTERNAL_MEMORY_SPACE} define in the @file{settings.dist} file. @item @cindex return-address The locating of the caller's address from the dmalloc functions. This is useful in locating problems from dmalloc functions called from C files which did not include @file{dmalloc.h}: C library calls for instance. @cindex gcc See @file{return.h} for the available architecture/compiler combinations. You may want to examine the assembly code from gcc (GNUs superior c-compiler) version 2+ being run on the following code. It should give you a good start on building a hack for your box. @example static char * x; a() @{ x = __builtin_return_address(0); @} main() @{ a(); @} @end example @end itemize @c -------------------------------- @node Troubleshooting, Index of Concepts, Source Code, Top @chapter Some Solutions to Common Problems @cindex troubleshooting @cindex common problems @cindex help @cindex how do i... @cindex faq @cindex questions @cindex problems This section provides some answers to some common problems and questions. Please send me mail with any additions to this list -- either problems you are still having or tips that you would like to pass on. When diagnosing a problem, if possible, always make sure you are running the most up to date version of Dmalloc available from the home page at URL @uref{http://dmalloc.com/}. Problems are often fixed and a new release can be published before people encounter them. @table @samp @cindex slow running @cindex why running slow @cindex too slow @cindex why hanging @cindex hanging program @item Why does my program run so slow? @cindex check-heap This library has never been (and maybe never will be) optimized for space nor speed. Some of its features make it unable to use some of the organizational methods of other more efficient heap libraries. If you have the @code{check-heap} token enabled, your program might run slow or seem to hang. This is because by default, the library will run a full check of the heap with every memory allocation or free. You can have the library check itself less frequently by using the @kbd{-i} option to the dmalloc utility. @xref{Dmalloc Program}. If you are using the @kbd{high} token and you need your program to run faster, try the @kbd{medium} or @kbd{low} tokens which don't check as many heap features and so run faster although they will not catch as many problems. @xref{RC File}. @cindex logfile not produced @cindex no logfile produced @item Why was a log-file not produced after I ran my program? This could be caused by a number of different problems. @enumerate @item Are you sure you followed all of the items in the ``Getting Started'' section? Please review them if there is any doubt. @xref{Getting Started}. @cindex env @cindex printenv @cindex DMALLOC_OPTIONS @item Use the @kbd{env} or @kbd{printenv} commands to make sure that the @samp{DMALLOC_OPTIONS} variable is set in your exported environment. @xref{Environment Variable}. @cindex ident @cindex strings @item Make sure that your program has been compiled correctly with the dmalloc library. The @kbd{ident} program should show chunk.c and other dmalloc files compiled into your program. You can also do @kbd{strings -a your-program | grep chunk.c} and look for something like @samp{$Id: chunk.c,v 1.152 1999/08/25 12:37:01 gray Exp $} with different versions and date information. If this doesn't show up then chances are dmalloc was not linked into your program. @item If your program changes its working directory, it may write the dmalloc log-file somewhere else in the filesystem. You will need to check both where the program was started and to where it might change directory. @item The logfile is only produced when @code{dmalloc_shutdown()} is called. By default it will be called when @code{exit()} gets called. If you are running your program and press @kbd{Control-C} under Unix the program will stop immediately and @code{dmalloc_shutdown()} will not get called. You can either setup a signal handler for @code{SIGINTR} and call exit yourself, or you can enable the @code{catch-signals} token. @xref{Debug Tokens}. @item If your program is segfaulting or otherwise crashing when it exits, the @code{exit()} routine may not being called. You will have to resolve these issues so the dmalloc library can gracefully exit and write its log file. @item You may want to call @code{dmalloc_log_stats()} and @code{dmalloc_log_unfreed()} (or @code{dmalloc_log_changed()}) directly to have the library write its log file. Some system modules may not have shutdown if you call this before @code{exit()} so extra unfreed memory may be reported. @end enumerate @item I don't see any information about my non-freed (leaked) memory? The library will not (by default) report on ``unknown'' non-freed memory. Unknown means memory that does not have associated file and line information. This will be necessary if you are @emph{not} including @file{dmalloc.h} in all of your C files or if you are interested in tracking leaks in system functions. @item Dmalloc is returning the error "malloc library has gone recursive" This most likely indicates that you are using the Dmalloc library within a threaded application and two threads are trying to use the dmalloc library at once. Please see the section of the manual about threads for more information about properly configuring the library. @xref{Using With Threads}. If you are not using threads, then your program could have caught a signal while within Dmalloc, which then in turn called a memory allocation routine. It is unwise to allocate memory on the heap in most signal handlers. Lastly, some functions called by the library may call memory routines that it does not anticipate. If you think this the case, please report the problem and include a stack trace, operating system version/type, and the version of Dmalloc you are using. @end table @c -------------------------------- @node Index of Concepts,, Troubleshooting, Top @unnumbered Index of Concepts @printindex cp @contents @bye dmalloc-5.5.2/contrib/README000640 001751 001751 00000001255 10622115666 015432 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- $Id: README,v 1.6 2000/03/21 20:13:01 gray Exp $ ------------------------------------------------------------------------------- This directory contains files contributed by others. Please free to contribute programming examples, favorite tricks, operating system specific help files, etc. Send your contributions to the author. Gray Watson makes no representations about the suitability of the software described herein for any purpose. It is provided "as is" without express or implied warranty. http://dmalloc.com/ ------------------------------------------------------------------------------- dmalloc-5.5.2/contrib/z_os_notes000640 001751 001751 00000005176 10622115666 016665 0ustar00graygray000000 000000 [ From Tony Reyelts. ] Building dmalloc on z/OS 1.3 After a few tries, I've boiled down the steps to building dmalloc on z/OS to run under USS. Here's how: 1. Set the environment so Makefile generates a valid compile: export DEFINES='-D_XOPEN_SOURCE_EXTENDED -Wc,"LANGLVL(ANSI)" 2. Run configure: configure --prefix==/some/path --disable-cxx Note: The default is to use C++, but the make failed with it because the compiler expects the extension .C, not .cc. Since I don't use C++, I disabled that part. You'll get the following message from configure: WARNING: The library has limited support for heaps that grow down. Please see the NOTES file and send the author mail. 3. Edit conf.h: - Change HEAP_GROWS_UP to 1 from 0. For some reason, configure thinks it grows down when it really doesn't. 4. Edit the Makefile: - Unset $LIBS because cc won't link with it on the end of the link command. - Set LDFLAGS to "-L ./" so libdmalloc.a can be found. 5. Create a dummy ranlib (return 0) because z/OS doesn't have one. 6. Run make to build the code. I got a compile warning for malloc.c assigning between "long *" and "unsigned long *" at line 246. It looks like this is because _dmalloc_address_seen_n (unsigned long *) is being passed as the third argument to _dmalloc_environ_get (long *). The code seems to work ok, so I didn't bother fixing this. Using dmalloc on z/OS 1.3 1. dmalloc uses sbrk() to allocate storage. The sbrk() function on z/OS only uses the primary allocation (vs. secondary), so the primary has to be set to be big enough to hold eveything. This is a Language Environment run-time option called HEAP. In USS, you can set it with the _CEE_RUNOPTS environment variable. For example, I used the following: export_CEE_RUNOPTS="heap(64M,1M,ANY,FREE)" 2. The z/OS C compiler provides functions for doing MVS-specific things such as allocating data sets. The easiest way to gain access is to compile with -Wc,"LANGLVL(EXTENDED)" vs. -Wc,"LANGLVL(ANSI)". This makes dmalloc.h think it is a non-ANSI compile (__STDC__ is not set), so the definitions of malloc(), etc fall afoul of those from stdlib.h. So, if you're using LANGLVL(EXTENDED), you'll need to edit dmalloc.h so the ANSI version of DMALLOC_PNT is used. 3. The following functions are known to not be tracked by dmalloc on z/OS 1.3. They apparently use their own storage scheme: - glob()/globfree() - wordexp()/wordfree() dmalloc-5.5.2/contrib/tsecs000750 001751 001751 00000002123 10622115666 015613 0ustar00graygray000000 000000 #!/usr/bin/perl # # Little perl script which converts the time in epoch seconds into a # use viewable time/date. # use strict; use POSIX qw(strftime); sub usage { print qq[Usage: tsecs [-h] [-f strftime-format] [epoch1 [epoch2 [...]]] -h Specify the times as hex values instead of decimal. -f Specify the strftime format string to use to display the time. You can give a list times in epoch seconds to convert on the command line. The time "now" will display the current date and secs. If no times are given it will print out the current date and secs. ]; exit 1; } my $now = time; @ARGV = ( $now ) unless @ARGV; my $time_format = "%a %b %e %H:%M:%S %Y %Z"; my $hex_b = 0; my @times; while ( @ARGV ) { $_ = shift; /^-f/ && do { $time_format = shift || usage(); next; }; /^-h/ && do { $hex_b = 1; next; }; /^-/ && usage(); /^now$/ && do { $times[++$#times] = $now; next; }; $times[++$#times] = ($hex_b ? hex $_ : $_); } foreach my $secs ( @times ) { my $time_str = strftime $time_format, localtime($secs); print "Time in seconds for $secs is '$time_str'\n"; } dmalloc-5.5.2/contrib/stratus_ftx_notes000640 001751 001751 00000001234 10622115666 020270 0ustar00graygray000000 000000 From: Wim_van_Duuren Subject: dmalloc library Date: Wed, 12 Aug 1998 10:36:42 -0400 I recently used your dmalloc library on a Stratus FTX (release 2.3.1.1, i860 Intel processor) system. Getting the return-address setup properly was a problem (couldn't get the "asm" working in the selected compiler mode), and I ended up with compiling according to full-ANSI rules (using the -Xa compiler option). This I could only do after modifying the "dmalloc.h.3" in such a way that the malloc/calloc/realloc/free definitions would no longer cause the compiler to bark with 'identifier redeclared' (I just put an #ifdef _STDLIB_H ... #endif around those functions). ... sdf dmalloc-5.5.2/contrib/ra_info.pl000750 001751 001751 00000004466 10622115666 016535 0ustar00graygray000000 000000 #!/usr/bin/perl # # script to run gdb on return-addresses # Usage: $0 malloc-log-file binary # # Copyright 2000 by Gray Watson # # This file is part of the dmalloc package. # # Permission to use, copy, modify, and distribute this software for # any purpose and without fee is hereby granted, provided that the # above copyright notice and this permission notice appear in all # copies, and that the name of Gray Watson not be used in advertising # or publicity pertaining to distribution of the document or software # without specific, written prior permission. # # Gray Watson makes no representations about the suitability of the # software described herein for any purpose. It is provided "as is" # without express or implied warranty. # # The author may be contacted via http://dmalloc.com/ # # $Id: ra_info.pl,v 1.7 2000/11/20 17:44:06 gray Exp $ # # # Use this Perl script to run gdb and get information on the return-address # (ra) addresses from a dmalloc logfile output. This will search for # any ra= lines and will examine them and try to get the line number. # # NOTE: you may want to direct the output from the script to a file # else gdb seems to prompt for a return like you are on the end of a # page. # # Be sure to send me mail if there is an easier way to do all this. # ############################################################################### # usage message # if (@ARGV != 2 ) { die "Usage: $0 dmalloc-log binary-that-generated-log\n"; } $malloc = @ARGV[0]; $command = @ARGV[1]; open(malloc, "<" . $malloc) || die "Could not open $malloc: $!\n"; open (gdb, "|gdb -nx -q $command") || die "Could not run gdb: $!\n"; $| = 1; # get rid of the (gdb) printf (gdb "set prompt\n"); printf (gdb "echo \\n\n"); # load in the shared libraries printf (gdb "sharedlibrary\n"); printf (gdb "add-shared-symbol-files\n"); while ( ) { $count = 0; $line = $_; while ( $line =~ m,ra=0x[0-9a-fA-F]+, ) { $count++; $address = $_; $address =~ s/.*ra=(0x[0-9a-fA-F]+).*\n?/\1/; $line =~ s/ra=0x[0-9a-fA-F]+//; printf (gdb "echo -----------------------------------------------\\n\n"); printf (gdb "echo Address = '%s' line %d num %d\\n\n", $address, $., $count); printf (gdb "x %s\n", $address); printf (gdb "info line *(%s)\n", $address); } } $| = 0; close(gdb); close(malloc); dmalloc-5.5.2/contrib/next_notes000640 001751 001751 00000001165 10622115666 016663 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- $Id: next_notes,v 1.2 2000/03/21 20:13:02 gray Exp $ ------------------------------------------------------------------------------- From email with Next users: --------------------------- When linking your code with the dmalloc library, you will need to use the -m flag which tells the compiler to ignore the presence of multiple references and to just take the first available one. At this time, I have no other recommendations and have not heard of any success on the Next system. _Please_ send me any hints. Gray Watson http://dmalloc.com/ dmalloc-5.5.2/contrib/dmalloc_summarize.pl000750 001751 001751 00000011467 10622115666 020626 0ustar00graygray000000 000000 #!/usr/bin/perl5 -w # # dmalloc_summarize -- summarizes dmalloc log files # # Copyright 1997 by USC/ISI All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, advertising # materials, and other materials related to such distribution and use # acknowledge that the software was developed by the University of # Southern California, Information Sciences Institute. The name of # the University may not be used to endorse or promote products # derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # $Id: dmalloc_summarize.pl,v 1.1 1997/07/07 08:13:52 gray Exp $ # sub usage { print STDERR <= 1 && $ARGV[0] eq '-?'); my($exe) = undef; if ($#ARGV >= 0) { $exe = $ARGV[0]; }; # initialize counters my($totcount, $totgross) = (0, 0); ###################################################################### # # Store key into the hash or increment existing value # sub safe_inc { my($hashref, $key, $inc) = @_; if (defined($hashref->{$key})) { $hashref->{$key} += $inc; } else { $hashref->{$key} = $inc; }; } ###################################################################### my($gdb_pid); # # Start a gdb pipe to resolve unknown return addresses. # sub start_gdb { $SIG{'PIPE'} = sub { mydie("ERROR: premature end-of-data.\n"); }; $gdb_pid = open2('GDB_RDR', 'GDB_WTR', 'gdb', '-nx', '-q', $exe) || die "$0: cannot run gdb on $exe\n"; # tidy things up # prompt becomes a magic number to look for print GDB_WTR "set prompt (gdb)\\n\n"; print GDB_WTR "set print asm-demangle on\n"; print GDB_WTR "set height 0\n"; } # # Huh? # sub never_called { ; ; # hack for warnings } # # Lookup an unknown ra-address with gdb # sub interpret_name { my($name) = @_; return $name if ($name !~ /^ra/); return $name if (!defined($exe)); start_gdb() if (!defined($gdb_pid)); ($a) = ($name =~ /ra=([0-9a-fA-FxX]+)/); return $name if (!defined($a)); print GDB_WTR "info line *($a)\n"; my($something) = undef; my($file_line, $function); while () { if (/^\(gdb\)$/) { last if ($something); next; # skip prompts }; $something = 1; if (/^Line (\d+) of "([^\"]+)"/) { $file_line = "$2:$1"; }; if (/\<(.*)\+\d+\>/) { $function = $1; }; }; my($n) = ""; $n .= "$function " if (defined($function)); $n .= "[$file_line] " if (defined($file_line)); $n = $name if ($n eq ''); return $n; } ###################################################################### my(%allocers) = (); # read the data sub read_data { while () { next if (! /\d:\s+not freed:\s+'([^\']+)'\s+\((\d+)\s+bytes\)\s+from\s+'([^\']*)'$/); my($pointer, $size, $allocer) = ($1, $2, $3); if (! defined($allocers{$allocer})) { $allocers{$allocer} = {}; $allocers{$allocer}->{'sizes'} = {}; }; safe_inc($allocers{$allocer}, 'nsizes', 1) if (! defined($allocers{$allocer}->{'sizes'}{$size})); safe_inc($allocers{$allocer}->{'sizes'}, $size, 1); safe_inc($allocers{$allocer}, 'subcount', 1); safe_inc($allocers{$allocer}, 'subgross', $size); $totcount++; $totgross += $size; } } # # Print the report line # sub form { printf "%10s %10s %10s %s\n", @_[1,2,3,0]; } sub by_size { return $allocers{$b}->{'subgross'} <=> $allocers{$a}->{'subgross'}; } # # Dump out the report # sub print_report { form ('function', 'size', 'count', 'gross'); form ('total', '', $totcount, $totgross); my($allocer, $size); foreach $allocer (sort by_size keys %allocers) { my($head) = interpret_name($allocer); my($sizes); if ($allocers{$allocer}->{'nsizes'} > 1) { my($subcount, $subgross) = ($allocers{$allocer}->{'subcount'}, $allocers{$allocer}->{'subgross'}); form($head, 'subtotal', $subcount, $subgross); $head = "\""; }; foreach $size (sort {$a<=>$b} keys %{$allocers{$allocer}->{'sizes'}}) { my($count) = $allocers{$allocer}->{'sizes'}{$size}; my($gross) = $count * $size; form ($head, $size, $count, $gross); $head = "\""; }; }; } read_data; print_report; exit 0; dmalloc-5.5.2/contrib/dmalloc.gdb000640 001751 001751 00000002175 10622115666 016645 0ustar00graygray000000 000000 # # This is a little helper to use dmalloc within gdb, use it via # "source dmalloc.gdb" # # It will provide a command dmalloc, which will ask the user for # arguments to provide to the dmalloc application. The output will be # in gdb format and will be parsed by gdb. # # Its main purpose is to generate breaks at allocations of unfreed # memory (via dmalloc -a ...). # # As gdb's language is very basic, there is no back substitution and # variable arguments to user defined commands. Therefore the user # defined command dmalloc will use a shell escape to ask the user for # the arguments to the dmalloc applications. The dmalloc applications # will execute with the provided arguments and write the output to a # temporary file. This temporary file will then be read by gdb and # deleted afterwards. # # November 10, 1998 - Jens Krinke # define dmalloc echo Enter dmalloc options: shell read arg; dmalloc -g $arg > /tmp/dmalloc-gdb source /tmp/dmalloc-gdb shell rm -f /tmp/dmalloc-gdb show env DMALLOC_OPTIONS # the following will not work if no symboltable is loaded, but that # doesn't matter. break dmalloc_error end dmalloc-5.5.2/contrib/dgux_notes000640 001751 001751 00000004205 10622115666 016652 0ustar00graygray000000 000000 Date: Sun, 15 Aug 1999 22:29:56 -0700 (PDT) From: Takis Psarogiannakopoulos Subject: DG/UX dmalloc Dear Gray, I am writing this relating to the DG/ux port (ix86) of dmalloc library. I am responsible for the DG/ux X11R6.3 and I am designing a new Xserver with multiple threads, so I want to use your dmalloc, as a replacemnet for the crap system DG/ux library. I am curious who wrote to you that dmalloc (as is) will work in DG/ux. Firstly the threads library for DG/ux "-lthread ", (configure , configure.in) should be something like AC_CHECK_LIB(thread, __d10_pthread_mutex_init, LIBTHREAD="-lthread" DG_THREAD_FLAG="-D_POSIX4A_DRAFT10_SOURCE") (there is no pthread_create , pthread_mutex_init or ... inside -lthread) and the functions sould be detected by , say, AC_CHECK_FUNCS(__d10_pthread_mutex_init) ...etc As the DG/ux header pthread.h is _not_ a desent one , we need probably to define somewhere (in conf.h.in ?) something like #if defined(DGUX) #include #define _USING_POSIX4A_DRAFT10 1 #endif and then #define __d10_pthread_mutex_init mutex_init etc ... (for the others). Also in the above AC_CHECK_LIB(thread ...) to add (for the _d10__xxx of DG/ux) a special flag like DG_THREAD_FLAG="-D_POSIX4A_DRAFT10_SOURCE" (as I did already) which we want to append in the Makefile as AC_SUBST(DG_THREAD_FLAG) and add it to the standard CFLAGS as DG_THREAD_FLAG = @DG_THREAD_FLAG@ CFLAGS = ... $(DG_THREAD_FLAG) so it will be empty for other OS ... I confess these are not great changes, but as dmalloc is it will not detect lthread, and also neither of the pthread functions! Finnaly the correct CFLAGS for DG/ux are -DDGUX -D_DGUX_SOURCE -D_POSIX4A_DRAFT10_SOURCE but I guess one can pass these to configure when it executes it. However looking for the header dg_sys_info.h (which obviously is a DG/ux particular header , not in any other OS) like AC_CHECK_HEADER(dg_sys... ) we can have in the configure.in something like $ac_is_dgux=yes,no and accordingly set the DG/ux CFLAGS, so the user doesnt need to know the correct configuration command. If you want me to submit a patch drop me an e-mail. Regards, Takis dmalloc-5.5.2/contrib/dec_notes000640 001751 001751 00000004420 10622115666 016435 0ustar00graygray000000 000000 ------------------------------------------------------------------------------- $Id: dec_notes,v 1.7 2000/03/21 20:13:02 gray Exp $ ------------------------------------------------------------------------------- From Dave Hill: ----------------------------------- DEC OSF1/AXP extra notes: ========================= To build this library, you will need to have -std1 as a flag to cc in the Makefile. This sets the compiler into ansi-mode. The configure script may have done this for you, but if not, the Makefile should read: # default c-compiler CC = cc -std1 To create a shared library from the static library: ld -shared -o libdmalloc.so -all libdmalloc.a -all \ -soname libdmalloc.so -none -lc The OSF1/AXP shared library loader has the capabilities to override the shared libraries used, even to the extent that it takes symbols from a library that the program was not linked with. Using this technique, you may override the standard malloc in libc with the debug malloc shared library. _RLD_LIST=/path_to_the_dir/libdmalloc.so:DEFAULT;export _RLD_LIST Remember though, setting this variable will affect ALL commands invoked from the shell that it is set inside of. You may wish to do this inside of a shell script that sets the variable just before starting your program. Another option with sh and ksh is to list the environment variables on the program invocation line, for example: _RLD_LIST=/path_to_the_dir/libdmalloc.so:DEFAULT program This command will set the specified env variable and then run program. ------------------------------------------------------------------------------- [The dmalloc library currently supports the at_exit() auto-shutdown routine. If this is not working, however, you may want to consider the following.] OSF1 also supports the use of an 'init' and a 'fini' routine. Any function prefixed with '__init_' will be executed prior to main() and any function prefixed with '__fini_' will be executed after any call to exit() or after main() returns. A fini routine can be used with the debug library to invoke dmalloc_shutdown to get final statistics from the library package. For example: void __fini_dmalloc() { dmalloc_shutdown(); } Try putting this code in a separate .o file and linking it into your application when you are debugging. dmalloc-5.5.2/contrib/atexit.c000640 001751 001751 00000004640 10622115666 016215 0ustar00graygray000000 000000 /* * * Copyright (c) 1994, Textil Computer Design GmbH, Dresden * * Author: J"org Wunsch * * Dumb atexit() implementation. It is far from being elegant. It is * only here to provide a workaround for systems where the existing * atexit() implementation is known to cause problems due to doing * own mallocs. The problem arose originally on a Data General * machine running DG/UX 5.4R*, along with gcc compiling C++ code. * In order to have global and static variables called their const- * ructors, a chunk of code has been placed by the compiler that * ran before invoking main(). This code registered the desctructors * with atexit() at this very early stage, but the existing atexit() * bypassed the normal memory allocation scheme, and hence caused * grievous troubles in combination with the dmalloc library. * * Known problem for DG/UX: the crt0.o (at least in a COFF environ- * ment) passes the return value from main() to _real_exit() instead * of exit(). Hence programs which return from main instead of calling * exit() do not work as expected. I do not see any good workaround * for this so far (since crt0.o always happens to reference the * _real_exit() from the library, even if we would provide our very * own symbol for it). * * Permission to use, copy, modify, and distribute this software for any * purpose and without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of TCD GmbH not be used in advertising or publicity pertaining to * distribution of the document or software without specific, written prior * permission. * * Textil Computer Design GmbH makes no representations about the * suitability of the software described herein for any purpose. It * is provided "as is" without express or implied warranty. */ /* ANSI C requires at least 32 atexit functions to be allowed */ #define MAXATEXIT 32 static void (*__atexit[MAXATEXIT])(void); static int __atexit_registered = 0; int atexit(void (*fn)(void)) { if(__atexit_registered == MAXATEXIT) return -1; __atexit[__atexit_registered++] = fn; return 0; } void exit(int status) { static int already_in_atexit = 0; extern void _exit(int); if(already_in_atexit++) /* some silly atexit()-registered stuff called exit(); give up */ _exit(status); while(__atexit_registered) (*__atexit[--__atexit_registered])(); _exit(status); } dmalloc-5.5.2/contrib/aix_notes000640 001751 001751 00000002505 10622115666 016465 0ustar00graygray000000 000000 From: Martin Krumpolec Sent: Tuesday, June 23, 1998 1:11 PM Subject: RE: dmalloc - bug report ? > The problem seems to be that certain libc calls which allocate > memory (strdup for instance) somehow bypass the malloc() call and do > their own allocations. This confuses dmalloc when the free is called. Hello, I have observed this problem is regarding not only strdup but several other libc (AIX 4.2) routines allocating memory: scandir, strdup, tempnam, ... When I played a bit, I have found neat idea in the man pages - they adviced to add flags: -bnso -bI:/lib/syscalls.exp to linker options in AIX ... Voila, it suddenly works :) Martin > -----Original Message----- > > > > k> s.p = (char *) strdup("blah"); > > k> free((void *) s.p); > > > Huh? No a bug with libdmalloc I don't think. Looks to me > that strdup > > is not calling malloc at all. See the 1: before the free > error in the > > logfile? This indicates that it is the first time that the library > > has been called. This is very strange. Strdup should not be using > > its own allocator but who knows. > > It seems you are right. I have replaced strdup with malloc > and it went ok ... On my Linux box it works with strdup, so > conclusion is the AIX's libc has weird implementation of strdup > (man page says it uses malloc, but it evidently lies) dmalloc-5.5.2/contrib/Xmalloc.c000640 001751 001751 00000002767 10622115666 016326 0ustar00graygray000000 000000 /* * Provide malloc library replacements for X Window System heap routines * XtCalloc * XtFree * XtMalloc * XtRealloc * so that we can get accurate caller data. * * David Hill */ #define DMALLOC_DISABLE #include "conf.h" #include "dmalloc.h" #include "dmalloc_loc.h" #include "dmalloc_lp.h" #include "return.h" #define DO_XT_ENTRY_POINTS 1 #if DO_XT_ENTRY_POINTS static void _XtAllocError(const char *name) { (void)write(STDERR, "Xt Error: ", 10); (void)write(STDERR, name, strlen(name)); (void)write(STDERR, "\n", 1); exit(1); } char *XtMalloc(unsigned size) { char *file, *ptr; GET_RET_ADDR(file); ptr = _malloc_leap(size > 0 ? size : 1, file, 0); if (ptr == NULL) { _XtAllocError("malloc"); } return ptr; } void XtFree(char *pnt) { char *file; GET_RET_ADDR(file); if (ptr != NULL) { _free_leap(pnt, file, 0); } } char *XtCalloc(unsigned num_elements, unsigned size) { char *file; GET_RET_ADDR(file); ptr = _calloc_leap(num_elements, size ? size : 1, file, 0); if (ptr == NULL) { _XtAllocError("calloc"); } return ptr; } /* * resizes OLD_PNT to SIZE bytes and return the new space after either copying * all of OLD_PNT to the new area or truncating. returns 0L on error. */ char *XtRealloc(char *ptr, unsigned size) { char *file; GET_RET_ADDR(file); ptr = _realloc_leap(ptr, size > 0 ? size : 1, file, 0); if (ptr == NULL) { _XtAllocError("realloc"); } return ptr; } #endif /* DO_XT_ENTRY_POINTS */ dmalloc-5.5.2/contrib/aix_5l_notes000640 001751 001751 00000021427 10622115666 017071 0ustar00graygray000000 000000 [ From: Freddie M ] Here is a howto for dmalloc using AIX 5L and xlc For xlc compiler: 1. CC='xlc_r' ./configure --enable-threads 2. settings.h ifndef LOCK_THREADS #define LOCK_THREADS 1 <<<<<<< should be 1 #endif 3. malloc.c changes , diff changes also included NOTE : all "malloc" entry points need to be changed to have 2 "__" pre and post fix. Example: malloc __malloc__ free __free__ malloc.c changes: #ifdef AIX extern int __multi_threaded; #include #endif #if LOCK_THREADS /* * mutex lock the malloc library */ static void lock_thread(void) { /* we only lock if the lock-on counter has reached 0 */ #ifdef AIX /* In AIX __mutli_threaded variable is 0 until a thread is created. * It will never reset to 0 after that. */ if (__multi_threaded) { #else if (thread_lock_c == 0) { #endif #if HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&dmalloc_mutex); #endif } } /* * mutex unlock the malloc library */ static void unlock_thread(void) { #ifdef AIX /* In AIX __mutli_threaded variable is 0 until a thread is created. * It will never reset to 0 after that. */ if (__multi_threaded) { #if HAVE_PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock(&dmalloc_mutex); #endif /* ifdef AIX */ } ... #ifdef AIX void __malloc_init__() { pthread_mutex_init(&dmalloc_mutex, THREAD_LOCK_INIT_VAL); } void __malloc_prefork_lock__() { pthread_mutex_lock(&dmalloc_mutex); } void __malloc_postfork_unlock__() { pthread_mutex_unlock(&dmalloc_mutex); } /* legacy function not needed */ int __mallopt__ (int x, int y) { } /* legacy function not needed */ struct mallinfo __mallinfo__() { } /* optional - not really needed */ void __malloc_once__() { } #endif ---- here is the diff ----- *** ../1/dmalloc-4.8.2/malloc.c Mon Feb 26 13:31:16 2001 --- malloc.c Thu Sep 5 11:26:24 2002 *************** *** 61,66 **** --- 61,71 ---- #include #endif + #ifdef AIX + extern int __multi_threaded; + #include + #endif + #define DMALLOC_DISABLE #include "dmalloc.h" *************** *** 163,169 **** --- 168,181 ---- static void lock_thread(void) { /* we only lock if the lock-on counter has reached 0 */ + #ifdef AIX + /* In AIX __mutli_threaded variable is 0 until a thread is created. + * It will never reset to 0 after that. + */ + if (__multi_threaded) { + #else if (thread_lock_c == 0) { + #endif #if HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&dmalloc_mutex); #endif *************** *** 175,180 **** --- 187,202 ---- */ static void unlock_thread(void) { + #ifdef AIX + /* In AIX __mutli_threaded variable is 0 until a thread is created. + * It will never reset to 0 after that. + */ + if (__multi_threaded) { + #if HAVE_PTHREAD_MUTEX_UNLOCK + pthread_mutex_unlock(&dmalloc_mutex); + #endif + } + #else /* if the lock-on counter has not reached 0 then count it down */ if (thread_lock_c > 0) { thread_lock_c--; *************** *** 205,210 **** --- 227,233 ---- pthread_mutex_unlock(&dmalloc_mutex); #endif } + #endif } #endif *************** *** 770,776 **** * Returns 0L on error. */ #undef malloc ! DMALLOC_PNT malloc(DMALLOC_SIZE size) { char *file; --- 793,799 ---- * Returns 0L on error. */ #undef malloc ! DMALLOC_PNT __malloc__(DMALLOC_SIZE size) { char *file; *************** *** 785,791 **** * Returns 0L on error. */ #undef calloc ! DMALLOC_PNT calloc(DMALLOC_SIZE num_elements, DMALLOC_SIZE size) { DMALLOC_SIZE len = num_elements * size; char *file; --- 808,814 ---- * Returns 0L on error. */ #undef calloc ! DMALLOC_PNT __calloc__(DMALLOC_SIZE num_elements, DMALLOC_SIZE size) { DMALLOC_SIZE len = num_elements * size; char *file; *************** *** 804,810 **** * Returns 0L on error. */ #undef realloc ! DMALLOC_PNT realloc(DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size) { char *file; --- 827,833 ---- * Returns 0L on error. */ #undef realloc ! DMALLOC_PNT __realloc__(DMALLOC_PNT old_pnt, DMALLOC_SIZE new_size) { char *file; *************** *** 901,907 **** * is defined by your compiler. */ #undef free ! DMALLOC_FREE_RET free(DMALLOC_PNT pnt) { char *file; int ret; --- 924,930 ---- * is defined by your compiler. */ #undef free ! DMALLOC_FREE_RET __free__(DMALLOC_PNT pnt) { char *file; int ret; *************** *** 932,937 **** --- 955,994 ---- return ret; #endif } + + #ifdef AIX + void __malloc_init__() + { + pthread_mutex_init(&dmalloc_mutex, THREAD_LOCK_INIT_VAL); + } + + void __malloc_prefork_lock__() + { + pthread_mutex_lock(&dmalloc_mutex); + } + + void __malloc_postfork_unlock__() + { + pthread_mutex_unlock(&dmalloc_mutex); + } + + + /* legacy function not needed */ + int __mallopt__ (int x, int y) + { + } + + /* legacy function not needed */ + struct mallinfo __mallinfo__() + { + } + + /* optional - not really needed */ + void __malloc_once__() + { + } + + #endif /******************************* utility calls *******************************/ create the file mem.exp with the following entries __malloc__ __free__ __realloc__ __calloc__ __mallopt__ __mallinfo__ __malloc_init__ __malloc_prefork_lock__ __malloc_postfork_unlock__ __malloc_once__ Building a shared library for 32 and 64 bit use. Makefile - 32 bit . 1. add -DAIX to DEFS 2. change LIB_TH . This just actually renames the module built by the ld command. LIB_TH = mem32.o 3. Add to CCFLAGS CCFLAGS = -g -D_LARGE_THREADS 4. change the $(LIB_TH) build stanza $(LIB_TH) : $(OBJS) $(THREAD_OBJS) ld -b32 -m -o $@ $? -bE:mem.exp -bM:SRE -lpthreads -lc Makefile - 64 bit 1. add -DAIX to DEFS 2. change LIB_TH . This just actually renames the module built by the ld command. LIB_TH = mem64.o 3. Add to CCFLAGS CCFLAGS = -g -q64 -D_LARGE_THREADS 4. change the $(LIB_TH) build stanza $(LIB_TH) : $(OBJS) $(THREAD_OBJS) ld -b64 -m -o $@ $? -bE:mem.exp -bM:SRE -lpthreads -lc 5. If you care about making a library archive Add -X64 to the ar command $(LIBRARY) : $(OBJS) $(NORMAL_OBJS) ar -X64 cr $@ $? ranlib $@ Save mem32.o and mem64.o somewhere safe so that a make clean does not clean them out. The last step is to make an AIX shared lirary. ar -X32_64 -r libmymem.a mem32.o mem64.o On the AIX machine export MALLOCTYPE=user:libmymem.a export LIBPATH= Define your dmalloc env Test the library out Other notes: In return.h , there is a macro called #define GET_RET_ADDR(file) file = DMALLOC_DEFAULT_FILE for AIX when the calling address is not know, it will return an "unknown" in the log for unfreed memory For AIX you can do the following: typedef struct _frame { struct _frame *fr_next; /* frame list */ int fr_unused1; long fr_lr; /* link register */ } _frame_t; /* _frame_t *get_stkp(void); */ #pragma mc_func get_stkp \ { \ "7c230b78" /* mr 3,1 */ \ } #pragma reg_killed_by get_stkp gr3 #define CALLER (((_frame_t *)get_stkp())->fr_next->fr_lr) #define CALLER3 ( \ ( ((_frame_t *)get_stkp())->fr_next == NULL ) \ ? DMALLOC_DEFAULT_FILE : \ ( ((_frame_t *)get_stkp())->fr_next->fr_next == NULL ) \ ? DMALLOC_DEFAULT_FILE : ((_frame_t *)get_stkp())->fr_next->fr_next->fr_next->fr_lr \ ) #define CALLER2 ( \ ( ((_frame_t *)get_stkp())->fr_next == NULL ) \ ? DMALLOC_DEFAULT_FILE : \ ( ((_frame_t *)get_stkp())->fr_next->fr_next == NULL ) \ ? DMALLOC_DEFAULT_FILE : ((_frame_t *)get_stkp())->fr_next->fr_next->fr_lr \ ) You will want to define CALLER2 because if you define CALLER1 you will just get "malloc" as the return address. You really want to get the caller that called malloc instead of __malloc__ #define GET_RET_ADDR(file) file = (char *) CALLER2 or #define GET_RET_ADDR(file) file = (char *) CALLER1 Other notes (con't) 1. If you are debugging a system command, say telnet, this command may do an exec and not copy over the LIBPATH where the damlloc library resides. This results in the following error: USER DEFINED MALLOC ERROR: Unable to load user supplied object: "libmymem.a(mem32.o)", load() errno == 2 The solution is to place the library in /usr/lib chmod 555 chown bin.bin