Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

mkwSys.c

Go to the documentation of this file.
00001  /**************************************************************************
00002    mkwSys.c version 2.01
00003    *************************************************************************
00004    Brought to you by Michael K. Weise               http://home.att.net/~mkw
00005                      (a.k.a. Mizadil)                     mailto:mkw@att.net
00006    *************************************************************************
00007    Provides an improved, more informative memory command.
00008    Automatically sets string space size, doing away with the need to edit 
00009    MAX_STRING and recompile when adding areas.
00010    Provides several very convenient functions for use throughout your code,
00011    including chprintf(), logf(), strswitch() and my subcommand interpreter, 
00012    vinterpret(). See my comments throughout this file for information on 
00013    other features.
00014    *************************************************************************
00015    *************************************************************************
00016    This code was written and is copyright (c) 1998 by Michael K. Weise.
00017    Portions of this code are derived from code included with ROM 2.4b4a,
00018    and are therefore subject to the ROM, MERC and Diku license agreements.
00019    Released by to the public for non-commercial use on the sole condition
00020    that this comment block not be removed or altered in any way.
00021    It may be released as part of a derivative work on the conditions that 
00022    this comment block remain unaltered in the source and that proper credit
00023    be given to Michael K. Weise in the release's main licence or readme file.
00024    Crediting the author in a help entry is appreciated, but not required.
00025    *************************************************************************
00026    This code is designed to work in conjunction with MERC and its derivatives.
00027    It has been extensively tested with ROM 2.4b4a; other code bases may 
00028    require slight changes to the code. 
00029    MERC and ROM are copyrighted by their respective authors; see the comment 
00030    block in your merc.h for more information.
00031    *************************************************************************
00032    Any bugs in or suggested improvements to the code in this file should be 
00033    reported to mkw@att.net. For issues relating to learing C/C++, see my web 
00034    page. For issues relating to the ROM/MERC/Diku code in general, see 
00035    Garry's FAQ at http://www.hypercube.org/tess/rom/faq.
00036    *************************************************************************
00037 
00038 ******************
00039    Instructions
00040 ******************
00041 
00042 Note that if you're replacing version 1.0, steps 1 through 5 should be done already.
00043 
00044 (1) Remove definition of MAX_STRING 
00045 
00046 (2) At the beginning of boot_db():
00047 
00048 -   if ( ( string_space = calloc( 1, MAX_STRING ) ) == NULL )
00049 -   {
00050 -       bug( "Boot_db: can't alloc %d string space.", MAX_STRING );
00051 -       exit( 1 );
00052 -   }
00053 +   strspace_alloc();
00054 
00055 
00056 (3) In fread_string() and in fread_string_eol():
00057 
00058 -    if ( plast > &string_space[MAX_STRING - MAX_STRING_LENGTH] )
00059 +    if ( plast > &string_space[strspace_size*1024 - MAX_STRING_LENGTH] )
00060 +       strspace_size_increment();
00061 -   {
00062 -   bug( "Fread_string: MAX_STRING %d exceeded.", MAX_STRING );
00063 -   exit( 1 );
00064 -   }
00065 
00066 (4) In db.h, add
00067 
00068 #define DATPATH ""
00069 extern unsigned strspace_size;  
00070 char* strspace_alloc();
00071 void  strspace_size_increment();
00072 extern int      nAllocString;
00073 extern int      sAllocString;   
00074 extern int      social_count;
00075 
00076 (5) Remove old definition of do_memory()
00077 
00078 (6) These three little functions I wrote do wonders for code readability, besides saving
00079     lots of typing. Put the declarations in your merc.h, use them throughout your code and
00080     notice how they save typing and improve readability.
00081 
00082 int     logf( const char *format, ... );
00083             // mkw: print to log formatted
00084 
00085 int     chprintf( CHAR_DATA* ch, const char *format, ... );
00086             // mkw: print to character formatted
00087 
00088 int     strswitch( const char* arg, ... );
00089             // mkw: "bundles" any number of string comparisons neatly 
00090             // into one return value that can be used in a switch statement.
00091             // Last argument passed must be NULL to mark end of list.
00092             // Will behave badly if that is forgotten or anything other than 
00093             // strings are passed.
00094             // First variable argument is counted as one.
00095             // Returns 0 if no strings match.
00096 
00097 void    vinterpret( CHAR_DATA *ch, char *argument, ... );
00098             // mkw: This is my subcommand interpreter.
00099             // Pattern for variable args: 
00100             // { string_1, [do_fun_1|NULL], ... } NULL, [default_do_fun|NULL]
00101             // NULL passed for a string marks end of list.
00102             // NULL passed for a do_fun means no action on match.
00103   
00104 
00105 (7) Remove the definitions of alloc_mem(), free_mem(), alloc_perm() 
00106     nAllocPerm, sAllocPerm, rgFreeList and rgSizeList from db.c
00107 
00108 (8) Move the definition of MAX_PERM_BLOCK from db.c to db.h.
00109 
00110 ***************************************************************************/
00111 
00112 #if defined(macintosh)
00113 #include <types.h>
00114 #else
00115 #include <sys/types.h>
00116 #endif
00117 #include <stdio.h>
00118 #include <time.h>
00119 #include <string.h>
00120 #include <assert.h>
00121 #include <stdlib.h>
00122 #include <stdarg.h>
00123 #include "merc.h"
00124 #include "db.h"
00125 
00126 /*********************************************************
00127  *  settings
00128  */
00129 
00130 #define STRSPACE_DEFAULT (2*4096)
00131             // unit is kB
00132             // purposely set too low, so that you'll see how it works
00133 
00134 #define STRSPACE_INCREMENT 128
00135             // unit is kB
00136 
00137 #define MPROGS_INSTALLED
00138             // comment out if you do not have Ivan's (or compatible) mob programs
00139 
00140 #define DOUBLE_LOGGING
00141             // I have stdout redirected to a log file and stderr writing normally
00142             // to the console. (That helps with debugging.) All log strings are 
00143             // sent once to each stream if DOUBLE_LOGGING is defined, otherwise
00144             // only to stderr.
00145 
00146 #define SHOW_ALL_RGSIZES
00147             // Comment out if you want memory report to show only used block sizes
00148 
00149 #define ALLOC_PERM_ALIGN 32//sizeof(int)
00150             // use powers of two only
00151             // higher values may improve speed significantly on some machines, at the expense of memory.
00152             // 32 should be the fastest value on most machines
00153             // I don't recommend values below machine word length, but feel free to experiment
00154             // setting it to 1 won't save much, but slow things down considerably
00155 
00156 
00157 #define     MAX_MEM_LIST    11
00158 
00159 const size_t    rgSizeList  [MAX_MEM_LIST]
00160             = { 16, 32, 64, 128, 256, 1024, 2048, 4096, 8192, 16384, 32768-64 };
00161 
00162 
00163 /*********************************************************
00164  *  macros from mkw.h
00165  */
00166 #ifndef __mkwMUD
00167 
00168 #define MAGIC_CHECKING
00169         // comment out disable internal assertion of memory allocation/recycling
00170 
00171 #define chwrite( ch, str )  send_to_char( str, ch )
00172             // I find send_to_char()'s syntax counter-intuitive
00173 
00174 #define object_free obj_free
00175             // easy fix for name inconsistency in merc
00176 
00177 #define OK  0
00178 #define ERR 1
00179 
00180 #endif
00181 
00182 /*********************************************************
00183  *  imports
00184  */
00185 
00186 extern char *       string_space;
00187 extern int          mobile_count;
00188 extern  OBJ_DATA    *obj_free;
00189 extern  CHAR_DATA   *char_free;
00190 extern  DESCRIPTOR_DATA *descriptor_free;
00191 extern  PC_DATA     *pcdata_free;
00192 extern  AFFECT_DATA *affect_free;
00193 extern  NOTE_DATA   *note_list,*idea_list,*penalty_list,*news_list,*changes_list;
00194 
00195 
00196 
00197 /*********************************************************
00198  *  locals
00199  */
00200 
00201 int     has_system_auth( CHAR_DATA* ch );
00202 int     strspace_size_read();
00203 int     strspace_size_set( int newsize );
00204 void    strspace_size_default();
00205 extern const size_t rgSizeList  [MAX_MEM_LIST];
00206 extern void *       rgFreeList  [MAX_MEM_LIST];
00207 
00208 
00209 
00210 /****************************************************************
00211  * Implementation section
00212  */
00213 
00214 const char ver_mkwSys[]="mkwSys Version 2.01";
00215 
00216 unsigned strspace_size;  
00217 
00218 void*    rgFreeList [MAX_MEM_LIST];
00219 
00220 unsigned long nAllocGP[MAX_MEM_LIST] = { 0,0,0,0,0,0,0,0,0,0,0};
00221 
00222 int     nAllocPerm;
00223 size_t  sAllocPerm  = 0;
00224 int     nPermBlocks = 0;
00225 
00226 void boot_fail(char* module_name)
00227 {
00228     logf( "*********************  Reboot by %-11s *********************", module_name );
00229     exit( EXIT_FAILURE );
00230 }
00231 
00232 
00233 char* strspace_alloc()
00234 {
00235     strspace_size_read();
00236     if ( ( string_space = calloc( 1, strspace_size * 1024 ) ) == NULL )
00237     {
00238         logf( "mkwSys.c: Unable to allocate %d kB string space from system.", strspace_size );
00239         if( strspace_size > STRSPACE_DEFAULT )
00240             strspace_size_default();
00241         else
00242             logf( "Increase your system's virtual memory size.", strspace_size );
00243         boot_fail( "mkwSys.c" );
00244     }
00245     return string_space;
00246 }
00247 
00248 
00249 void    strspace_size_default()
00250 {
00251     strspace_size_set( STRSPACE_DEFAULT );
00252     logf( "mkwSys.c: String space size reset to program default of %d kB.", strspace_size );
00253 }
00254 
00255 
00256 void strspace_size_increment()
00257 {
00258     logf( "mkwSys.c: String space size of %d kB did not suffice.", strspace_size );
00259     strspace_size_set( strspace_size + STRSPACE_INCREMENT );
00260     logf( "mkwSys.c: Incrementing string space size to %d kB and rebooting.", strspace_size );
00261     boot_fail( "mkwSys.c" );
00262 }
00263 
00264 
00265 int strspace_size_set( int newsize )
00266 {
00267   if( newsize > 0 )
00268   {
00269     FILE* memini= fopen( DATPATH "mkwSys.ini", "w" );
00270     if( memini )
00271     {
00272         fprintf( memini, "stringspace = %u\n", newsize );
00273         fclose( memini );
00274         return OK;
00275     }
00276     else
00277     {
00278         logf( "Unable to open mkwSys.ini for writing" );
00279     }
00280   }
00281   return ERR;
00282 }
00283 
00284 
00285 int strspace_size_read()
00286 {
00287     FILE* memini= fopen( DATPATH "mkwSys.ini", "r" );
00288     if( memini )
00289     {
00290         strspace_size = 0;
00291         while( str_cmp( fread_word( memini ), "stringspace" ) )
00292             ;
00293         fscanf( memini, " = %u", &strspace_size );
00294         fclose( memini );
00295         if( !strspace_size )
00296         {
00297             logf( "mkwSys.c: String space size not set in mkwSys.ini, using default." );
00298             strspace_size_default();
00299         }
00300         else
00301             return OK;
00302     }
00303     else
00304     {
00305         logf( "mkwSys.c: Unable to open memsize.ini for reading, using default string space size." );
00306         strspace_size_default();
00307     }
00308     return ERR; 
00309 }
00310 
00311 int has_system_auth( CHAR_DATA* ch )
00312 {
00313     if( get_trust( ch ) < CREATOR )
00314     {
00315         send_to_char( "You are not authorized to issue system commands.\n\r", ch );
00316         return FALSE;
00317     }
00318     else
00319         return TRUE;
00320 }
00321 
00322 #define IMP_COUNTER( type, start, px) \
00323   int px##type() { type * p = start; int n = 0; while( p!=NULL ) { p= p->next; n++; } return n; }
00324   
00325 
00326 #define IMP_LIST_COUNTERS( type, prefix ) \
00327         IMP_COUNTER( type, prefix##list, n )    IMP_COUNTER( type, prefix##free, f )
00328   
00329 
00330             // these object types have no global list
00331 IMP_COUNTER ( PC_DATA, pcdata_free, f)
00332 IMP_COUNTER ( AFFECT_DATA, affect_free, f)
00333 
00334             // these do
00335 IMP_LIST_COUNTERS ( OBJ_DATA, object_ );
00336 IMP_LIST_COUNTERS ( CHAR_DATA, char_ );
00337 IMP_LIST_COUNTERS ( DESCRIPTOR_DATA, descriptor_ );
00338 
00339 #ifdef MPROGS_INSTALLED
00340 IMP_COUNTER ( MPROG_CODE, mprog_list, n );
00341 //IMP_LIST_COUNTER ( MPROG_LIST, ??? );
00342             // not currently implemented 
00343             // (There is no global list of MPROG_LISTs to count from)
00344 #endif
00345 
00346 int nNOTE_DATA()
00347 {   
00348     NOTE_DATA* p; int n = 0; 
00349     for( p=note_list;p!=NULL; p=p->next) n++; 
00350     for( p=idea_list;p!=NULL; p=p->next) n++; 
00351     for( p=changes_list;p!=NULL; p=p->next) n++; 
00352     for( p=penalty_list;p!=NULL; p=p->next) n++; 
00353     for( p=news_list;p!=NULL; p=p->next) n++; 
00354     return n; 
00355 }
00356 
00357 
00358 #define rpt( name, n, obj ) chprintf( ch, "%5d %-14s *%4d Bytes =%6d kB\n\r", \
00359                                      n, name, sizeof(obj), (n) * sizeof(obj)/1024 )
00360             // report on an object type
00361 
00362 #define rpt_dy( name, type ) { int n= n##type(); rpt( name, n, type ); }
00363             // report object with dynamic counting of list -
00364             // calls rpt() without evaluating n twice 
00365 
00366 #define rptsd( st, sz ) chprintf( ch, "%-34s %5d kB\n\r", st, sz )
00367             // report string and decimal
00368 
00369 #define rptdsd(n,st,sz) chprintf( ch, "%5d %-28s %5d kB\n\r", n, st, sz )
00370             // report decimal, string, decimal
00371 
00372 const char separator[] = "-------------------------------------------\n\r";
00373 
00374 void do_memory_perms( CHAR_DATA *ch, char* argument )
00375 {
00376     int i;
00377     chwrite( ch, separator );
00378     chwrite( ch, "{cPermanent memory objects in use{x\n\r");
00379     chwrite( ch, separator );
00380     rpt_dy( "Characters", CHAR_DATA );
00381     rpt( "PCs", nCHAR_DATA() - mobile_count /* should be an accurate shortcut */, PC_DATA ); 
00382     rpt_dy( "Descriptors", DESCRIPTOR_DATA );
00383     rpt( "Mob Prototypes", top_mob_index, MOB_INDEX_DATA );
00384     rpt_dy( "Objects", OBJ_DATA);
00385     rpt( "Obj Prototypes", top_obj_index, OBJ_INDEX_DATA);
00386     rpt( "Extra Descs", top_ed, EXTRA_DESCR_DATA );
00387     rpt( "Affects", top_affect, AFFECT_DATA );
00388     rpt( "Rooms", top_room, ROOM_INDEX_DATA );
00389     rpt( "Exits", top_exit, EXIT_DATA );
00390     rpt( "Shops", top_shop, SHOP_DATA );
00391     rpt( "Areas", top_area, AREA_DATA );
00392     rpt( "Resets", top_reset, RESET_DATA );
00393     rpt( "Help entries", top_help, HELP_DATA );
00394     rpt_dy( "Notes", NOTE_DATA);
00395     rpt( "Socials", social_count, struct social_type );
00396 #ifdef MPROGS_INSTALLED
00397     rpt_dy( "Mob progs", MPROG_CODE )
00398 #endif
00399     for( i= 0; i<MAX_MEM_LIST; i++)
00400 #ifndef SHOW_ALL_RGSIZES
00401        if( nAllocGP[i] )
00402 #endif
00403             chprintf( ch, "%5d GP blocks of  %6d Bytes =%6d kB\n\r", 
00404                     nAllocGP[i], rgSizeList[i], nAllocGP[i] * rgSizeList[i] / 1024);
00405     chwrite( ch, separator );
00406 }
00407 
00408 
00409 #define rptf( name, type ) { int n= f##type(); rpt( name, n, type ); }
00410 
00411 void do_memory_freelists( CHAR_DATA *ch, char* argument )
00412 {
00413     int i;
00414     chwrite( ch, separator );
00415     chwrite( ch, "Memory objects waiting to be recycled\n\r");
00416     chwrite( ch, separator );
00417     rptf( "Characters", CHAR_DATA );
00418     rptf( "PCs", PC_DATA ); 
00419     rptf( "Descriptors", DESCRIPTOR_DATA );
00420     rptf( "Objects", OBJ_DATA);
00421     rptf( "Affects", AFFECT_DATA );
00422 
00423     for( i= 0; i<MAX_MEM_LIST; i++)
00424 #ifndef SHOW_ALL_RGSIZES
00425        if( rgFreeList[i] )
00426 #endif
00427        {
00428         void* p;
00429         int n = 0;
00430         for(p= rgFreeList[i]; p != NULL; p= * ((void **) p ) )
00431             n++;
00432         chprintf( ch, "%5d GP blocks of  %6d Bytes =%6d kB\n\r", 
00433             n, rgSizeList[i], n * rgSizeList[i] / 1024);
00434        }
00435     chwrite( ch, separator );
00436 }
00437 
00438 
00439 void do_memory_heap( CHAR_DATA *ch, char* argument )
00440 {
00441     chwrite( ch, separator );
00442     chprintf( ch, "Perm Block size is set to %d kB\n\r", MAX_PERM_BLOCK/1024 );
00443     chprintf( ch, "Object alignment is set to %d Bytes\n\r", ALLOC_PERM_ALIGN );
00444      
00445     rptdsd( nPermBlocks , "Blocks allocated from heap", nPermBlocks * MAX_PERM_BLOCK/1024 );
00446     rptdsd( nAllocPerm, "Permanent objects occupy", sAllocPerm/1024 );
00447     rptsd( "Current alloc_perm() overhead", 
00448             ( nPermBlocks * MAX_PERM_BLOCK - sAllocPerm ) / 1024 );
00449     chwrite( ch, separator );
00450 
00451     rptsd( "String Space allocated at DB boot", strspace_size );
00452     rptdsd( nAllocString, "Strings in string space",  sAllocString/1024 );
00453     rptsd( "Excess string space", strspace_size - sAllocString/1024 );
00454 
00455     chwrite( ch, separator );
00456     rptsd( "Total managed heap memory", nPermBlocks * MAX_PERM_BLOCK/1024 + strspace_size );
00457     chwrite( ch, separator );
00458 }
00459 
00460 
00461         
00462 
00463 void do_memory_formats( CHAR_DATA *ch, char* argument )
00464 {
00465     chwrite( ch, separator );
00466     chprintf( ch, "Old format mobs: %d\n\rOld format objects: %d\n\r", 
00467              top_mob_index - newmobs, top_obj_index - newobjs ); 
00468     chwrite( ch, separator );
00469 }
00470 
00471 #undef rpt
00472 #undef rpt_dy
00473 #undef rptsd
00474 #undef rptdsd
00475     /* Those macros are not for general use */
00476 
00477 void do_memory_stringspace( CHAR_DATA *ch, char *argument )
00478 {
00479     if( has_system_auth(ch) )
00480     {
00481         char arg[MAX_INPUT_LENGTH];
00482         int sz = 0;
00483         argument= one_argument( argument, arg );
00484         if( is_number( arg ) )
00485             sz= atoi( arg );
00486         if( sz <= 0 || sz > 32000 )
00487         {
00488             chwrite( ch, "Invalid parameter.\n\r" );
00489             return;
00490         }
00491         if( strspace_size_set( sz ) == OK )
00492             chprintf( ch, "String space size for next DB boot set to %d kB.\n\r", sz );
00493         else
00494             chwrite( ch, "Error writing new setting to file.\n\r" );
00495     }
00496 }
00497 
00498 void do_memory_help( CHAR_DATA *ch, char *argument )
00499 {
00500     chwrite(ch, ver_mkwSys );
00501     chwrite(ch, " copyright (c) 1998 Michael K. Weise\n\r"
00502                 "See home.att.net/~mkw/mudframe.html for more information\n\n\r"
00503                 "usage: memory <command>\n\r\ravailable commands:\n\r"
00504                 "heap                Report heap memory allocated by the memory manager\n\r"
00505                 "perms               Report managed memory objects in use by other modules\n\r"
00506                 "freelists           Report memory objects waiting to be recycled\n\r"
00507                 "stringspace <size>  Set string space size in kB for next reboot\n\r"
00508                 "formats             Report old format prototypes\n\r"
00509                 "?                   This message\n\r"
00510                  );
00511 }
00512 
00513 
00514 void do_memory( CHAR_DATA *ch, char *argument )
00515 {
00516     vinterpret( ch, argument, 
00517                 "perms", do_memory_perms,
00518                 "heap", do_memory_heap,
00519                 "freelists", do_memory_freelists,
00520                 "stringspace", do_memory_stringspace,
00521                 "formats", do_memory_formats,
00522                 NULL, do_memory_help );
00523 }
00524 
00525 
00526 int strswitch( const char* arg, ... )
00527 {
00528     int i = 0;
00529     char* p;
00530     va_list caselist;
00531     if( arg[0] )
00532     {
00533         va_start( caselist, arg );
00534         while( (p = va_arg( caselist, char* )) != NULL )
00535         {
00536             i++;
00537             if( !str_prefix( arg, p ) )
00538                 return i;
00539         }
00540     }
00541     return 0;
00542 }
00543 
00544 
00545 void vinterpret( CHAR_DATA *ch, char *argument, ... )
00546 {
00547     char arg[MAX_INPUT_LENGTH];
00548     char* iStr;
00549     DO_FUN *iFun;
00550     va_list caselist;
00551     va_start( caselist, argument );
00552     argument= one_argument( argument, arg );
00553     do 
00554     {
00555         iStr = va_arg( caselist, char* );
00556         iFun = va_arg( caselist, DO_FUN* );
00557     } 
00558     while( iStr != NULL && ( !arg[0] || str_prefix( arg, iStr ) ) );
00559     if( iFun != NULL )
00560         (*iFun)( ch, argument );
00561 }
00562 
00563 
00564 size_t rgSize_lookup( size_t size )
00565 {
00566     int iList;
00567     size += sizeof( int );  // room needed for integrity marker
00568 
00569     for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
00570     {
00571         if ( size <= rgSizeList[iList] )
00572             return rgSizeList[iList] - sizeof( int );
00573     }
00574     return 0; // size won't fit into any alloc_mem() block
00575 }
00576 
00577 
00578 /*
00579  * Request a GP memory block.
00580  * GP blocks must be returned using free_mem() when no longer needed.
00581  * Checks freelist for block of appropriate size,
00582  * allocates heap memory if none available
00583  */
00584 void *alloc_mem( size_t sMem )
00585 {
00586     void *pMem;
00587     int iList;
00588 
00589 #ifdef MAGIC_CHECKING
00590      int *magic;
00591      sMem += sizeof(*magic);
00592 #endif
00593 
00594     for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
00595     {
00596         if ( sMem <= rgSizeList[iList] )
00597             break;
00598     }
00599 
00600     if ( iList == MAX_MEM_LIST )
00601     {
00602         bug( "Alloc_mem: size %d too large.", sMem );
00603         //exit( EXIT_FAILURE );
00604     return pMem;
00605     }
00606 
00607     if ( rgFreeList[iList] == NULL )
00608     {
00609         pMem              = alloc_perm( rgSizeList[iList] );
00610         nAllocGP[iList]++;
00611     }
00612     else
00613     {
00614         pMem              = rgFreeList[iList];
00615         rgFreeList[iList] = * ((void **) rgFreeList[iList]);
00616     }
00617 
00618 #ifdef MAGIC_CHECKING
00619     magic = (int *) pMem;
00620     *magic = MAGIC_NUM;
00621     pMem = (void*) (((char*)pMem) + sizeof (*magic));
00622 #endif
00623     return pMem;
00624 }
00625 
00626 
00627 
00628 /*
00629  * This is the memory manager's interface to the system heap.
00630  * All memory allocated here is either permanently typecast
00631  * and managed by the object recycler, or managed by the GP
00632  * block manager.
00633  */
00634 void *alloc_perm( size_t sMem )
00635 {
00636     static int iMemPerm;    
00637     static char *pMemPerm;
00638     void *pMem;
00639 
00640     while ( sMem % ALLOC_PERM_ALIGN != 0 )
00641         sMem++;
00642     if ( sMem > MAX_PERM_BLOCK )
00643     {
00644         bug( "Alloc_perm: %d too large.", sMem );
00645         exit( EXIT_FAILURE );
00646     }
00647 
00648     if ( pMemPerm == NULL || iMemPerm + sMem > MAX_PERM_BLOCK )
00649     {
00650         iMemPerm = 0;
00651         nPermBlocks++;
00652         if ( ( pMemPerm = calloc( 1, MAX_PERM_BLOCK ) ) == NULL )
00653         {
00654             perror( "Alloc_perm" );
00655             exit( EXIT_FAILURE );
00656         }
00657     }
00658 
00659     pMem        = pMemPerm + iMemPerm;
00660     iMemPerm   += sMem;
00661     nAllocPerm += 1;
00662     sAllocPerm += sMem;
00663     return pMem;
00664 }
00665 
00666 
00667 /*
00668  * Give a GP block back to the memory manager for recycling.
00669  */
00670 void free_mem( void *pMem, size_t sMem )
00671 {
00672     int iList;
00673 
00674 #ifdef MAGIC_CHECKING
00675     int *magic;
00676   
00677     pMem = (void*) (((char*)pMem) - sizeof (*magic));   
00678     magic = (int *) pMem;
00679   
00680     if (*magic != MAGIC_NUM)
00681     {
00682         bug("Attempt to recyle invalid memory of size %d.",sMem);
00683         bug((char*) pMem + sizeof(*magic),0);
00684         return;
00685     }
00686 
00687     *magic = 0;
00688     sMem += sizeof(*magic);
00689 #endif
00690 
00691     for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
00692     {
00693         if ( sMem <= rgSizeList[iList] )
00694             break;
00695     }
00696 
00697     if ( iList == MAX_MEM_LIST )
00698     {
00699         bug( "Free_mem: size %d too large.", sMem );
00700         exit( EXIT_FAILURE );
00701     }
00702 
00703     * ((void **) pMem) = rgFreeList[iList];
00704     rgFreeList[iList]  = pMem;
00705 
00706     return;
00707 }
00708 
00709 
00710 
00711 
00712 /* 
00713  * All ANSI C compilers aught to have stdarg.h.
00714  * If not, #include <varargs.h>
00715  * and implement logf() in traditional C style 
00716  */
00717 /*int logf( const char *format, ... )
00718 {
00719     va_list arglist;
00720     char *strtime;
00721     int status;
00722     va_start( arglist, format );
00723     strtime = ctime( &current_time );
00724     strtime[strlen(strtime)-1] = '\0';
00725     fprintf( stderr, "%s :: ", strtime );
00726 #ifdef DOUBLE_LOGGING
00727     fprintf( stdout, "%s :: ", strtime );
00728     vfprintf( stdout, format, arglist );
00729     fprintf( stdout, "\n" );
00730     fflush( stdout );
00731 #endif
00732     status = vfprintf( stderr, format, arglist );
00733     va_end( arglist );
00734     fprintf( stderr, "\n" );
00735     fflush( stderr );
00736     return status;
00737 }
00738 */
00739 
00740 int chprintf( CHAR_DATA* ch, const char *format, ... )
00741 {
00742     static char buf[MAX_STRING_LENGTH+1];
00743     va_list arglist;
00744     int nChars= 0;
00745     va_start( arglist, format );
00746     if ( format != NULL && format[0] && ch->desc != NULL )
00747     {
00748         nChars = vsprintf( buf, format, arglist );
00749         assert( nChars <= MAX_STRING_LENGTH );
00750         write_to_buffer( ch->desc, buf, nChars );
00751     }
00752     va_end( arglist );
00753     return nChars;
00754 }
00755 
00756 
00757 
00758 

Generated on Thu Jan 13 21:48:12 2005 for Beyond the Shadows by  doxygen 1.4.0