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