3 * $Id: utils.c,v 1.5 1997/09/17 10:24:47 mdw Exp $
5 * Miscellaneous useful bits of code.
7 * (c) 1997 Mark Wooding
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of `become'
14 * `Become' is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * `Become' is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with `become'; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Revision history --------------------------------------------------*
32 * Revision 1.5 1997/09/17 10:24:47 mdw
33 * Flush output before and after writing memory tracking information.
35 * Revision 1.4 1997/09/08 13:43:54 mdw
36 * Flush tracedump file after each `interesting' write.
38 * Revision 1.3 1997/08/20 16:25:37 mdw
39 * Add some simple `malloc' tracking.
41 * Revision 1.2 1997/08/04 10:24:26 mdw
42 * Sources placed under CVS control.
44 * Revision 1.1 1997/07/21 13:47:42 mdw
49 /*----- Header files ------------------------------------------------------*/
51 /* --- ANSI headers --- */
59 /* --- Local headers --- */
64 /*----- Program name handling ---------------------------------------------*/
66 /* --- Static data --- */
68 static const char *myname = 0; /* What's my name? */
74 * Returns: Pointer to the program name.
76 * Use: Returns the program name.
79 const char *quis(void)
86 * Arguments: @const char *p@ = pointer to program name
90 * Use: Tells the utils library what the program's name is.
94 # if defined(__riscos)
96 # elif defined(__unix) || defined(unix)
103 void ego(const char *p)
113 /*----- Error reporting ---------------------------------------------------*/
117 * Arguments: @const char *f@ = a @printf@-style format string
118 * @...@ = other arguments
122 * Use: Reports an error.
125 void moan(const char *f, ...)
129 fprintf(stderr, "%s: ", myname);
130 vfprintf(stderr, f, ap);
137 * Arguments: @const char *f@ = a @printf@-style format string
138 * @...@ = other arguments
142 * Use: Reports an error and hari-kiris. Like @moan@ above, only
146 void die(const char *f, ...)
150 fprintf(stderr, "%s: ", myname);
151 vfprintf(stderr, f, ap);
157 /*----- Trace messages ----------------------------------------------------*/
159 #if defined(TRACING) || !defined(NDEBUG)
161 /* --- Static data --- */
163 static FILE *tracefp = 0; /* Where does debugging go? */
164 static unsigned int tracelvl = 0; /* How much tracing gets done? */
168 * Arguments: @unsigned int lvl@ = trace level for output
169 * @const char *f@ = a @printf@-style format string
170 * @...@ = other arguments
174 * Use: Reports a message to the trace output.
177 void trace(unsigned int lvl, const char *f, ...)
180 if ((lvl & tracing()) == 0)
183 fprintf(tracefp, "*** %s: ", myname);
184 vfprintf(tracefp, f, ap);
190 /* --- @traceblk@ --- *
192 * Arguments: @unsigned int lvl@ = trace level for output
193 * @const char *hdr@ = some header string to write
194 * @const void *blk@ = pointer to a block of memory to dump
195 * @size_t sz@ = size of the block of memory
199 * Use: Dumps the contents of a block to the trace output.
202 void traceblk(unsigned int lvl, const char *hdr, const void *blk, size_t sz)
204 const unsigned char *p = blk;
209 /* --- Skip if the trace level is too high --- */
211 if ((lvl & tracing()) == 0)
214 /* --- Now start work --- */
216 fprintf(tracefp, "*** %s: %s\n", myname, hdr);
219 fprintf(tracefp, "*** %s: %08lu : ", myname, o);
220 for (i = 0; i < 8; i++) {
222 fprintf(tracefp, "%02x ", p[i]);
224 fputs("** ", tracefp);
226 fputs(": ", tracefp);
227 for (i = 0; i < 8; i++) {
229 fputc(isprint(p[i]) ? p[i] : '.', tracefp);
233 fputc('\n', tracefp);
234 c = (sz >= 8) ? 8 : sz;
235 sz -= c, p += c, o += c;
240 /* --- @traceon@ --- *
242 * Arguments: @FILE *fp@ = a file to trace on
243 * @unsigned int lvl@ = trace level to set
247 * Use: Enables tracing to a file.
250 void traceon(FILE *fp, unsigned int lvl)
257 /* --- @tracesetlvl@ --- *
259 * Arguments: @unsigned int lvl@ = trace level to set
263 * Use: Sets the tracing level.
266 void tracesetlvl(unsigned int lvl) { tracelvl = lvl; }
268 /* --- @tracing@ --- *
272 * Returns: Zero if not tracing, tracing level if tracing.
274 * Use: Informs the caller whether tracing is enabled.
277 unsigned int tracing(void) { return (tracefp ? tracelvl : 0u); }
281 /*----- Memory management functions ---------------------------------------*/
283 /* --- @xmalloc@ --- *
285 * Arguments: @size_t sz@ = size of block to allocate
287 * Returns: Pointer to allocated block.
289 * Use: Allocates memory. If the memory isn't available, we don't
290 * hang aroung long enough for a normal function return.
293 void *xmalloc(size_t sz)
295 void *p = malloc(sz);
297 die("not enough memory");
301 /* --- @xstrdup@ --- *
303 * Arguments: @const char *s@ = pointer to a string
305 * Returns: Pointer to a copy of the string.
307 * Use: Copies a string (like @strdup@ would, if it existed).
310 char *xstrdup(const char *s)
312 size_t sz = strlen(s) + 1;
313 char *p = xmalloc(sz);
318 /* --- @xrealloc@ --- *
320 * Arguments: @void *p@ = pointer to a block of memory
321 * @size_t sz@ = new size desired for the block
323 * Returns: Pointer to the resized memory block (which is almost
324 * certainly not in the same place any more).
326 * Use: Resizes a memory block.
329 void *xrealloc(void *p, size_t sz)
333 die("not enough memory");
337 /*----- Simple memory use tracking ----------------------------------------*/
341 /*#define TRACK_VERBOSE*/
343 /* --- A type to record a size and have a nice alignment --- */
345 typedef union szblock {
355 /* --- Static data --- */
357 static unsigned int memused = 0;
358 static szblock *memlist;
360 /* --- @track_malloc@ --- *
362 * Arguments: @size_t sz@ = size requested
364 * Returns: Pointer to allocated space, or null
366 * Use: Allocates memory, and tracks how much is allocated.
369 void *track_malloc(size_t sz)
371 szblock *q = (malloc)(sz + sizeof(szblock));
376 printf("[%p] allocated %lu\n", (void *)(q + 1), (unsigned long)sz);
383 q->x.next->x.prev = q;
390 /* --- @track_free@ --- *
392 * Arguments: @void *p@ = pointer to an allocated block
396 * Use: Frees memory, and tracks how much is still allocated.
399 void track_free(void *p)
405 q = (szblock *)p - 1;
408 printf("[%p] freed %lu\n", (void *)(q + 1), (unsigned long)q->x.sz);
412 q->x.next->x.prev = q->x.prev;
414 q->x.prev->x.next = q->x.next;
421 /* --- @track_realloc@ --- *
423 * Arguments: @void *p@ = pointer to an allocated block
424 * @size_t sz@ = how big it wants to be
426 * Returns: Pointer to the new block.
428 * Use: Reallocates a block, tracking how much memory is still
432 void *track_realloc(void *p, size_t sz)
437 q = (szblock *)p - 1;
440 q->x.next->x.prev = q->x.prev;
442 q->x.prev->x.next = q->x.next;
449 qq = (realloc)(q, sz + sizeof(szblock));
453 printf("[%p->%p] reallocated %lu -> %lu\n",
454 (void *)(q + 1), (void *)(qq + 1),
455 (unsigned long)osz, (unsigned long)sz);
459 qq->x.next = memlist;
462 qq->x.next->x.prev = qq;
471 /* --- @track_memused@ --- *
475 * Returns: A count of how much memory is used currently.
477 * Use: Returns the amount of memory which the @track_@-functions
478 * above have counted as being currently allocated.
481 unsigned long track_memused(void)
486 /* --- @track_memlist@ --- *
492 * Use: Dumps a list of allocated blocks to standard output.
495 void track_memlist(void)
497 szblock *q = memlist;
499 printf("listing blocks:\n");
501 printf("... [%p] %lu\n", (void *)(q + 1), (unsigned long)q->x.sz);
510 /*----- That's all, folks -------------------------------------------------*/