X-Git-Url: https://git.distorted.org.uk/~mdw/become/blobdiff_plain/c4f2d992e4a0fc068281376d89ec38de56dc2f58..c758e6541ca05409b178dd9629e9337494c49890:/src/utils.c diff --git a/src/utils.c b/src/utils.c index a46a310..c6e1313 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: utils.c,v 1.1 1997/07/21 13:47:42 mdw Exp $ + * $Id: utils.c,v 1.6 1998/01/12 16:46:47 mdw Exp $ * * Miscellaneous useful bits of code. * - * (c) 1997 Mark Wooding + * (c) 1998 Mark Wooding */ -/*----- Licencing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of `become' * @@ -22,14 +22,29 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with `become'; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * along with `become'; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*----- Revision history --------------------------------------------------* * * $Log: utils.c,v $ - * Revision 1.1 1997/07/21 13:47:42 mdw + * Revision 1.6 1998/01/12 16:46:47 mdw + * Fix copyright date. + * + * Revision 1.5 1997/09/17 10:24:47 mdw + * Flush output before and after writing memory tracking information. + * + * Revision 1.4 1997/09/08 13:43:54 mdw + * Flush tracedump file after each `interesting' write. + * + * Revision 1.3 1997/08/20 16:25:37 mdw + * Add some simple `malloc' tracking. + * + * Revision 1.2 1997/08/04 10:24:26 mdw + * Sources placed under CVS control. + * + * Revision 1.1 1997/07/21 13:47:42 mdw * Initial revision * */ @@ -38,20 +53,22 @@ /* --- ANSI headers --- */ +#include #include #include #include +#include /* --- Local headers --- */ #include "config.h" #include "utils.h" -/*----- Static data -------------------------------------------------------*/ +/*----- Program name handling ---------------------------------------------*/ -static const char *myname = 0; /* What's my name? */ +/* --- Static data --- */ -/*----- Program name handling ---------------------------------------------*/ +static const char *myname = 0; /* What's my name? */ /* --- @quis@ --- * * @@ -140,6 +157,130 @@ void die(const char *f, ...) exit(EXIT_FAILURE); } +/*----- Trace messages ----------------------------------------------------*/ + +#if defined(TRACING) || !defined(NDEBUG) + +/* --- Static data --- */ + +static FILE *tracefp = 0; /* Where does debugging go? */ +static unsigned int tracelvl = 0; /* How much tracing gets done? */ + +/* --- @trace@ --- * + * + * Arguments: @unsigned int lvl@ = trace level for output + * @const char *f@ = a @printf@-style format string + * @...@ = other arguments + * + * Returns: --- + * + * Use: Reports a message to the trace output. + */ + +void trace(unsigned int lvl, const char *f, ...) +{ + va_list ap; + if ((lvl & tracing()) == 0) + return; + va_start(ap, f); + fprintf(tracefp, "*** %s: ", myname); + vfprintf(tracefp, f, ap); + va_end(ap); + putc('\n', tracefp); + fflush(tracefp); +} + +/* --- @traceblk@ --- * + * + * Arguments: @unsigned int lvl@ = trace level for output + * @const char *hdr@ = some header string to write + * @const void *blk@ = pointer to a block of memory to dump + * @size_t sz@ = size of the block of memory + * + * Returns: --- + * + * Use: Dumps the contents of a block to the trace output. + */ + +void traceblk(unsigned int lvl, const char *hdr, const void *blk, size_t sz) +{ + const unsigned char *p = blk; + size_t i; + unsigned long o = 0; + size_t c; + + /* --- Skip if the trace level is too high --- */ + + if ((lvl & tracing()) == 0) + return; + + /* --- Now start work --- */ + + fprintf(tracefp, "*** %s: %s\n", myname, hdr); + + while (sz) { + fprintf(tracefp, "*** %s: %08lu : ", myname, o); + for (i = 0; i < 8; i++) { + if (i < sz) + fprintf(tracefp, "%02x ", p[i]); + else + fputs("** ", tracefp); + } + fputs(": ", tracefp); + for (i = 0; i < 8; i++) { + if (i < sz) + fputc(isprint(p[i]) ? p[i] : '.', tracefp); + else + fputc('*', tracefp); + } + fputc('\n', tracefp); + c = (sz >= 8) ? 8 : sz; + sz -= c, p += c, o += c; + } + fflush(tracefp); +} + +/* --- @traceon@ --- * + * + * Arguments: @FILE *fp@ = a file to trace on + * @unsigned int lvl@ = trace level to set + * + * Returns: --- + * + * Use: Enables tracing to a file. + */ + +void traceon(FILE *fp, unsigned int lvl) +{ + tracefp = fp; + if (!tracelvl) + tracelvl = lvl; +} + +/* --- @tracesetlvl@ --- * + * + * Arguments: @unsigned int lvl@ = trace level to set + * + * Returns: --- + * + * Use: Sets the tracing level. + */ + +void tracesetlvl(unsigned int lvl) { tracelvl = lvl; } + +/* --- @tracing@ --- * + * + * Arguments: --- + * + * Returns: Zero if not tracing, tracing level if tracing. + * + * Use: Informs the caller whether tracing is enabled. + */ + +unsigned int tracing(void) { return (tracefp ? tracelvl : 0u); } + +#endif + /*----- Memory management functions ---------------------------------------*/ /* --- @xmalloc@ --- * @@ -196,4 +337,177 @@ void *xrealloc(void *p, size_t sz) return (p); } +/*----- Simple memory use tracking ----------------------------------------*/ + +#ifdef TRACK_MALLOC + +/*#define TRACK_VERBOSE*/ + +/* --- A type to record a size and have a nice alignment --- */ + +typedef union szblock { + struct { + union szblock *next; + union szblock *prev; + size_t sz; + } x; + long double _ld; + void *_p; +} szblock; + +/* --- Static data --- */ + +static unsigned int memused = 0; +static szblock *memlist; + +/* --- @track_malloc@ --- * + * + * Arguments: @size_t sz@ = size requested + * + * Returns: Pointer to allocated space, or null + * + * Use: Allocates memory, and tracks how much is allocated. + */ + +void *track_malloc(size_t sz) +{ + szblock *q = (malloc)(sz + sizeof(szblock)); + if (q) { + memused += sz; +#ifdef TRACK_VERBOSE + fflush(0); + printf("[%p] allocated %lu\n", (void *)(q + 1), (unsigned long)sz); + fflush(stdout); +#endif + q->x.sz = sz; + q->x.next = memlist; + q->x.prev = 0; + if (q->x.next) + q->x.next->x.prev = q; + memlist = q; + return (q + 1); + } + return (0); +} + +/* --- @track_free@ --- * + * + * Arguments: @void *p@ = pointer to an allocated block + * + * Returns: --- + * + * Use: Frees memory, and tracks how much is still allocated. + */ + +void track_free(void *p) +{ + szblock *q; + + if (!p) + return; + q = (szblock *)p - 1; +#ifdef TRACK_VERBOSE + fflush(0); + printf("[%p] freed %lu\n", (void *)(q + 1), (unsigned long)q->x.sz); + fflush(stdout); +#endif + if (q->x.next) + q->x.next->x.prev = q->x.prev; + if (q->x.prev) + q->x.prev->x.next = q->x.next; + else + memlist = q->x.next; + memused -= q->x.sz; + (free)(q); +} + +/* --- @track_realloc@ --- * + * + * Arguments: @void *p@ = pointer to an allocated block + * @size_t sz@ = how big it wants to be + * + * Returns: Pointer to the new block. + * + * Use: Reallocates a block, tracking how much memory is still + * available. + */ + +void *track_realloc(void *p, size_t sz) +{ + size_t osz; + szblock *q, *qq; + if (p) { + q = (szblock *)p - 1; + osz = q->x.sz; + if (q->x.next) + q->x.next->x.prev = q->x.prev; + if (q->x.prev) + q->x.prev->x.next = q->x.next; + else + memlist = q->x.next; + } else { + q = 0; + osz = 0; + } + qq = (realloc)(q, sz + sizeof(szblock)); + if (qq) { +#ifdef TRACK_VERBOSE + fflush(0); + printf("[%p->%p] reallocated %lu -> %lu\n", + (void *)(q + 1), (void *)(qq + 1), + (unsigned long)osz, (unsigned long)sz); + fflush(stdout); +#endif + qq->x.sz = sz; + qq->x.next = memlist; + qq->x.prev = 0; + if (qq->x.next) + qq->x.next->x.prev = qq; + memlist = qq; + memused += sz - osz; + qq->x.sz = sz; + return (qq + 1); + } + return (0); +} + +/* --- @track_memused@ --- * + * + * Arguments: --- + * + * Returns: A count of how much memory is used currently. + * + * Use: Returns the amount of memory which the @track_@-functions + * above have counted as being currently allocated. + */ + +unsigned long track_memused(void) +{ + return (memused); +} + +/* --- @track_memlist@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Dumps a list of allocated blocks to standard output. + */ + +void track_memlist(void) +{ + szblock *q = memlist; + fflush(0); + printf("listing blocks:\n"); + while (q) { + printf("... [%p] %lu\n", (void *)(q + 1), (unsigned long)q->x.sz); + q = q->x.next; + } + printf("done\n"); + fflush(stdout); +} + +#endif + /*----- That's all, folks -------------------------------------------------*/