summaryrefslogtreecommitdiff
path: root/src/z-virt.c
blob: c92771668aec46200da7c5ca9aad38360c66408d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/* File: z-virt.c */

/*
 * Copyright (c) 1997 Ben Harrison
 *
 * This software may be copied and distributed for educational, research,
 * and not for profit purposes provided that this copyright and statement
 * are included in all such copies.
 */

/* Purpose: Memory management routines -BEN- */

#include "z-virt.h"

#include "z-util.h"


/*
 * Allow debugging messages to track memory usage.
 */
#ifdef VERBOSE_RALLOC
static long virt_make = 0;
static long virt_kill = 0;
static long virt_size = 0;
#endif


/*
 * Optional auxiliary "rnfree" function
 */
vptr (*rnfree_aux)(vptr, huge) = NULL;

/*
 * Free some memory (allocated by ralloc), return NULL
 */
vptr rnfree(vptr p, huge len)
{
	/* Easy to free zero bytes */
	if (len == 0) return (NULL);

#ifdef VERBOSE_RALLOC

	/* Decrease memory count */
	virt_kill += len;

	/* Message */
	if (len > virt_size)
	{
		char buf[80];
		sprintf(buf, "Kill (%ld): %ld - %ld = %ld.",
		        len, virt_make, virt_kill, virt_make - virt_kill);
		plog(buf);
	}

#endif

	/* Use the "aux" function */
	if (rnfree_aux) return ((*rnfree_aux)(p, len));

	/* Use "free" */
	free ((char*)(p));

	/* Done */
	return (NULL);
}


/*
 * Optional auxiliary "rpanic" function
 */
vptr (*rpanic_aux)(huge) = NULL;

/*
 * The system is out of memory, so panic.  If "rpanic_aux" is set,
 * it can be used to free up some memory and do a new "ralloc()",
 * or if not, it can be used to save things, clean up, and exit.
 * By default, this function simply crashes the computer.
 */
vptr rpanic(huge len)
{
	/* Hopefully, we have a real "panic" function */
	if (rpanic_aux) return ((*rpanic_aux)(len));

	/* Attempt to crash before icky things happen */
	core("Out of Memory!");

	/* Paranoia */
	return ((vptr)(NULL));
}


/*
 * Optional auxiliary "ralloc" function
 */
vptr (*ralloc_aux)(huge) = NULL;


/*
 * Allocate some memory
 */
vptr ralloc(huge len)
{
	vptr mem;

	/* Allow allocation of "zero bytes" */
	if (len == 0) return ((vptr)(NULL));

#ifdef VERBOSE_RALLOC

	/* Count allocated memory */
	virt_make += len;

	/* Log important allocations */
	if (len > virt_size)
	{
		char buf[80];
		sprintf(buf, "Make (%ld): %ld - %ld = %ld.",
		        len, virt_make, virt_kill, virt_make - virt_kill);
		plog(buf);
	}

#endif

	/* Use the aux function if set */
	if (ralloc_aux) mem = (*ralloc_aux)(len);

	/* Use malloc() to allocate some memory */
	else mem = ((vptr)(malloc((size_t)(len))));

	/* We were able to acquire memory */
	if (!mem) mem = rpanic(len);

	/* Return the memory, if any */
	return (mem);
}




/*
 * Allocate a constant string, containing the same thing as 'str'
 */
cptr string_make(cptr str)
{
	huge len = 0;
	cptr t = str;
	char *s, *res;

	/* Simple sillyness */
	if (!str) return (str);

	/* Get the number of chars in the string, including terminator */
	while (str[len++]) /* loop */;

	/* Allocate space for the string */
	s = res = (char*)(ralloc(len));

	/* Copy the string (with terminator) */
	while ((*s++ = *t++) != 0) /* loop */;

	/* Return the allocated, initialized, string */
	return (res);
}


/*
 * Un-allocate a string allocated above.
 * Depends on no changes being made to the string.
 */
errr string_free(cptr str)
{
	huge len = 0;

	/* Succeed on non-strings */
	if (!str) return (0);

	/* Count the number of chars in 'str' plus the terminator */
	while (str[len++]) /* loop */;

	/* Kill the buffer of chars we must have allocated above */
	rnfree((vptr)(str), len);

	/* Success */
	return (0);
}