Heap management A few routines that are more convenient than malloc, free, etc. (at least for my style of programming). The routines (or macros) implement their own error checking: when insufficient space is available, the program is aborted with an error message. Exports [[fatal(char *s)]] prints s on stderr and aborts with a core dump. [[new(p)]] a macro that allocates space and points p to it. The allocated space is enough to hold what p points to (= sizeof(*p)). [[dispose(p)]] deallocates the space that p points to. When p does not point to space that has been allocated on the heap, or when dispose is called twice for the same space, the results are undefined. [[dispose]] may safely be called on a [[NULL]] pointer or on a pointer that has already been disposed (without any effects, of course.) [[newarray(p, unsigned int n)]] allocates space for an array of length n, of the type pointed to by p. [[renewarray(p, unsigned int n)]] allocates space for an array of length n, of the type pointed to by p, and points p to it. When p is not NULL, the previous contents are copied to the new space. If n is 0, the effect is the same as for dispose(p). If n = 1, the effect is the same as for new(p). [[long heapmax(p)]] return the length of the largest array that can at this moment be allocated with newarray(p, n). (I.e., the largest available memory block.) [[char *newstring(char *s)]] allocate space and copy s to it. If s is NULL, the result will also be NULL. [[char *newnstring(char *s, int n)]] allocate space for n characters and copy s to it. If s is NULL, the result will also be NULL. History 30 April 1993: created <<*>>= #include #include #ifndef BSD #include #else #include #endif #include #include #ifdef __export #define FILE / ## *"*/__FI ## LE__/*"* ## / #define LINE / ## *"*/__LI ## NE__/*"* ## / #endif #define fatal(msg) fatal3(msg, FILE, LINE) #define new(p) if (((p)=malloc(sizeof(*(p))))); else fatal("out of memory") #define dispose(p) if (!(p)) ; else (free(p), (p) = (void*)0) #define heapmax(p) 9999999 /* ? */ #define newstring(s) heap_newstring(s, -1, FILE, LINE) #define newnstring(s,n) heap_newstring(s, n, FILE, LINE) #define newarray(p,n) \ if (((p)=malloc((n)*sizeof(*(p))))); else fatal("out of memory") #define renewarray(p,n) \ if (((p)=realloc(p,(n)*sizeof(*(p))))); else fatal("out of memory") EXPORTDEF(fatal(msg)) EXPORTDEF(new(p)) EXPORTDEF(dispose(p)) EXPORTDEF(heapmax(p)) EXPORTDEF(newstring(s)) EXPORTDEF(newnstring(s,n)) EXPORTDEF(newarray(p,n)) EXPORTDEF(renewarray(p,n)) EXPORT void fatal3(const char *s, const char *file, const int line) { fprintf(stderr, "%s (file %s, line %d)\n", s, file, line); abort(); } EXPORT char * heap_newstring(const char *s, int n, const char *file, int line) { char *t; if (n < 0) n = strlen(s); if (!s) return NULL; t = malloc((n + 1) * sizeof(*t)); if (!t) fatal3("out of memory", file, line); strncpy(t, s, n); t[n] = '\0'; return t; }