3 * $Id: utils.c,v 1.4 1997/09/08 13:43:54 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.4 1997/09/08 13:43:54 mdw
33 * Flush tracedump file after each `interesting' write.
35 * Revision 1.3 1997/08/20 16:25:37 mdw
36 * Add some simple `malloc' tracking.
38 * Revision 1.2 1997/08/04 10:24:26 mdw
39 * Sources placed under CVS control.
41 * Revision 1.1 1997/07/21 13:47:42 mdw
46 /*----- Header files ------------------------------------------------------*/
48 /* --- ANSI headers --- */
56 /* --- Local headers --- */
61 /*----- Program name handling ---------------------------------------------*/
63 /* --- Static data --- */
65 static const char *myname
= 0; /* What's my name? */
71 * Returns: Pointer to the program name.
73 * Use: Returns the program name.
76 const char *quis(void)
83 * Arguments: @const char *p@ = pointer to program name
87 * Use: Tells the utils library what the program's name is.
91 # if defined(__riscos)
93 # elif defined(__unix) || defined(unix)
100 void ego(const char *p
)
110 /*----- Error reporting ---------------------------------------------------*/
114 * Arguments: @const char *f@ = a @printf@-style format string
115 * @...@ = other arguments
119 * Use: Reports an error.
122 void moan(const char *f
, ...)
126 fprintf(stderr
, "%s: ", myname
);
127 vfprintf(stderr
, f
, ap
);
134 * Arguments: @const char *f@ = a @printf@-style format string
135 * @...@ = other arguments
139 * Use: Reports an error and hari-kiris. Like @moan@ above, only
143 void die(const char *f
, ...)
147 fprintf(stderr
, "%s: ", myname
);
148 vfprintf(stderr
, f
, ap
);
154 /*----- Trace messages ----------------------------------------------------*/
156 #if defined(TRACING) || !defined(NDEBUG)
158 /* --- Static data --- */
160 static FILE *tracefp
= 0; /* Where does debugging go? */
161 static unsigned int tracelvl
= 0; /* How much tracing gets done? */
165 * Arguments: @unsigned int lvl@ = trace level for output
166 * @const char *f@ = a @printf@-style format string
167 * @...@ = other arguments
171 * Use: Reports a message to the trace output.
174 void trace(unsigned int lvl
, const char *f
, ...)
177 if ((lvl
& tracing()) == 0)
180 fprintf(tracefp
, "*** %s: ", myname
);
181 vfprintf(tracefp
, f
, ap
);
187 /* --- @traceblk@ --- *
189 * Arguments: @unsigned int lvl@ = trace level for output
190 * @const char *hdr@ = some header string to write
191 * @const void *blk@ = pointer to a block of memory to dump
192 * @size_t sz@ = size of the block of memory
196 * Use: Dumps the contents of a block to the trace output.
199 void traceblk(unsigned int lvl
, const char *hdr
, const void *blk
, size_t sz
)
201 const unsigned char *p
= blk
;
206 /* --- Skip if the trace level is too high --- */
208 if ((lvl
& tracing()) == 0)
211 /* --- Now start work --- */
213 fprintf(tracefp
, "*** %s: %s\n", myname
, hdr
);
216 fprintf(tracefp
, "*** %s: %08lu : ", myname
, o
);
217 for (i
= 0; i
< 8; i
++) {
219 fprintf(tracefp
, "%02x ", p
[i
]);
221 fputs("** ", tracefp
);
223 fputs(": ", tracefp
);
224 for (i
= 0; i
< 8; i
++) {
226 fputc(isprint(p
[i
]) ? p
[i
] : '.', tracefp
);
230 fputc('\n', tracefp
);
231 c
= (sz
>= 8) ?
8 : sz
;
232 sz
-= c
, p
+= c
, o
+= c
;
237 /* --- @traceon@ --- *
239 * Arguments: @FILE *fp@ = a file to trace on
240 * @unsigned int lvl@ = trace level to set
244 * Use: Enables tracing to a file.
247 void traceon(FILE *fp
, unsigned int lvl
)
254 /* --- @tracesetlvl@ --- *
256 * Arguments: @unsigned int lvl@ = trace level to set
260 * Use: Sets the tracing level.
263 void tracesetlvl(unsigned int lvl
) { tracelvl
= lvl
; }
265 /* --- @tracing@ --- *
269 * Returns: Zero if not tracing, tracing level if tracing.
271 * Use: Informs the caller whether tracing is enabled.
274 unsigned int tracing(void) { return (tracefp ? tracelvl
: 0u); }
278 /*----- Memory management functions ---------------------------------------*/
280 /* --- @xmalloc@ --- *
282 * Arguments: @size_t sz@ = size of block to allocate
284 * Returns: Pointer to allocated block.
286 * Use: Allocates memory. If the memory isn't available, we don't
287 * hang aroung long enough for a normal function return.
290 void *xmalloc(size_t sz
)
292 void *p
= malloc(sz
);
294 die("not enough memory");
298 /* --- @xstrdup@ --- *
300 * Arguments: @const char *s@ = pointer to a string
302 * Returns: Pointer to a copy of the string.
304 * Use: Copies a string (like @strdup@ would, if it existed).
307 char *xstrdup(const char *s
)
309 size_t sz
= strlen(s
) + 1;
310 char *p
= xmalloc(sz
);
315 /* --- @xrealloc@ --- *
317 * Arguments: @void *p@ = pointer to a block of memory
318 * @size_t sz@ = new size desired for the block
320 * Returns: Pointer to the resized memory block (which is almost
321 * certainly not in the same place any more).
323 * Use: Resizes a memory block.
326 void *xrealloc(void *p
, size_t sz
)
330 die("not enough memory");
334 /*----- Simple memory use tracking ----------------------------------------*/
338 /*#define TRACK_VERBOSE*/
340 /* --- A type to record a size and have a nice alignment --- */
342 typedef union szblock
{
352 /* --- Static data --- */
354 static unsigned int memused
= 0;
355 static szblock
*memlist
;
357 /* --- @track_malloc@ --- *
359 * Arguments: @size_t sz@ = size requested
361 * Returns: Pointer to allocated space, or null
363 * Use: Allocates memory, and tracks how much is allocated.
366 void *track_malloc(size_t sz
)
368 szblock
*q
= (malloc
)(sz
+ sizeof(szblock
));
372 printf("[%p] allocated %lu\n", (void *)(q
+ 1), (unsigned long)sz
);
378 q
->x
.next
->x
.prev
= q
;
385 /* --- @track_free@ --- *
387 * Arguments: @void *p@ = pointer to an allocated block
391 * Use: Frees memory, and tracks how much is still allocated.
394 void track_free(void *p
)
400 q
= (szblock
*)p
- 1;
402 printf("[%p] freed %lu\n", (void *)(q
+ 1), (unsigned long)q
->x
.sz
);
405 q
->x
.next
->x
.prev
= q
->x
.prev
;
407 q
->x
.prev
->x
.next
= q
->x
.next
;
414 /* --- @track_realloc@ --- *
416 * Arguments: @void *p@ = pointer to an allocated block
417 * @size_t sz@ = how big it wants to be
419 * Returns: Pointer to the new block.
421 * Use: Reallocates a block, tracking how much memory is still
425 void *track_realloc(void *p
, size_t sz
)
430 q
= (szblock
*)p
- 1;
433 q
->x
.next
->x
.prev
= q
->x
.prev
;
435 q
->x
.prev
->x
.next
= q
->x
.next
;
442 qq
= (realloc
)(q
, sz
+ sizeof(szblock
));
445 printf("[%p->%p] reallocated %lu -> %lu\n",
446 (void *)(q
+ 1), (void *)(qq
+ 1),
447 (unsigned long)osz
, (unsigned long)sz
);
450 qq
->x
.next
= memlist
;
453 qq
->x
.next
->x
.prev
= qq
;
462 /* --- @track_memused@ --- *
466 * Returns: A count of how much memory is used currently.
468 * Use: Returns the amount of memory which the @track_@-functions
469 * above have counted as being currently allocated.
472 unsigned long track_memused(void)
477 /* --- @track_memlist@ --- *
483 * Use: Dumps a list of allocated blocks to standard output.
486 void track_memlist(void)
488 szblock
*q
= memlist
;
489 printf("listing blocks:\n");
491 printf("... [%p] %lu\n", (void *)(q
+ 1), (unsigned long)q
->x
.sz
);
499 /*----- That's all, folks -------------------------------------------------*/