830e037ae85482e57b155188bf2a81cadec6ce69
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 -------------------------------------------------*/