G:/ScriptBasic/source/memory.c

Go to the documentation of this file.
00001 /* 
00002 FILE:   memory.c
00003 HEADER: memory.h
00004 
00005 --GNU LGPL
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010 
00011 This library is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public
00017 License along with this library; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 TO_HEADER:
00021 
00022 typedef unsigned char BYTE, *PBYTE;
00023 
00024 typedef struct _FixSizeMemoryObject {
00025 
00026   union _fsmoval{
00027     PBYTE  pValue; // the value of the object
00028     long   lValue; // the long value of the object
00029     double dValue; // the double value of the object
00030     struct _FixSizeMemoryObject **aValue;
00031     } Value;
00032   unsigned long Size; // the actual size used (may be different from the size indicated by the type)
00033   BYTE sType; // index to the array SizeOfType. If this is LARGE_BLOCK_TYPE then
00034               // Size is the memory allocated for the value
00035   BYTE vType; // the variable type, VTYPE_/LONG/DOUBLE/STRING/REF/UNDEF/ARRAY
00036   BYTE State; // state of the variable (mortal, free or assigned)
00037   // these two pointers help to maintain either the free list or the mortal lists
00038   // a variable can never be in a free and in a mortal list at the same time
00039   // in case of reference variable these fields maintain a linked list of
00040   // variables referencing the same value
00041   struct _FixSizeMemoryObject *next;     // link to the next object
00042   union {
00043     struct _FixSizeMemoryObject *prev;   // link to the previous object
00044     struct _FixSizeMemoryObject **rprev; // link to the previous variable referencing
00045     }link;
00046   long ArrayLowLimit, ArrayHighLimit;    // If this is an array then these fields tell you where to start
00047                                          // and where to end
00048   } FixSizeMemoryObject, *pFixSizeMemoryObject, 
00049     *MortalList, **pMortalList;
00050 
00051 // these macros can be used to access the actual values of the objects
00052 #define DOUBLEVALUE(x) ((x)->Value.dValue)
00053 #define LONGVALUE(x)   ((x)->Value.lValue)
00054 #define STRINGVALUE(x) ((char *)((x)->Value.pValue))
00055 #define ARRAYVALUE(x,i)  (((x)->Value.aValue)[(i)-(x)->ArrayLowLimit])
00056 #define ARRAYLOW(x)    ((x)->ArrayLowLimit)
00057 #define ARRAYHIGH(x)   ((x)->ArrayHighLimit)
00058 #define STRLEN(x)      ((x)->Size)
00059 
00060 #define MAX_NUMBER_OF_FIX_TYPES 254
00061 #define LARGE_BLOCK_TYPE 255
00062 
00063 typedef struct _MemoryObject {
00064   unsigned long SizeOfType[MAX_NUMBER_OF_FIX_TYPES]; // SizeOfType[i] is the size of the type i
00065   BYTE iNumberOfFixTypes;    // the number of fix length type memory objects
00066                              // we can have at most MAX_NUMBER_OF_FIX_TYPES fix size types
00067                              // LARGE_BLOCK_TYPE means large block which is not stored in free list
00068   BYTE FirstStringIndex,LastStringIndex;
00069   pFixSizeMemoryObject MemoryObjectsFreeList[MAX_NUMBER_OF_FIX_TYPES];
00070   void *(*memory_allocating_function)(size_t);
00071   void (*memory_releasing_function)(void *);
00072   void *pMemorySegment; //this pointer is passed to the memory allocating functions
00073                         //this pointer is initialized in ex_init
00074   unsigned long maxderef;
00075   } MemoryObject, *pMemoryObject;
00076 
00077 #define TYPESIZE(pMo,X) (pMo->SizeOfType(X))
00078 #define IsMortal(x) ((x)->State == STATE_MORTAL)
00079 
00080 // these are fixed and stored inside the FixSizeMemoryObject in the place of the pointer
00081 // these constants should be used for the field sType
00082 #define FIX_TYPE_LONG    0
00083 #define FIX_TYPE_DOUBLE  1
00084 #define FIX_TYPE_CSTRING 2 // constant string variable, pointing to a string that should not be altered
00085 #define MAX_FIX_TYPE     3
00086 #define FIX_TYPE_ALLOC FIX_TYPE_LONG // the one (arbitrary) that is used to list free variables
00087 
00088 #define STATE_UNKNOWN  0
00089 #define STATE_FREE     1
00090 #define STATE_MORTAL   2
00091 #define STATE_IMMORTAL 3
00092 
00093 // these constants are for vType (which is variable type)
00094 // you can define other variables in case you need other types
00095 #define VTYPE_LONG   0 // long value stored inside the struct
00096 #define VTYPE_DOUBLE 1 // double value stored inside the struct
00097 #define VTYPE_STRING 2 // string pointed by Value.pValue
00098 #define VTYPE_ARRAY  3 // array pointing to other values
00099 #define VTYPE_REF    4 // reference value pointing to another variable
00100 #define VTYPE_UNDEF  5 // this is used, when an undef variable is referenced
00101 */
00102 #include <stdlib.h>
00103 #include <string.h>
00104 
00105 #ifdef _DEBUG
00106 #include <stdio.h>
00107 #endif
00108 
00109 #include "errcodes.h"
00110 #include "memory.h"
00111 #include "myalloc.h"
00112 
00113 /*POD
00114 =H memory_InitStructure()
00115 
00116 Each execution context should have its own memory object responsible for the administration
00117 of the variables and the memory storing the values assigned to variables.
00118 
00119 This function initializes such a memory object.
00120 
00121 /*FUNCTION*/
00122 int memory_InitStructure(pMemoryObject pMo
00123   ){
00124 /*noverbatim
00125 CUT*/
00126 /*  int i;
00127 
00128   for( i=0 ; i < MAX_NUMBER_OF_FIX_TYPES ; i++ ){
00129     pMo->SizeOfType[i] = 0;
00130     pMo->MemoryObjectsFreeList[i] = NULL;
00131     }
00132 */
00133   memset(pMo->SizeOfType,0,sizeof(long)*MAX_NUMBER_OF_FIX_TYPES);
00134   memset(pMo->MemoryObjectsFreeList,0,sizeof(void *)*MAX_NUMBER_OF_FIX_TYPES);
00135   pMo->iNumberOfFixTypes = MAX_FIX_TYPE; /* long, double and constant string are implicit types that 
00136                                             are stored inside the FixSizeMemoryObject */
00137   pMo->pMemorySegment = alloc_InitSegment(pMo->memory_allocating_function,pMo->memory_releasing_function);
00138   if( pMo->pMemorySegment == NULL )return MEM_ERROR_MEMORY_LOW;
00139   return MEM_ERROR_SUCCESS;
00140   }
00141 
00142 /*POD
00143 =H memory_RegisterType()
00144 
00145 This function should be used to register a variable type. The return value
00146 is the serial number of the type that should later be used to reference the type.
00147 
00148 /*FUNCTION*/
00149 int memory_RegisterType(pMemoryObject pMo,
00150                         unsigned long SizeOfThisType
00151   ){
00152 /*noverbatim
00153 The argument of the function is the size of the type in terms of bytes. Usually this
00154 is calculated using the C structure T<sizeof>.
00155 
00156 If the type can not be registered -1 is returned.
00157 CUT*/
00158   if( pMo->iNumberOfFixTypes >= MAX_NUMBER_OF_FIX_TYPES )return -1;
00159   pMo->SizeOfType[pMo->iNumberOfFixTypes++] = SizeOfThisType;
00160   return pMo->iNumberOfFixTypes-1;
00161   }
00162 
00163 
00164 /*POD
00165 =H memory_RegisterTypes()
00166 
00167 This function should be used to initialize the usual T<FixSizeMemoryObject> types. This
00168 sets some usual string sizes, but the caller may not call this function and set different
00169 size objects.
00170 
00171 /*FUNCTION*/
00172 void memory_RegisterTypes(pMemoryObject pMo
00173   ){
00174 /*noverbatim
00175 This function registers the different string sizes. In the current implementation a string has
00176 at least 32 characters. If this is longer that that (including the terminating zchar) then
00177 a 64 byte fix size object is allocated. If this is small enough then a 128 byte fix size memory
00178 object is allocated and so on up to 1024 bytes. If a string is longer that that then a LARGE_OBJECT_TYPE
00179 is allocated.
00180 
00181 The reason to register these types is that this memory management module keeps a list for these
00182 memory pieces and when a new short string is needed it may be available already without calling
00183 T<malloc>. On the other hand when a T<LARGE_OBJECT_TYPE> value is released it is always passed back
00184 to the operating system calling T<free>.
00185 
00186 CUT*/
00187 
00188   pMo->FirstStringIndex = memory_RegisterType(pMo,32);
00189                           memory_RegisterType(pMo,64);
00190                           memory_RegisterType(pMo,128);
00191                           memory_RegisterType(pMo,256);
00192                           memory_RegisterType(pMo,512);
00193   pMo->LastStringIndex = memory_RegisterType(pMo,1024);
00194   }
00195 
00196 #ifdef _DEBUG
00197 /*POD
00198 =H memory_DebugDump()
00199 
00200 This is a debugging function that dumps several variable data to the standard output.
00201 The actual behavior of the function may change according to the actual debug needs.
00202 
00203 /*FUNCTION*/
00204 void memory_DebugDump(pMemoryObject pMo
00205   ){
00206 /*noverbatim
00207 CUT*/
00208   pFixSizeMemoryObject p;
00209   int i;
00210   unsigned long count;
00211 
00212   for( i = pMo->FirstStringIndex ; i <= pMo->LastStringIndex ; i++ ){
00213     p = pMo->MemoryObjectsFreeList[i];
00214     count = 0;
00215     while( p ){
00216       p = p->next;
00217       count++;
00218       }
00219     printf("list %d. length=%d\n",i,count);
00220     }
00221 
00222   }
00223 #endif
00224 
00225 /*POD
00226 =H memory_NewVariable()
00227 
00228 This function should be used whenever a new variable is to be allocated.
00229 The function returns a pointer to a T<FixSizeMemoryObject> structure that
00230 holds the variable information and pointer to the memory that stores the
00231 actual value for the memory.
00232 
00233 If there is not engough memory or the calling is illegal the returned value is T<NULL>
00234 /*FUNCTION*/
00235 pFixSizeMemoryObject memory_NewVariable(pMemoryObject pMo,
00236                                         int type,
00237                                         unsigned long LargeBlockSize
00238   ){
00239 /*noverbatim
00240 
00241 The second argument gives the type of the memory object to be allocated. If this
00242 value is T<LARGE_BLOCK_TYPE> then the third argument is used to determine the size of the
00243 memory to be allocated. If the type if NOT T<LARGE_BLOCK_TYPE> then this argument is
00244 ignored and the proper size is allocated.
00245 
00246 If the type has memory that was earlier allocated and released it is stored in a free list
00247 and is reused.
00248 
00249 CUT*/
00250   pFixSizeMemoryObject p;
00251   int atype; /* from which we allocate */
00252 
00253   if( type == LARGE_BLOCK_TYPE ){
00254     p = alloc_Alloc(sizeof(FixSizeMemoryObject),pMo->pMemorySegment);
00255     if( p == NULL )return NULL;
00256     p->sType = type;
00257     p->State = STATE_UNKNOWN;
00258     p->next = NULL;
00259     p->link.prev = NULL;
00260     p->ArrayHighLimit = 0;
00261     p->ArrayLowLimit  = 1;
00262     p->Size = LargeBlockSize;
00263     p->Value.pValue = alloc_Alloc(LargeBlockSize,pMo->pMemorySegment);
00264     if( p->Value.pValue == NULL ){
00265       alloc_Free(p,pMo->pMemorySegment);
00266       return NULL;
00267       }
00268     return p;
00269     }
00270 
00271   if( type >= MAX_NUMBER_OF_FIX_TYPES )return NULL;
00272 
00273   /* if the type is so that it does not use extra memory to store the value, like
00274      long, double or constant string then use only one list. No matter which, but
00275      only one. */
00276   if( type < MAX_FIX_TYPE )
00277     atype = FIX_TYPE_ALLOC;
00278   else
00279     atype = type;
00280 
00281   /* Check if there is any free variable on the free list of the type. */
00282   if( pMo->MemoryObjectsFreeList[atype] == NULL ){
00283     p = alloc_Alloc(sizeof(FixSizeMemoryObject),pMo->pMemorySegment);
00284     if( p == NULL )return NULL;
00285     p->sType = type;
00286     p->State = STATE_UNKNOWN;
00287     p->next = NULL;
00288     p->link.prev = NULL;
00289     /* if size is null then the variable is stored inside the FixSizeMemoryObject */
00290     if( pMo->SizeOfType[type] != 0 ){
00291       p->Value.pValue = alloc_Alloc(pMo->SizeOfType[type],pMo->pMemorySegment);
00292       if( p->Value.pValue == NULL ){
00293         alloc_Free(p,pMo->pMemorySegment);
00294         return NULL;
00295         }
00296       }else{
00297       p->Value.pValue = NULL;
00298       }
00299     return p;
00300     }
00301 
00302   p = pMo->MemoryObjectsFreeList[atype];
00303   pMo->MemoryObjectsFreeList[atype] = pMo->MemoryObjectsFreeList[atype]->next;
00304   if( pMo->MemoryObjectsFreeList[atype] )
00305     pMo->MemoryObjectsFreeList[atype]->link.prev = NULL;
00306 
00307   p->sType = type;
00308   p->next = NULL;
00309   p->link.prev = NULL;
00310   p->ArrayHighLimit = 0;
00311   p->ArrayLowLimit  = 1;
00312   p->State = STATE_UNKNOWN;
00313   return p;
00314   }
00315 
00316 /*POD
00317 =H memory_ReleaseVariable()
00318 
00319 This function should be used to release a memory object.
00320 
00321 /*FUNCTION*/
00322 int memory_ReleaseVariable(pMemoryObject pMo,
00323                            pFixSizeMemoryObject p
00324   ){
00325 /*noverbatim
00326 CUT*/
00327   long i;
00328   int atype; /* from which we allocate */
00329   pFixSizeMemoryObject *pRefHead,*pRef,pSwap;
00330 #ifdef _DEBUG
00331 pFixSizeMemoryObject q;
00332 static int dbgc=0;
00333 #endif
00334   /* ease the life of caller if it does not check that the value is undef. */
00335   if( p == NULL )return 0;
00336 
00337 #ifdef _DEBUG
00338   if( p->sType != LARGE_BLOCK_TYPE ){
00339     q = pMo->MemoryObjectsFreeList[p->sType];
00340     while( q ){
00341       if( q == p ){
00342         printf("A released memory location is rereleased.\n");
00343         exit(666);
00344         }
00345       q = q->next;
00346       }
00347    }
00348 #endif
00349 
00350   /* if there is any variable referring to this value then we need this value
00351      we will swap the two variables. */
00352   if( p->State == STATE_IMMORTAL && p->link.rprev && p->vType != VTYPE_REF){
00353     /* change the two variables so that the variable being released will point to
00354        the REF structure and the first in the list referring to this variable will point
00355        to the actual value. */
00356     pRefHead = p->link.rprev;
00357     /* save this pointer, we will need it after the swap */
00358     pRef = (*pRefHead)->link.rprev;
00359     /* perform the swapping and the REF variable will be released (but w/o unlinking!!!!)*/
00360     pSwap = p;
00361     p = *pRefHead;
00362     *pRefHead = pSwap;
00363     /* The value should start the link correctly, instead of pointing to itself. Before the swap
00364        the pointer (pRefHead)->link.rprev pointed to the second element (or NULL). This pointer is
00365        in p->link.rprev after the swap. This has to be placed "back" to the structure pointed by
00366        *pRefHead */
00367     (*pRefHead)->link.rprev = pRef;
00368     /* this is not a reference anymore thus there is no next anymore */
00369     (*pRefHead)->next = NULL;
00370     if( pRef )(*pRef)->next = *pRefHead;
00371     /* alter all other references so that they reference the new head */
00372     while( pRef ){
00373       (*pRef)->Value.aValue = pRefHead;
00374       pRef = (*pRef)->link.rprev;
00375       }
00376     }else{/* if a reference variable is deleted then we have to unlink it
00377     but this is an "else" branch and we do not perform this unlinking when
00378     releasing a reference variable that was released because it was swapped
00379     with a non-ref variable Such a ref variable is released the normal way
00380     just as if it was a long. */
00381     if( p->State == STATE_IMMORTAL && p->vType == VTYPE_REF ){
00382       if( p->next )
00383         p->next->link.rprev = p->link.rprev;
00384       if( p->link.rprev )
00385         (*(p->link.rprev))->next = p->next;
00386       p->link.rprev = NULL;
00387       p->next = NULL;
00388       }
00389     }
00390   /* if the variable is an array then all the elements should be released */
00391   if( p->vType == VTYPE_ARRAY ){
00392     for( i = p->ArrayLowLimit ; i<= p->ArrayHighLimit ; i++ )
00393       if( p->Value.aValue[i - p->ArrayLowLimit] )
00394         memory_ReleaseVariable(pMo,p->Value.aValue[i - p->ArrayLowLimit]);
00395     }
00396 
00397   /* if it is a large block, then release it */
00398   if( p->sType == LARGE_BLOCK_TYPE ){
00399     if( p->Value.pValue )
00400       alloc_Free(p->Value.pValue,pMo->pMemorySegment);
00401     alloc_Free(p,pMo->pMemorySegment);
00402     return 0;
00403     }
00404 
00405   /* if the type is so that it does not use extra memory to store the value, like
00406      long, double or constant string then use only one list. No matter which, but
00407      only one. */
00408   if( p->sType < MAX_FIX_TYPE )
00409     atype = FIX_TYPE_ALLOC;
00410   else
00411     atype = p->sType;
00412 
00413   /* link the item into the free list */
00414   p->next = pMo->MemoryObjectsFreeList[atype];
00415   p->link.prev = NULL;
00416   if( p->next )
00417     p->next->link.prev = p;
00418   p->State = STATE_FREE;
00419   pMo->MemoryObjectsFreeList[atype] = p;
00420   return 0;
00421   }
00422 
00423 /*POD
00424 =H memory_NewString()
00425 
00426 This function should be used to allocate string variable.
00427 /*FUNCTION*/
00428 pFixSizeMemoryObject memory_NewString(pMemoryObject pMo,
00429                                       unsigned long StringSize
00430   ){
00431 /*noverbatim
00432 
00433 The second argument specifies the length of th required string including.
00434 
00435 The function checks the desired length and if this is small then is allocates a fix size
00436 object. If this is too large then it allocates a T<LARGE_BLOCK_TYPE>
00437 
00438 CUT*/
00439   BYTE i;
00440   pFixSizeMemoryObject p;
00441 
00442   for( i=pMo->FirstStringIndex ; i<= pMo->LastStringIndex ; i++ ){
00443     if( StringSize <= pMo->SizeOfType[i] ){
00444       p = memory_NewVariable(pMo,i,0);
00445       if( p == NULL )return NULL;
00446       p->vType = VTYPE_STRING;
00447       p->Size = StringSize;
00448       return p;
00449       }
00450     }
00451   p = memory_NewVariable(pMo,(int)LARGE_BLOCK_TYPE,StringSize);
00452   if( p == NULL )return NULL;
00453   p->vType = VTYPE_STRING;
00454   return p;
00455   }
00456 
00457 /*POD
00458 =H memory_NewCString()
00459 
00460 This function should be used to allocate variable to store a constant string.
00461 /*FUNCTION*/
00462 pFixSizeMemoryObject memory_NewCString(pMemoryObject pMo,
00463                                        unsigned long StringSize
00464   ){
00465 /*noverbatim
00466 
00467 The second argument specifies the length of the required string.
00468 CUT*/
00469   pFixSizeMemoryObject p;
00470 
00471   p = memory_NewVariable(pMo,FIX_TYPE_CSTRING,0);
00472   if( p == NULL )return NULL;
00473   p->Size = StringSize;
00474   p->vType = VTYPE_STRING;
00475   return p;
00476   }
00477 
00478 /*POD
00479 =H memory_SetRef()
00480 
00481 Set the variable T<ppVar> to reference the variable T<ppVal>.
00482 
00483 /*FUNCTION*/
00484 int memory_SetRef(pMemoryObject pMo,
00485                    pFixSizeMemoryObject *ppVar,
00486                    pFixSizeMemoryObject *ppVal
00487   ){
00488 /*noverbatim
00489 
00490 CUT*/
00491   unsigned long refcount;
00492   pFixSizeMemoryObject *ppVAL;
00493   refcount = pMo->maxderef;
00494 
00495   /* if the value to reference points to a variable that is a reference itself then
00496      we dereference it so that the reference always points to the final variable
00497      holding a normal (non-reference) value */
00498   while( ppVal && *ppVal && (*ppVal)->vType == VTYPE_REF && refcount ){
00499     ppVal = (*ppVal)->Value.aValue ;
00500     refcount --;
00501     }
00502 
00503   if( *ppVal && (*ppVal)->vType == VTYPE_REF )return COMMAND_ERROR_CIRCULAR;
00504 
00505   /* If the variable to be referenced is undef presented as NULL pointer then
00506      we have to convert it to "stored" undef to have a structure that has space
00507      for the rprev pointer that points backward.
00508   */
00509   if( *ppVal == NULL ){
00510     *ppVal = memory_NewUndef(pMo);
00511     if( *ppVal == NULL )return COMMAND_ERROR_MEMORY_LOW;
00512     }
00513 
00514   ppVAL = ppVal;
00515   /* now hook the new reference variable to the end of the list of the referencing variables */
00516   refcount = pMo->maxderef;
00517   while( (*ppVal)->link.rprev ){
00518     ppVal = (*ppVal)->link.rprev;
00519     if( ! refcount-- )return COMMAND_ERROR_CIRCULAR;
00520     }
00521   (*ppVal)->link.rprev = ppVar;
00522   (*ppVar)->next = *ppVal;
00523 
00524   /* now set all variables that were referencing ppVar to reference ppVal */
00525   refcount = pMo->maxderef;
00526   while( (*ppVar)->link.rprev ){
00527     (*ppVar)->Value.aValue = ppVAL;
00528     ppVar = (*ppVar)->link.rprev;
00529     if( ! refcount-- )return COMMAND_ERROR_CIRCULAR;
00530     }
00531   /* Set the reference even for the last one that has no predeccessor. */
00532   (*ppVar)->Value.aValue = ppVAL;
00533 
00534   return COMMAND_ERROR_SUCCESS;
00535   }
00536 
00537 /*POD
00538 =H memory_NewRef()
00539 
00540 /*FUNCTION*/
00541 pFixSizeMemoryObject memory_NewRef(pMemoryObject pMo
00542   ){
00543 /*noverbatim
00544 CUT*/
00545   pFixSizeMemoryObject p;
00546   p = memory_NewVariable(pMo,(BYTE)FIX_TYPE_LONG,0);
00547   if( p == NULL )return NULL;
00548   p->vType = VTYPE_REF;
00549   p->State = STATE_IMMORTAL;
00550   p->link.prev = p->next = NULL;
00551   p->Value.aValue = NULL;
00552   return p;
00553   }
00554 
00555 /*POD
00556 =H memory_IsUndef()
00557 
00558 This function returns if the examined variable is T<undef>. Since a
00559 variable containing T<undef> but having other variables referencing this
00560 variable is NOT stored as T<NULL> examining the variable agains T<NULL> is
00561 not enough anymore since reference variables were introduced.
00562 
00563 /*FUNCTION*/
00564 int memory_IsUndef(pFixSizeMemoryObject pVar
00565   ){
00566 /*noverbatim
00567 CUT*/
00568   if( pVar == NULL )return 1;
00569   if( pVar->vType == VTYPE_UNDEF )return 1;
00570   return 0;
00571   }
00572 
00573 /*POD
00574 =H memory_Type()
00575 
00576 This function returns the type of the variable. In case the program
00577 does not want to check the T<NULL> undef, but wants to get T<VTYPE_UNDEF>
00578 even if the variable is real T<undef> being T<NULL> calling this function
00579 is safe. Use this function instead of the macro T<TYPE> defined in T<command.h>
00580 is there is doubt.
00581 
00582 /*FUNCTION*/
00583 int memory_Type(pFixSizeMemoryObject pVar
00584   ){
00585 /*noverbatim
00586 CUT*/
00587   if( pVar == NULL )return VTYPE_UNDEF;
00588   return pVar->vType;
00589   }
00590 
00591 /*POD
00592 =H memory_SelfOrRealUndef()
00593 
00594 /*FUNCTION*/
00595 pFixSizeMemoryObject memory_SelfOrRealUndef(pFixSizeMemoryObject pVar
00596   ){
00597 /*noverbatim
00598 CUT*/
00599   if( pVar == NULL )return NULL;
00600   if( pVar->vType == VTYPE_UNDEF )return NULL;
00601   return pVar;
00602   }
00603 
00604 /*POD
00605 =H memory_NewUndef()
00606 
00607 /*FUNCTION*/
00608 pFixSizeMemoryObject memory_NewUndef(pMemoryObject pMo
00609   ){
00610 /*noverbatim
00611 CUT*/
00612   pFixSizeMemoryObject p;
00613   p = memory_NewVariable(pMo,(BYTE)FIX_TYPE_LONG,0);
00614   if( p == NULL )return NULL;
00615   p->vType = VTYPE_UNDEF;
00616   p->State = STATE_IMMORTAL;
00617   p->link.prev = p->next = NULL;
00618   p->Value.aValue = NULL;
00619   return p;
00620   }
00621 
00622 /*POD
00623 =H memory_ReplaceVariable()
00624 
00625 /*FUNCTION*/
00626 int memory_ReplaceVariable(pMemoryObject pMo,
00627                            pFixSizeMemoryObject *Lval,
00628                            pFixSizeMemoryObject NewValue,
00629                            pMortalList pMortal,
00630                            int iDupFlag
00631   ){
00632 /*noverbatim
00633 CUT*/
00634   int iErrorCode;
00635 
00636   iErrorCode = 0;
00637   /* This is quite common that a variable is used to hold the same type of value. Changing the value
00638      only and not allocating a new variable and releasing the old speeds up execution a bit. I could
00639      see some speed improvement when running the program mandel1.bas */
00640   if( memory_IsUndef(*Lval) && memory_IsUndef(NewValue) )return COMMAND_ERROR_SUCCESS;
00641 
00642   if( *Lval && NewValue ){
00643     if( NewValue->vType == VTYPE_LONG && (*Lval)->vType == VTYPE_LONG ){
00644       LONGVALUE(*Lval) = LONGVALUE(NewValue);
00645       return COMMAND_ERROR_SUCCESS;
00646       }
00647 
00648     if( NewValue->vType == VTYPE_DOUBLE && (*Lval)->vType == VTYPE_DOUBLE ){
00649       DOUBLEVALUE(*Lval) = DOUBLEVALUE(NewValue);
00650       return COMMAND_ERROR_SUCCESS;
00651       }
00652     }
00653 
00654   /* after the references have been looked after we duplicate the result to have an own copy of the value. */
00655   if( NewValue && iDupFlag ){
00656     NewValue = memory_DupMortalize(pMo,NewValue,pMortal,&iErrorCode);
00657     if( iErrorCode )return iErrorCode;
00658     }
00659 
00660 
00661   /* if the result of the expression is not undef then immortalize */
00662   if( NewValue )
00663     /* we immortalize the new variable if it is a variable and not NULL meaning undef */
00664     memory_Immortalize(NewValue,pMortal);
00665 
00666   /* if there are other variables that reference this variable and the value is undef then we need a
00667       stored undef */
00668   if( *Lval && (*Lval)->link.rprev && NewValue == NULL )NewValue = memory_NewUndef(pMo);
00669 
00670   /* The new value will hold the same reference information as the former value.
00671      The former on the other hand is going to be unhooked. */
00672   if( *Lval && (*Lval)->link.rprev ){
00673     NewValue->link.rprev = (*Lval)->link.rprev;
00674     if( NewValue->link.rprev )(*(NewValue->link.rprev))->next = NewValue;
00675     (*Lval)->link.rprev = NULL;
00676     NewValue->next = (*Lval)->next;
00677     (*Lval)->next = NULL;
00678     }
00679   /* if this variable had value assigned to it then release that value */
00680   if( *Lval )memory_ReleaseVariable(pMo,*Lval);
00681 
00682   /* and finally assign the code to the variable */
00683   *Lval = NewValue;
00684 
00685   return COMMAND_ERROR_SUCCESS;
00686   }
00687 
00688 /*POD
00689 =H memory_NewLong()
00690 
00691 /*FUNCTION*/
00692 pFixSizeMemoryObject memory_NewLong(pMemoryObject pMo
00693   ){
00694 /*noverbatim
00695 CUT*/
00696   pFixSizeMemoryObject p;
00697   p = memory_NewVariable(pMo,(BYTE)FIX_TYPE_LONG,0);
00698   if( p == NULL )return NULL;
00699   p->vType = VTYPE_LONG;
00700   p->State = STATE_IMMORTAL;
00701   p->link.prev = p->next = NULL;
00702   return p;
00703   }
00704 
00705 /*POD
00706 =H memory_NewDouble()
00707 
00708 /*FUNCTION*/
00709 pFixSizeMemoryObject memory_NewDouble(pMemoryObject pMo
00710   ){
00711 /*noverbatim
00712 CUT*/
00713   pFixSizeMemoryObject p;
00714   p = memory_NewVariable(pMo,FIX_TYPE_DOUBLE,0);
00715   if( p == NULL )return NULL;
00716   p->vType = VTYPE_DOUBLE;
00717   p->link.prev = p->next = NULL;
00718   p->State = STATE_IMMORTAL;
00719   return p;
00720   }
00721 
00722 /*POD
00723 =H memory_CopyArray
00724 
00725 /*FUNCTION*/
00726 pFixSizeMemoryObject memory_CopyArray(pMemoryObject pMo,
00727                                       pFixSizeMemoryObject p
00728   ){
00729 /*noverbatim
00730 CUT*/
00731   long aLow,aHigh;
00732   pFixSizeMemoryObject result;
00733   long i;
00734 
00735   if( p == NULL )return NULL;
00736   if( p->vType != VTYPE_ARRAY )return NULL;
00737   aLow = p->ArrayLowLimit;
00738   aHigh = p->ArrayHighLimit;
00739   result = memory_NewArray(pMo,aLow,aHigh);
00740   if( result == NULL )return NULL;
00741   for( i=0 ; i <= aHigh-aLow ; i++ ){
00742     if( memory_IsUndef(p->Value.aValue[i]) )continue;
00743     switch(p->Value.aValue[i]->vType ){
00744       case VTYPE_ARRAY :
00745         result->Value.aValue[i] = memory_CopyArray(pMo,p->Value.aValue[i]);
00746         if( result->Value.aValue[i] == NULL )return NULL;
00747         continue;
00748       case VTYPE_LONG:
00749         result->Value.aValue[i] = memory_NewLong(pMo);
00750         if( result->Value.aValue[i] == NULL )return NULL;
00751         result->Value.aValue[i]->Value.lValue = p->Value.aValue[i]->Value.lValue;
00752         continue;
00753       case VTYPE_DOUBLE:
00754         result->Value.aValue[i] = memory_NewDouble(pMo);
00755         if( result->Value.aValue[i] == NULL )return NULL;
00756         result->Value.aValue[i]->Value.dValue = p->Value.aValue[i]->Value.dValue;
00757         continue;
00758       case VTYPE_STRING:
00759         result->Value.aValue[i] = memory_NewString(pMo,STRLEN(p->Value.aValue[i]));
00760         if( result->Value.aValue[i] == NULL )return NULL;
00761         memcpy(result->Value.aValue[i]->Value.pValue,
00762                     p->Value.aValue[i]->Value.pValue,STRLEN(p->Value.aValue[i]));
00763         continue;
00764       case VTYPE_REF:
00765         result->Value.aValue[i] = memory_NewRef(pMo);
00766         memory_SetRef(pMo,&(result->Value.aValue[i]),&(p->Value.aValue[i]));
00767         continue;
00768       }
00769     }
00770   return result;
00771   }
00772 
00773 /*POD
00774 =H memory_NewArray()
00775 
00776 This function should be used whenever a new array is to be allocated.
00777 
00778 /*FUNCTION*/
00779 pFixSizeMemoryObject memory_NewArray(pMemoryObject pMo,
00780                                      long LowIndex,
00781                                      long HighIndex
00782   ){
00783 /*noverbatim
00784 The index variables define the indices that are to be used when accessing an
00785 array element. The index values are inclusive.
00786 CUT*/
00787   pFixSizeMemoryObject p;
00788   long i;
00789 
00790   p = memory_NewVariable(pMo,LARGE_BLOCK_TYPE, (HighIndex-LowIndex+1)*sizeof(void *));
00791   if( p == NULL )return NULL;
00792   p->vType = VTYPE_ARRAY;
00793   p->ArrayHighLimit = HighIndex;
00794   p->ArrayLowLimit = LowIndex;
00795   /* initialize the array */
00796   for( i=LowIndex ; i <= HighIndex ; i++ )
00797     p->Value.aValue[i - LowIndex] = NULL;
00798   p->link.prev = p->next = NULL;
00799   p->State = STATE_IMMORTAL;
00800   return p;
00801   }
00802 
00803 /*POD
00804 =H memory_ReDimArray()
00805 
00806 This function should be used when an array needs redimensioning.
00807 If the redimensioning is succesful the function returns the pointer
00808 to the argument T<p>. If memory allocation is needed and the memory
00809 allocation fails the function returns T<NULL>. In this case the 
00810 original array is not changed.
00811 
00812 If the redimensioned array is smaller that the original no memory allocation
00813 takes place, only the array elements (pointers) are moved.
00814 
00815 /*FUNCTION*/
00816 pFixSizeMemoryObject memory_ReDimArray(pMemoryObject pMo,
00817                                        pFixSizeMemoryObject p,
00818                                        long LowIndex,
00819                                        long HighIndex
00820   ){
00821 /*noverbatim
00822 CUT*/
00823   unsigned long NewSize;
00824   long i;
00825   pFixSizeMemoryObject *pValue;
00826 
00827   NewSize = (HighIndex-LowIndex+1)*sizeof(void*);
00828   if( NewSize > p->Size ){
00829     pValue = alloc_Alloc(NewSize,pMo->pMemorySegment);
00830     if( pValue == NULL )return NULL;
00831 
00832     for( i = LowIndex ; i<= HighIndex ; i++ )
00833       if( i < p->ArrayLowLimit || i > p->ArrayHighLimit )
00834         pValue[i-LowIndex] = NULL;
00835       else{
00836         pValue[i-LowIndex] = p->Value.aValue[i-p->ArrayLowLimit];
00837         /* If this is a reference value and there is a next (should be) than that points
00838            to this variable in the field link.rprev. Because we allocated a new variable
00839            as an array element we have to alter that pointer to point to the new variable. */
00840         if( p->Value.aValue[i-p->ArrayLowLimit] && 
00841             p->Value.aValue[i-p->ArrayLowLimit]->vType == VTYPE_REF &&
00842             (p->Value.aValue[i-p->ArrayLowLimit])->next )
00843           (p->Value.aValue[i-p->ArrayLowLimit])->next->link.rprev = pValue+i-LowIndex;
00844         }
00845 
00846     alloc_Free(p->Value.pValue,pMo->pMemorySegment);
00847     p->Value.aValue = pValue;
00848     p->ArrayHighLimit = HighIndex;
00849     p->ArrayLowLimit = LowIndex;
00850     return p;
00851     }
00852 
00853   pValue = p->Value.aValue;
00854   if( LowIndex < p->ArrayLowLimit )
00855     for( i = HighIndex ; i>= LowIndex ; i-- )
00856       if( i < p->ArrayLowLimit || i > p->ArrayHighLimit )
00857         pValue[i-LowIndex] = NULL;
00858       else{
00859         pValue[i-LowIndex] = pValue[i-p->ArrayLowLimit];
00860         /* see comments above */
00861         if( p->Value.aValue[i-p->ArrayLowLimit]->vType == VTYPE_REF &&
00862             (p->Value.aValue[i-p->ArrayLowLimit])->next )
00863           (p->Value.aValue[i-p->ArrayLowLimit])->next->link.rprev = pValue+i-LowIndex;
00864         }
00865   else
00866     for( i = LowIndex ; i<= HighIndex ; i++ )
00867       if( i < p->ArrayLowLimit || i > p->ArrayHighLimit )
00868         pValue[i-LowIndex] = NULL;
00869       else{
00870         pValue[i-LowIndex] = pValue[i-p->ArrayLowLimit];
00871         /* see comments above */
00872         if( p->Value.aValue[i-p->ArrayLowLimit]->vType == VTYPE_REF &&
00873             (p->Value.aValue[i-p->ArrayLowLimit])->next )
00874           (p->Value.aValue[i-p->ArrayLowLimit])->next->link.rprev = pValue+i-LowIndex;
00875         }
00876   p->ArrayHighLimit = HighIndex;
00877   p->ArrayLowLimit = LowIndex;
00878   return p;
00879   }
00880 
00881 /*POD
00882 =H memory_CheckArrayIndex()
00883 
00884 This function should be called before accessing a certain element of an array.
00885 The function checks that the index is within the index limitsof the array
00886 and in case the index is outside the index limits of the array it redimensionate the
00887 array.
00888 
00889 The function returns the pointer passed as parameter T<p> or NULL in case there is a
00890 memory allocation error.
00891 /*FUNCTION*/
00892 pFixSizeMemoryObject memory_CheckArrayIndex(pMemoryObject pMo,
00893                                             pFixSizeMemoryObject p,
00894                                             long Index
00895   ){
00896 /*noverbatim
00897 CUT*/
00898 
00899   if( p->ArrayHighLimit < Index )
00900     return memory_ReDimArray(pMo,p,p->ArrayLowLimit,Index);
00901   if( p->ArrayLowLimit > Index )
00902     return memory_ReDimArray(pMo,p,Index,p->ArrayHighLimit);
00903   return p;
00904   }
00905 
00906 
00907 /*POD
00908 =H memory_Mortalize()
00909 
00910 This function should be used when a variable is to be put in a mortal list.
00911 
00912 /*FUNCTION*/
00913 void memory_Mortalize(pFixSizeMemoryObject p,
00914                       pMortalList pMortal
00915   ){
00916 /*noverbatim
00917 Note that care should be taken to be sure that the variable is NOT on a mortal
00918 list. If the variable is already on a mortal list calling this function will
00919 break the original list and therefore may loose the variables that follow this one.
00920 CUT*/
00921 
00922   p->next = *pMortal;
00923   if( p->next )
00924     p->next->link.prev = p;
00925   p->link.prev = NULL;
00926   p->State = STATE_MORTAL;
00927   *pMortal = p;
00928   return;
00929   }
00930 
00931 /*POD
00932 =H memory_Immortalize()
00933 
00934 Use this function to immortalize a variable. This can be used when the result of an expression
00935 evaluation gets into a mortal variable and instead of copiing the value from the mortal variable to
00936 an immortal variable the caller can immortalize the variable. However it should know which mortal list
00937 the variable is on.
00938 
00939 /*FUNCTION*/
00940 void memory_Immortalize(pFixSizeMemoryObject p,
00941                         pMortalList pMortal
00942   ){
00943 /*noverbatim
00944 CUT*/
00945   if( ! p )return;/* the code tries to immortalize undef at several location, therefore it is better
00946                      to handle this situation here. */
00947   if( p->State == STATE_IMMORTAL )return;
00948   if( p->link.prev )
00949     p->link.prev->next = p->next;
00950   else
00951     *pMortal = p->next;
00952 
00953   if( p->next )
00954     p->next->link.prev = p->link.prev;
00955 
00956   p->link.prev = NULL;
00957   p->next = NULL;
00958   p->State = STATE_IMMORTAL;
00959   return;
00960   }
00961 
00962 /*POD
00963 =H memory_NewMortal()
00964 
00965 When an expression is evaluated mortal variables are needed to store
00966 the intermediate results. These variables are called mortal variables.
00967 Such a variable is is allocated using this function and specifying a
00968 variable of type T<MortalList> to assign the mortal to the list of
00969 mortal variables.
00970 
00971 When the expression is evaluated all mortal variables are to be released
00972 and they are calling the function T<memory_ReleaseMortals> (see R<memory_ReleaseMortals()>).
00973 /*FUNCTION*/
00974 pFixSizeMemoryObject memory_NewMortal(pMemoryObject pMo,
00975                                       BYTE type,
00976                                       unsigned long LargeBlockSize,
00977                                       pMortalList pMortal
00978   ){
00979 /*noverbatim
00980 If the parameter T<pMortal> is T<NULL> the generated variable is not mortal.
00981 CUT*/
00982   pFixSizeMemoryObject p;
00983 
00984   p = memory_NewVariable(pMo,type,LargeBlockSize);
00985   if( p == NULL )return NULL;
00986   if( pMortal )
00987     memory_Mortalize(p,pMortal);
00988   return p;
00989   }
00990 
00991 
00992 /*POD
00993 =H memory_DupImmortal()
00994 
00995 This function creates a new mortal and copies the argument T<pVar> into this
00996 new mortal.
00997 
00998 /*FUNCTION*/
00999 pFixSizeMemoryObject memory_DupImmortal(pMemoryObject pMo,
01000                                         pFixSizeMemoryObject pVar,
01001                                         int *piErrorCode
01002   ){
01003 /*noverbatim
01004 CUT*/
01005   pFixSizeMemoryObject mypVar ;
01006   int i;
01007 
01008   *piErrorCode = MEM_ERROR_SUCCESS;
01009   if( pVar == NULL )return NULL;
01010 
01011   mypVar = memory_NewVariable(pMo,pVar->sType,pVar->Size);
01012   if( mypVar == NULL ){
01013     *piErrorCode = MEM_ERROR_MEMORY_LOW;
01014     return NULL;
01015     }
01016 
01017   mypVar->vType = pVar->vType;
01018   mypVar->Size  = pVar->Size;
01019   if( mypVar->vType == VTYPE_ARRAY ){
01020     mypVar->ArrayHighLimit = pVar->ArrayHighLimit;
01021     mypVar->ArrayLowLimit = pVar->ArrayLowLimit;
01022     for( i = 0 ; i <= mypVar->ArrayHighLimit - mypVar-> ArrayLowLimit ; i++ ){
01023       mypVar->Value.aValue[i] = memory_DupImmortal(pMo,pVar->Value.aValue[i],piErrorCode);
01024       if( *piErrorCode )return NULL;
01025       }
01026     }else{
01027     if( pVar->sType == LARGE_BLOCK_TYPE ){
01028       if( pVar->Size )
01029         memcpy(mypVar->Value.pValue, pVar->Value.pValue, mypVar->Size);
01030       }else{
01031       if( pVar->vType == VTYPE_STRING && pVar->sType != FIX_TYPE_CSTRING ){
01032         if( pVar->Size )
01033           memcpy(mypVar->Value.pValue,pVar->Value.pValue,mypVar->Size);
01034         }else{
01035         mypVar->Value = pVar->Value;
01036         }
01037       }
01038     }
01039   return mypVar;
01040   }
01041 
01042 /*POD
01043 =H memory_DupVar()
01044 
01045 This function creates a new mortal and copies the argument T<pVar> into this
01046 new mortal.
01047 
01048 /*FUNCTION*/
01049 pFixSizeMemoryObject memory_DupVar(pMemoryObject pMo,
01050                                    pFixSizeMemoryObject pVar,
01051                                    pMortalList pMyMortal,
01052                                    int *piErrorCode
01053   ){
01054 /*noverbatim
01055 This function is vital, when used in operations that convert the
01056 values to T<long> or T<double>. Expression evaluation may return an immortal
01057 value, when the expression is a simple variable access. Conversion of the
01058 result would modify the value of the variable itself. Therefore functions and
01059 operators call this function to duplicate the result to be sure that the value
01060 they convert is mortal and to be sure they do not change the value of a variable
01061 when they are not supposed to.
01062 
01063 Note that you can duplicate T<long>, T<double> and T<string> values, but you can not
01064 duplicate arrays! The string value is duplicated and the characters are copied to
01065 the new location. This is perfect. However if you do the same with an array the array
01066 pointers will point to the same variables, which are not going to be duplicated. This
01067 result multiple reference to a single value. This situation is currently not supported
01068 by this system as we do not have either garbage collection or any other solution to support
01069 such memory structures.
01070 CUT*/
01071   pFixSizeMemoryObject mypVar ;
01072 
01073   *piErrorCode = MEM_ERROR_SUCCESS;
01074   if( pVar == NULL )return NULL;
01075 
01076   if( pVar->vType == VTYPE_ARRAY ){
01077     *piErrorCode = MEM_ERROR_INTERNAL001;
01078     return NULL;
01079     }
01080 
01081   mypVar = memory_NewMortal(pMo,pVar->sType,pVar->Size,pMyMortal);
01082   if( mypVar == NULL ){
01083     *piErrorCode = MEM_ERROR_MEMORY_LOW;
01084     return NULL;
01085     }
01086 
01087   mypVar->vType = pVar->vType;
01088   mypVar->Size  = pVar->Size;
01089   if( pVar->sType == LARGE_BLOCK_TYPE ){
01090     if( pVar->Size )
01091       memcpy(mypVar->Value.pValue, pVar->Value.pValue, mypVar->Size);
01092     }else{
01093     if( pVar->vType == VTYPE_STRING && pVar->sType != FIX_TYPE_CSTRING ){
01094       if( pVar->Size )
01095         memcpy(mypVar->Value.pValue,pVar->Value.pValue,mypVar->Size);
01096       }else{
01097       memcpy(&(mypVar->Value),&(pVar->Value),sizeof(union _fsmoval));
01098       }
01099     }
01100   return mypVar;
01101   }
01102 
01103 /*POD
01104 =H memory_DupMortalize()
01105 
01106 This function creates a new mortal and copies the argument T<pVar> into this
01107 new mortal only if the value is immortal. If the value is mortal the it returns
01108 the original value.
01109 
01110 /*FUNCTION*/
01111 pFixSizeMemoryObject memory_DupMortalize(pMemoryObject pMo,
01112                                          pFixSizeMemoryObject pVar,
01113                                          pMortalList pMyMortal,
01114                                          int *piErrorCode
01115   ){
01116 /*noverbatim
01117 CUT*/
01118 
01119   if( *piErrorCode )return NULL;/* if it was called after an erroneous evaluate then do not reset the error code. */
01120   if( pVar && IsMortal(pVar) )return pVar;
01121   return memory_DupVar(pMo,pVar,pMyMortal,piErrorCode);
01122   }
01123 
01124 /*POD
01125 =H memory_ReleaseMortals()
01126 
01127 This function should be used to release the mortal variables.
01128 
01129 When an expression is evaluated mortal variables are needed to store
01130 the intermediate results. These variables are called mortal variables.
01131 Such a variable is is allocated using this function and specifying a
01132 variable of type T<MortalList> to assign the mortal to the list of
01133 mortal variables.
01134 
01135 /*FUNCTION*/
01136 void memory_ReleaseMortals(pMemoryObject pMo,
01137                            pMortalList pMortal
01138   ){
01139 /*noverbatim
01140 CUT*/
01141   MortalList p;
01142 
01143   if( pMortal == NULL )return; /* this is to help lasy callers */
01144   while( p=*pMortal ){
01145     *pMortal = p->next;
01146     memory_ReleaseVariable(pMo,p);
01147     }
01148   *pMortal = NULL;
01149   }
01150 
01151 #ifdef _DEBUG
01152 /*POD
01153 =H memory_DebugDumpVariable()
01154 
01155 This function is used for debugging purposes. (To debug ScriptBasic and not
01156 to debug a BASIC program using ScriptBasic. T<:-o> )
01157 
01158 The function prints the content of a variable to the standard output.
01159 
01160 /*FUNCTION*/
01161 void memory_DebugDumpVariable(pMemoryObject pMo,
01162                               pFixSizeMemoryObject pVar
01163   ){
01164 /*noverbatim
01165 CUT*/
01166   long i;
01167 
01168   if( pVar == NULL ){
01169     printf("real undef");
01170     return;
01171     }
01172 
01173   switch( pVar->vType ){
01174     case VTYPE_UNDEF:
01175       printf("ref undef");
01176       return;
01177 
01178     case VTYPE_STRING:
01179       printf("string(%d)[",STRLEN(pVar));
01180       for( i=0 ;  ((unsigned long)i) < STRLEN(pVar) ; i++ ){
01181         printf("%c",STRINGVALUE(pVar)[i]);
01182         }
01183       printf("]");
01184       return;
01185 
01186     case VTYPE_LONG:
01187       printf("long[%d]",LONGVALUE(pVar));
01188       return;
01189 
01190     case VTYPE_DOUBLE:
01191       printf("long[%f]",DOUBLEVALUE(pVar));
01192       return;
01193 
01194     case VTYPE_ARRAY:
01195       printf("ARRAY(%d,%d)\n[",pVar->ArrayLowLimit, pVar->ArrayHighLimit);
01196       for( i=pVar->ArrayLowLimit ; i <= pVar->ArrayHighLimit  ; i++ ){
01197         memory_DebugDumpVariable(pMo,pVar->Value.aValue[i-pVar->ArrayLowLimit]);
01198         }
01199       printf(" ]");
01200       return;
01201 
01202     case VTYPE_REF:
01203       printf("->");
01204       memory_DebugDumpVariable(pMo,*(pVar->Value.aValue));
01205       return;
01206     }
01207 
01208   }
01209 
01210 /*POD
01211 =H memory_DebugDumpMortals()
01212 
01213 This function is used for debugging purposes. (To debug ScriptBasic and not
01214 to debug a BASIC program using ScriptBasic. T<:-o> )
01215 
01216 The function prints the content of the mortal list to the standard output.
01217 
01218 /*FUNCTION*/
01219 void memory_DebugDumpMortals(pMemoryObject pMo,
01220                              pMortalList pMortal
01221   ){
01222 /*noverbatim
01223 CUT*/
01224   MortalList p,q;
01225   long i;
01226 
01227   if( pMortal == NULL ){
01228     printf("This mortal list is empty\n");
01229     return; /* this is to help lasy callers */
01230     }
01231 
01232   printf("Mortal list %p:\n",pMortal);
01233   i = 1;
01234   q = *pMortal;
01235   while( p = q ){
01236     q = p->next;
01237     printf("%d. ",i++);
01238     memory_DebugDumpVariable(pMo,p);
01239     printf("\n");
01240     }
01241   }
01242 #endif
01243 
01244 /*POD
01245 =H memory_NewMortalString()
01246 
01247 /*FUNCTION*/
01248 pFixSizeMemoryObject memory_NewMortalString(pMemoryObject pMo,
01249                                             unsigned long StringSize,
01250                                             pMortalList pMortal
01251   ){
01252 /*noverbatim
01253 If the parameter T<pMortal> is T<NULL> the generated variable is not mortal.
01254 CUT*/
01255   pFixSizeMemoryObject p;
01256 
01257   p = memory_NewString(pMo,StringSize);
01258   if( p == NULL )return NULL;
01259   if( pMortal )
01260     memory_Mortalize(p,pMortal);
01261   return p;
01262   }
01263 
01264 /*POD
01265 =H memory_NewMortalCString()
01266 
01267 /*FUNCTION*/
01268 pFixSizeMemoryObject memory_NewMortalCString(pMemoryObject pMo,
01269                                              unsigned long StringSize,
01270                                              pMortalList pMortal
01271   ){
01272 /*noverbatim
01273 If the parameter T<pMortal> is T<NULL> the generated variable is not mortal.
01274 CUT*/
01275   pFixSizeMemoryObject p;
01276 
01277   p = memory_NewCString(pMo,StringSize);
01278   if( p == NULL )return NULL;
01279   if( pMortal )
01280     memory_Mortalize(p,pMortal);
01281   return p;
01282   }
01283 
01284 /*POD
01285 =H memory_NewMortalLong()
01286 
01287 /*FUNCTION*/
01288 pFixSizeMemoryObject memory_NewMortalLong(pMemoryObject pMo,
01289                                             pMortalList pMortal
01290   ){
01291 /*noverbatim
01292 If the parameter T<pMortal> is T<NULL> the generated variable is not mortal.
01293 CUT*/
01294   pFixSizeMemoryObject p;
01295 
01296   p = memory_NewLong(pMo);
01297   if( p == NULL )return NULL;
01298   if( pMortal )
01299     memory_Mortalize(p,pMortal);
01300   return p;
01301   }
01302 
01303 /*POD
01304 =H memory_NewMortalRef()
01305 
01306 This function was never used. It was presented in the code to allow external modules to
01307 create mortal reference variables. However later I found that the variable structure design does
01308 not allow mortal reference variables and thus this function is nonsense.
01309 
01310 Not to change the module interface defintion the function still exists but returns NULL, like if
01311 memory were exhausted.
01312 
01313 /*FUNCTION*/
01314 pFixSizeMemoryObject memory_NewMortalRef(pMemoryObject pMo,
01315                                          pMortalList pMortal
01316   ){
01317 /*noverbatim
01318 If the parameter T<pMortal> is T<NULL> the generated variable is not mortal.
01319 CUT*/
01320 
01321   /* just in case somebody uses this function to get immortal refs */
01322   if( pMortal == NULL )return memory_NewRef(pMo);
01323   return NULL;
01324 #if 0
01325   /* see the documentation above why this is commented out */
01326   pFixSizeMemoryObject p;
01327   p = memory_NewRef(pMo);
01328   if( p == NULL )return NULL;
01329   if( pMortal )
01330     memory_Mortalize(p,pMortal);
01331   return p;
01332 #endif
01333   }
01334 
01335 
01336 /*POD
01337 =H memory_NewMortalDouble()
01338 
01339 /*FUNCTION*/
01340 pFixSizeMemoryObject memory_NewMortalDouble(pMemoryObject pMo,
01341                                             pMortalList pMortal
01342   ){
01343 /*noverbatim
01344 If the parameter T<pMortal> is T<NULL> the generated variable is not mortal.
01345 CUT*/
01346   pFixSizeMemoryObject p;
01347 
01348   p = memory_NewDouble(pMo);
01349   if( p == NULL )return NULL;
01350   if( pMortal )
01351     memory_Mortalize(p,pMortal);
01352   return p;
01353   }
01354 
01355 
01356 /*POD
01357 =H memory_NewMortalArray()
01358 
01359 /*FUNCTION*/
01360 pFixSizeMemoryObject memory_NewMortalArray(pMemoryObject pMo,
01361                                            pMortalList pMortal,
01362                                            long IndexLow,
01363                                            long IndexHigh
01364   ){
01365 /*noverbatim
01366 If the parameter T<pMortal> is T<NULL> the generated variable is not mortal.
01367 CUT*/
01368   pFixSizeMemoryObject p;
01369 
01370   p = memory_NewArray(pMo,IndexLow,IndexHigh);
01371   if( p == NULL )return NULL;
01372   if( pMortal )
01373     memory_Mortalize(p,pMortal);
01374   return p;
01375   }

Generated on Sun Mar 12 23:56:31 2006 for ScriptBasic by  doxygen 1.4.6-NO