Imported from ../lua-3.2.tar.gz.
[lua.git] / src / lmem.c
blob5f840b005aba8b3324e5c51dccd919fda4890d7b
1 /*
2 ** $Id: lmem.c,v 1.17 1999/05/24 17:51:05 roberto Exp $
3 ** Interface to Memory Manager
4 ** See Copyright Notice in lua.h
5 */
8 #include <stdlib.h>
10 #include "lmem.h"
11 #include "lstate.h"
12 #include "lua.h"
16 ** real ANSI systems do not need these tests;
17 ** but some systems (Sun OS) are not that ANSI...
19 #ifdef OLD_ANSI
20 #define realloc(b,s) ((b) == NULL ? malloc(s) : (realloc)(b, s))
21 #define free(b) if (b) (free)(b)
22 #endif
25 #define MINSIZE 8 /* minimum size for "growing" vectors */
30 static unsigned long power2 (unsigned long n) {
31 unsigned long p = MINSIZE;
32 while (p<=n) p<<=1;
33 return p;
37 void *luaM_growaux (void *block, unsigned long nelems, int inc, int size,
38 char *errormsg, unsigned long limit) {
39 unsigned long newn = nelems+inc;
40 if (newn >= limit) lua_error(errormsg);
41 if ((newn ^ nelems) <= nelems || /* still the same power of 2 limit? */
42 (nelems > 0 && newn < MINSIZE)) /* or block already is MINSIZE? */
43 return block; /* do not need to reallocate */
44 else /* it crossed a power of 2 boundary; grow to next power */
45 return luaM_realloc(block, power2(newn)*size);
49 #ifndef DEBUG
52 ** generic allocation routine.
54 void *luaM_realloc (void *block, unsigned long size) {
55 size_t s = (size_t)size;
56 if (s != size)
57 lua_error("memory allocation error: block too big");
58 if (size == 0) {
59 free(block); /* block may be NULL, that is OK for free */
60 return NULL;
62 block = realloc(block, s);
63 if (block == NULL)
64 lua_error(memEM);
65 return block;
70 #else
71 /* DEBUG */
73 #include <string.h>
76 #define HEADER (sizeof(double))
77 #define MARKSIZE 16
79 #define MARK 55
82 #define blocksize(b) ((unsigned long *)((char *)(b) - HEADER))
84 unsigned long numblocks = 0;
85 unsigned long totalmem = 0;
88 static void *checkblock (void *block) {
89 if (block == NULL)
90 return NULL;
91 else {
92 unsigned long *b = blocksize(block);
93 unsigned long size = *b;
94 int i;
95 for (i=0;i<MARKSIZE;i++)
96 LUA_ASSERT(*(((char *)b)+HEADER+size+i) == MARK+i, "corrupted block");
97 numblocks--;
98 totalmem -= size;
99 return b;
104 static void freeblock (void *block) {
105 if (block)
106 memset(block, -1, *blocksize(block)); /* erase block */
107 free(checkblock(block));
111 void *luaM_realloc (void *block, unsigned long size) {
112 unsigned long realsize = HEADER+size+MARKSIZE;
113 if (realsize != (size_t)realsize)
114 lua_error("memory allocation error: block too big");
115 if (size == 0) {
116 freeblock(block);
117 return NULL;
119 else {
120 char *newblock = malloc(realsize);
121 int i;
122 if (block) {
123 unsigned long oldsize = *blocksize(block);
124 if (oldsize > size) oldsize = size;
125 memcpy(newblock+HEADER, block, oldsize);
126 freeblock(block); /* erase (and check) old copy */
128 if (newblock == NULL)
129 lua_error(memEM);
130 totalmem += size;
131 numblocks++;
132 *(unsigned long *)newblock = size;
133 for (i=0;i<MARKSIZE;i++)
134 *(newblock+HEADER+size+i) = MARK+i;
135 return newblock+HEADER;
140 #endif