3 * $Id: utils.c,v 1.3 1997/08/20 16:25:37 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.3 1997/08/20 16:25:37 mdw
33 * Add some simple `malloc' tracking.
35 * Revision 1.2 1997/08/04 10:24:26 mdw
36 * Sources placed under CVS control.
38 * Revision 1.1 1997/07/21 13:47:42 mdw
43 /*----- Header files ------------------------------------------------------*/
45 /* --- ANSI headers --- */
53 /* --- Local headers --- */
58 /*----- Program name handling ---------------------------------------------*/
60 /* --- Static data --- */
62 static const char *myname = 0; /* What's my name? */
68 * Returns: Pointer to the program name.
70 * Use: Returns the program name.
73 const char *quis(void)
80 * Arguments: @const char *p@ = pointer to program name
84 * Use: Tells the utils library what the program's name is.
88 # if defined(__riscos)
90 # elif defined(__unix) || defined(unix)
97 void ego(const char *p)
107 /*----- Error reporting ---------------------------------------------------*/
111 * Arguments: @const char *f@ = a @printf@-style format string
112 * @...@ = other arguments
116 * Use: Reports an error.
119 void moan(const char *f, ...)
123 fprintf(stderr, "%s: ", myname);
124 vfprintf(stderr, f, ap);
131 * Arguments: @const char *f@ = a @printf@-style format string
132 * @...@ = other arguments
136 * Use: Reports an error and hari-kiris. Like @moan@ above, only
140 void die(const char *f, ...)
144 fprintf(stderr, "%s: ", myname);
145 vfprintf(stderr, f, ap);
151 /*----- Trace messages ----------------------------------------------------*/
153 #if defined(TRACING) || !defined(NDEBUG)
155 /* --- Static data --- */
157 static FILE *tracefp = 0; /* Where does debugging go? */
158 static unsigned int tracelvl = 0; /* How much tracing gets done? */
162 * Arguments: @unsigned int lvl@ = trace level for output
163 * @const char *f@ = a @printf@-style format string
164 * @...@ = other arguments
168 * Use: Reports a message to the trace output.
171 void trace(unsigned int lvl, const char *f, ...)
174 if ((lvl & tracing()) == 0)
177 fprintf(tracefp, "*** %s: ", myname);
178 vfprintf(tracefp, f, ap);
183 /* --- @traceblk@ --- *
185 * Arguments: @unsigned int lvl@ = trace level for output
186 * @const char *hdr@ = some header string to write
187 * @const void *blk@ = pointer to a block of memory to dump
188 * @size_t sz@ = size of the block of memory
192 * Use: Dumps the contents of a block to the trace output.
195 void traceblk(unsigned int lvl, const char *hdr, const void *blk, size_t sz)
197 const unsigned char *p = blk;
202 /* --- Skip if the trace level is too high --- */
204 if ((lvl & tracing()) == 0)
207 /* --- Now start work --- */
209 fprintf(tracefp, "*** %s: %s\n", myname, hdr);
212 fprintf(tracefp, "*** %s: %08lu : ", myname, o);
213 for (i = 0; i < 8; i++) {
215 fprintf(tracefp, "%02x ", p[i]);
217 fputs("** ", tracefp);
219 fputs(": ", tracefp);
220 for (i = 0; i < 8; i++) {
222 fputc(isprint(p[i]) ? p[i] : '.', tracefp);
226 fputc('\n', tracefp);
227 c = (sz >= 8) ? 8 : sz;
228 sz -= c, p += c, o += c;
233 /* --- @traceon@ --- *
235 * Arguments: @FILE *fp@ = a file to trace on
236 * @unsigned int lvl@ = trace level to set
240 * Use: Enables tracing to a file.
243 void traceon(FILE *fp, unsigned int lvl)
250 /* --- @tracesetlvl@ --- *
252 * Arguments: @unsigned int lvl@ = trace level to set
256 * Use: Sets the tracing level.
259 void tracesetlvl(unsigned int lvl) { tracelvl = lvl; }
261 /* --- @tracing@ --- *
265 * Returns: Zero if not tracing, tracing level if tracing.
267 * Use: Informs the caller whether tracing is enabled.
270 unsigned int tracing(void) { return (tracefp ? tracelvl : 0u); }
274 /*----- Memory management functions ---------------------------------------*/
276 /* --- @xmalloc@ --- *
278 * Arguments: @size_t sz@ = size of block to allocate
280 * Returns: Pointer to allocated block.
282 * Use: Allocates memory. If the memory isn't available, we don't
283 * hang aroung long enough for a normal function return.
286 void *xmalloc(size_t sz)
288 void *p = malloc(sz);
290 die("not enough memory");
294 /* --- @xstrdup@ --- *
296 * Arguments: @const char *s@ = pointer to a string
298 * Returns: Pointer to a copy of the string.
300 * Use: Copies a string (like @strdup@ would, if it existed).
303 char *xstrdup(const char *s)
305 size_t sz = strlen(s) + 1;
306 char *p = xmalloc(sz);
311 /* --- @xrealloc@ --- *
313 * Arguments: @void *p@ = pointer to a block of memory
314 * @size_t sz@ = new size desired for the block
316 * Returns: Pointer to the resized memory block (which is almost
317 * certainly not in the same place any more).
319 * Use: Resizes a memory block.
322 void *xrealloc(void *p, size_t sz)
326 die("not enough memory");
330 /*----- Simple memory use tracking ----------------------------------------*/
334 /*#define TRACK_VERBOSE*/
336 /* --- A type to record a size and have a nice alignment --- */
338 typedef union szblock {
348 /* --- Static data --- */
350 static unsigned int memused = 0;
351 static szblock *memlist;
353 /* --- @track_malloc@ --- *
355 * Arguments: @size_t sz@ = size requested
357 * Returns: Pointer to allocated space, or null
359 * Use: Allocates memory, and tracks how much is allocated.
362 void *track_malloc(size_t sz)
364 szblock *q = (malloc)(sz + sizeof(szblock));
368 printf("[%p] allocated %lu\n", (void *)(q + 1), (unsigned long)sz);
374 q->x.next->x.prev = q;
381 /* --- @track_free@ --- *
383 * Arguments: @void *p@ = pointer to an allocated block
387 * Use: Frees memory, and tracks how much is still allocated.
390 void track_free(void *p)
396 q = (szblock *)p - 1;
398 printf("[%p] freed %lu\n", (void *)(q + 1), (unsigned long)q->x.sz);
401 q->x.next->x.prev = q->x.prev;
403 q->x.prev->x.next = q->x.next;
410 /* --- @track_realloc@ --- *
412 * Arguments: @void *p@ = pointer to an allocated block
413 * @size_t sz@ = how big it wants to be
415 * Returns: Pointer to the new block.
417 * Use: Reallocates a block, tracking how much memory is still
421 void *track_realloc(void *p, size_t sz)
426 q = (szblock *)p - 1;
429 q->x.next->x.prev = q->x.prev;
431 q->x.prev->x.next = q->x.next;
438 qq = (realloc)(q, sz + sizeof(szblock));
441 printf("[%p->%p] reallocated %lu -> %lu\n",
442 (void *)(q + 1), (void *)(qq + 1),
443 (unsigned long)osz, (unsigned long)sz);
446 qq->x.next = memlist;
449 qq->x.next->x.prev = qq;
458 /* --- @track_memused@ --- *
462 * Returns: A count of how much memory is used currently.
464 * Use: Returns the amount of memory which the @track_@-functions
465 * above have counted as being currently allocated.
468 unsigned long track_memused(void)
473 /* --- @track_memlist@ --- *
479 * Use: Dumps a list of allocated blocks to standard output.
482 void track_memlist(void)
484 szblock *q = memlist;
485 printf("listing blocks:\n");
487 printf("... [%p] %lu\n", (void *)(q + 1), (unsigned long)q->x.sz);
495 /*----- That's all, folks -------------------------------------------------*/