3 * $Id: utils.c,v 1.6 1998/01/12 16:46:47 mdw Exp $
5 * Miscellaneous useful bits of code.
7 * (c) 1998 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.6 1998/01/12 16:46:47 mdw
35 * Revision 1.5 1997/09/17 10:24:47 mdw
36 * Flush output before and after writing memory tracking information.
38 * Revision 1.4 1997/09/08 13:43:54 mdw
39 * Flush tracedump file after each `interesting' write.
41 * Revision 1.3 1997/08/20 16:25:37 mdw
42 * Add some simple `malloc' tracking.
44 * Revision 1.2 1997/08/04 10:24:26 mdw
45 * Sources placed under CVS control.
47 * Revision 1.1 1997/07/21 13:47:42 mdw
52 /*----- Header files ------------------------------------------------------*/
54 /* --- ANSI headers --- */
62 /* --- Local headers --- */
67 /*----- Program name handling ---------------------------------------------*/
69 /* --- Static data --- */
71 static const char *myname = 0; /* What's my name? */
77 * Returns: Pointer to the program name.
79 * Use: Returns the program name.
82 const char *quis(void)
89 * Arguments: @const char *p@ = pointer to program name
93 * Use: Tells the utils library what the program's name is.
97 # if defined(__riscos)
99 # elif defined(__unix) || defined(unix)
102 # define PATHSEP '\\'
106 void ego(const char *p)
116 /*----- Error reporting ---------------------------------------------------*/
120 * Arguments: @const char *f@ = a @printf@-style format string
121 * @...@ = other arguments
125 * Use: Reports an error.
128 void moan(const char *f, ...)
132 fprintf(stderr, "%s: ", myname);
133 vfprintf(stderr, f, ap);
140 * Arguments: @const char *f@ = a @printf@-style format string
141 * @...@ = other arguments
145 * Use: Reports an error and hari-kiris. Like @moan@ above, only
149 void die(const char *f, ...)
153 fprintf(stderr, "%s: ", myname);
154 vfprintf(stderr, f, ap);
160 /*----- Trace messages ----------------------------------------------------*/
162 #if defined(TRACING) || !defined(NDEBUG)
164 /* --- Static data --- */
166 static FILE *tracefp = 0; /* Where does debugging go? */
167 static unsigned int tracelvl = 0; /* How much tracing gets done? */
171 * Arguments: @unsigned int lvl@ = trace level for output
172 * @const char *f@ = a @printf@-style format string
173 * @...@ = other arguments
177 * Use: Reports a message to the trace output.
180 void trace(unsigned int lvl, const char *f, ...)
183 if ((lvl & tracing()) == 0)
186 fprintf(tracefp, "*** %s: ", myname);
187 vfprintf(tracefp, f, ap);
193 /* --- @traceblk@ --- *
195 * Arguments: @unsigned int lvl@ = trace level for output
196 * @const char *hdr@ = some header string to write
197 * @const void *blk@ = pointer to a block of memory to dump
198 * @size_t sz@ = size of the block of memory
202 * Use: Dumps the contents of a block to the trace output.
205 void traceblk(unsigned int lvl, const char *hdr, const void *blk, size_t sz)
207 const unsigned char *p = blk;
212 /* --- Skip if the trace level is too high --- */
214 if ((lvl & tracing()) == 0)
217 /* --- Now start work --- */
219 fprintf(tracefp, "*** %s: %s\n", myname, hdr);
222 fprintf(tracefp, "*** %s: %08lu : ", myname, o);
223 for (i = 0; i < 8; i++) {
225 fprintf(tracefp, "%02x ", p[i]);
227 fputs("** ", tracefp);
229 fputs(": ", tracefp);
230 for (i = 0; i < 8; i++) {
232 fputc(isprint(p[i]) ? p[i] : '.', tracefp);
236 fputc('\n', tracefp);
237 c = (sz >= 8) ? 8 : sz;
238 sz -= c, p += c, o += c;
243 /* --- @traceon@ --- *
245 * Arguments: @FILE *fp@ = a file to trace on
246 * @unsigned int lvl@ = trace level to set
250 * Use: Enables tracing to a file.
253 void traceon(FILE *fp, unsigned int lvl)
260 /* --- @tracesetlvl@ --- *
262 * Arguments: @unsigned int lvl@ = trace level to set
266 * Use: Sets the tracing level.
269 void tracesetlvl(unsigned int lvl) { tracelvl = lvl; }
271 /* --- @tracing@ --- *
275 * Returns: Zero if not tracing, tracing level if tracing.
277 * Use: Informs the caller whether tracing is enabled.
280 unsigned int tracing(void) { return (tracefp ? tracelvl : 0u); }
284 /*----- Memory management functions ---------------------------------------*/
286 /* --- @xmalloc@ --- *
288 * Arguments: @size_t sz@ = size of block to allocate
290 * Returns: Pointer to allocated block.
292 * Use: Allocates memory. If the memory isn't available, we don't
293 * hang aroung long enough for a normal function return.
296 void *xmalloc(size_t sz)
298 void *p = malloc(sz);
300 die("not enough memory");
304 /* --- @xstrdup@ --- *
306 * Arguments: @const char *s@ = pointer to a string
308 * Returns: Pointer to a copy of the string.
310 * Use: Copies a string (like @strdup@ would, if it existed).
313 char *xstrdup(const char *s)
315 size_t sz = strlen(s) + 1;
316 char *p = xmalloc(sz);
321 /* --- @xrealloc@ --- *
323 * Arguments: @void *p@ = pointer to a block of memory
324 * @size_t sz@ = new size desired for the block
326 * Returns: Pointer to the resized memory block (which is almost
327 * certainly not in the same place any more).
329 * Use: Resizes a memory block.
332 void *xrealloc(void *p, size_t sz)
336 die("not enough memory");
340 /*----- Simple memory use tracking ----------------------------------------*/
344 /*#define TRACK_VERBOSE*/
346 /* --- A type to record a size and have a nice alignment --- */
348 typedef union szblock {
358 /* --- Static data --- */
360 static unsigned int memused = 0;
361 static szblock *memlist;
363 /* --- @track_malloc@ --- *
365 * Arguments: @size_t sz@ = size requested
367 * Returns: Pointer to allocated space, or null
369 * Use: Allocates memory, and tracks how much is allocated.
372 void *track_malloc(size_t sz)
374 szblock *q = (malloc)(sz + sizeof(szblock));
379 printf("[%p] allocated %lu\n", (void *)(q + 1), (unsigned long)sz);
386 q->x.next->x.prev = q;
393 /* --- @track_free@ --- *
395 * Arguments: @void *p@ = pointer to an allocated block
399 * Use: Frees memory, and tracks how much is still allocated.
402 void track_free(void *p)
408 q = (szblock *)p - 1;
411 printf("[%p] freed %lu\n", (void *)(q + 1), (unsigned long)q->x.sz);
415 q->x.next->x.prev = q->x.prev;
417 q->x.prev->x.next = q->x.next;
424 /* --- @track_realloc@ --- *
426 * Arguments: @void *p@ = pointer to an allocated block
427 * @size_t sz@ = how big it wants to be
429 * Returns: Pointer to the new block.
431 * Use: Reallocates a block, tracking how much memory is still
435 void *track_realloc(void *p, size_t sz)
440 q = (szblock *)p - 1;
443 q->x.next->x.prev = q->x.prev;
445 q->x.prev->x.next = q->x.next;
452 qq = (realloc)(q, sz + sizeof(szblock));
456 printf("[%p->%p] reallocated %lu -> %lu\n",
457 (void *)(q + 1), (void *)(qq + 1),
458 (unsigned long)osz, (unsigned long)sz);
462 qq->x.next = memlist;
465 qq->x.next->x.prev = qq;
474 /* --- @track_memused@ --- *
478 * Returns: A count of how much memory is used currently.
480 * Use: Returns the amount of memory which the @track_@-functions
481 * above have counted as being currently allocated.
484 unsigned long track_memused(void)
489 /* --- @track_memlist@ --- *
495 * Use: Dumps a list of allocated blocks to standard output.
498 void track_memlist(void)
500 szblock *q = memlist;
502 printf("listing blocks:\n");
504 printf("... [%p] %lu\n", (void *)(q + 1), (unsigned long)q->x.sz);
513 /*----- That's all, folks -------------------------------------------------*/