1 /*
2  * malloc.c --
3  *
4  * Memory allocator.
5  *   Magic no longer contains its own version of malloc(), as all modern
6  *   operating systems have implementations which are as good or better.
7  *
8  *   The main thing this file does is to define mallocMagic and friends.
9  *   freeMagic frees the previously requested memory item, not the one
10  *   passed as the argument.  This allows efficient coding of loops which
11  *   run through linked lists and process and free them at the same time.
12  *
13  *   ALWAYS use mallocMagic() with freeMagic() and NEVER mix them with
14  *   malloc() and free().
15  *
16  *   Malloc trace routines have been removed.  There are standard methods
17  *   to trace memory allocation and magic doesn't need its own built-in
18  *   method.
19  *
20  *   The Tcl/Tk version of magic makes use of Tcl_Alloc() and Tcl_Free()
21  *   which allows the Tcl/Tk version to trace memory using Tcl's methods.
22  *
23  *     *********************************************************************
24  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
25  *     * Permission to use, copy, modify, and distribute this              *
26  *     * software and its documentation for any purpose and without        *
27  *     * fee is hereby granted, provided that the above copyright          *
28  *     * notice appear in all copies.  The University of California        *
29  *     * makes no representations about the suitability of this            *
30  *     * software for any purpose.  It is provided "as is" without         *
31  *     * express or implied warranty.  Export of this software outside     *
32  *     * of the United States of America may require an export license.    *
33  *     *********************************************************************
34  */
35 
36 #ifndef lint
37 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/malloc.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
38 #endif  /* not lint */
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <string.h>
44 
45 #include "tcltk/tclmagic.h"
46 #include "utils/magic.h"
47 #include "utils/malloc.h"
48 
49 /* Normally we're supposed to warn against the use of standard malloc()	*/
50 /* and free(), but obviously that doesn't apply to this file.		*/
51 
52 #undef malloc
53 #undef free
54 
55 /* Imports */
56 
57 extern void TxError();
58 extern char *TxGetLine();
59 
60 /*
61  * Magic may reference an object after it is free'ed, but only one object.
62  * This is a change from previous versions of Magic, which needed to reference
63  * an arbitrary number of objects before the next call to malloc.  Only then
64  * would no further references would be made to free'ed storage.
65  */
66 
67 /* Delay free'ing by one call, to accommodate Magic's needs. */
68 static char *freeDelayedItem = NULL;
69 
70 /* Local definitions */
71 
72 #ifdef MAGIC_WRAPPER
73 #ifdef TCL_MEM_DEBUG
74 #define MallocRoutine(a) ckalloc(a)
75 #define FreeRoutine(a) ckfree(a)
76 #else
77 /* DO NOT USE:  Tcl_Alloc is defined with argument (unsigned int) NOT
78  * (size_t) and therefore limits memory allocation to the size of a
79  * 32-bit integer.  Just use the normal malloc() and free().  Left as-is
80  * with TCL_MEM_DEBUG with the caveat that one should not use this to
81  * debug a huge design.  Valgrind works better anyway.
82  */
83 /* #define MallocRoutine(a) Tcl_Alloc(a) */
84 /* #define FreeRoutine(a) Tcl_Free(a) */
85 #define MallocRoutine(a) malloc(a)
86 #define FreeRoutine(a) free(a)
87 #endif
88 #else
89 #define MallocRoutine(a) malloc(a)
90 #define FreeRoutine(a) free(a)
91 #endif
92 
93 /*
94  *---------------------------------------------------------------------
95  * mallocMagic() --
96  *
97  *	memory allocator with support for one-delayed-item free'ing
98  *---------------------------------------------------------------------
99  */
100 
101 void *
mallocMagic(nbytes)102 mallocMagic(nbytes)
103     size_t nbytes;
104 {
105     void *p;
106 
107     if (freeDelayedItem)
108     {
109 	/* fprintf(stderr, "freed 0x%x (delayed)\n", freeDelayedItem); fflush(stderr); */
110 
111 	FreeRoutine(freeDelayedItem);
112 	freeDelayedItem=NULL;
113     }
114 
115     if ((p = (void *)MallocRoutine(nbytes)) != NULL)
116     {
117 	/* fprintf(stderr, "alloc'd %u bytes at 0x%x\n", nbytes, p); fflush(stderr); */
118 
119 	return p;
120     }
121     else
122     {
123 	ASSERT(FALSE, "Can't allocate any more memory.\n");
124     }
125     return NULL;
126 }
127 
128 /*
129  *---------------------------------------------------------------------
130  * freeMagic() --
131  *
132  *	one-delayed-item memory deallocation
133  *---------------------------------------------------------------------
134  */
135 
136 void
freeMagic(cp)137 freeMagic(cp)
138     void *cp;
139 {
140     if (cp == NULL)
141 	TxError("freeMagic called with NULL argument.\n");
142     if (freeDelayedItem)
143     {
144 	/* fprintf(stderr, "freed 0x%x\n", freeDelayedItem); fflush(stderr); */
145 
146 	FreeRoutine(freeDelayedItem);
147     }
148     freeDelayedItem=cp;
149 }
150 
151 /*
152  *---------------------------------------------------------------------
153  * callocMagic() --
154  *
155  *	allocate memory and initialize it to all zero bytes.
156  *---------------------------------------------------------------------
157  */
158 
159 void *
callocMagic(nbytes)160 callocMagic(nbytes)
161     size_t nbytes;
162 {
163     void *cp;
164 
165     cp = mallocMagic(nbytes);
166     bzero(cp, (size_t) nbytes);
167 
168     return (cp);
169 }
170 
171