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