/* vi: set tabstop=4 shiftwidth=4 */
/*
* $Id: error.c,v 2.1 2005/06/17 20:48:15 schweikh Exp $
*/
/*@ignore@*/
#ifndef _POSIX_SOURCE
# define _POSIX_SOURCE 1
#endif
/*@end@*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "shutup.h"
#include "error.h"
/*@-ptrarith@*/
/*@-redecl@*/
/*@-predboolint -statictrans -globstate@*/
/*
* progname is a short string prepended to error messages.
*/
/*@i1@*/ static char *progname = "(program name not assigned)";
#if MALLOC_DEBUG
static FILE *debug;
#endif
long alloc_free = 0; /* # alloc minus # free */
static void
err_doit (int, const char *, va_list ap)
/*@globals progname,stderr,fileSystem,errno@*/
/*@modifies *stderr,fileSystem,ap,errno@*/;
char *
program_name (void)
{
return progname;
}
/*
* Checked fprintf: do fprintf and exit if it failed
* (probably due to an I/O or "no space on device" error).
*/
void
cfprintf (FILE *fp, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
if (vfprintf (fp, fmt, ap) < 0) {
err_sys ("fprintf failed for format `%s'", fmt);
}
va_end (ap);
}
/*
* write program name to a stream and return
* a pointer to static memory with the name.
*/
char *
err_progname (FILE * fp)
{
if (fp != NULL) {
check_sys (fflush (fp) == 0);
cfprintf (fp, "%s", progname);
check_sys (fflush (fp) == 0);
}
return progname;
}
void
set_progname (char *argv0, char *def)
{
if (argv0 == NULL || argv0[0] == '\0') {
progname = def;
} else {
char *p = strrchr (argv0, '/');
/* p + 1 um '/' übergehen */
progname = p == NULL ? argv0 : p + 1;
}
#if MALLOC_DEBUG
debug = fopen (DEBUG_FILE, "w");
check_sys (debug != NULL);
#endif
}
/*
* Nonfatal error related to a system call. Print a message and return.
*/
void
err_ret (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
err_doit (1, fmt, ap);
va_end (ap);
}
/*
* Fatal error related to a system call. Print a message and exit().
*/
void
err_sys (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
err_doit (1, fmt, ap);
va_end (ap);
exit (EXIT_FAILURE);
}
/*
* Fatal error related to a system call. Print a message and dump core.
*/
void
err_dump (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
err_doit (1, fmt, ap);
va_end (ap);
abort ();
/*@NOTREACHED@*/
exit (EXIT_FAILURE); /* should never get here */
}
/*
* Nonfatal error unrelated to a system call. Print a message and return.
*/
void
err_msg (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
err_doit (0, fmt, ap);
va_end (ap);
}
/*
* Fatal error unrelated to a system call. Print a message and exit().
*/
void
err_quit (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
err_doit (0, fmt, ap);
va_end (ap);
exit (EXIT_FAILURE);
}
static void
err_doit (int errnoflag, const char *fmt, va_list ap)
{
int errno_save = errno;
Fflush (stdout);
Fprintf (stderr, "%s: ", progname);
Vfprintf (stderr, fmt, ap);
if (errnoflag != 0) {
Fputc (':', stderr);
Fputc (' ', stderr);
errno = errno_save;
perror (NULL);
} else {
Fputc ('\n', stderr);
}
Fflush (NULL);
}
void
/*@unused@*//*@printflike@*/
warn (int flags, const char *fmt,...)
{
int errno_save = errno;
va_list ap;
va_start (ap, fmt);
check_sys (fflush (NULL) == 0);
cfprintf (stderr, "%s: ", progname);
check_sys (vfprintf (stderr, fmt, ap) >= 0);
if (flags & E_PERROR) {
errno = errno_save;
perror (" ");
} else {
check_sys (fputc ('\n', stderr) != EOF);
}
check_sys (fflush (stderr) == 0);
}
void
/*@unused@*//*@printflike@*/
error (int flags, const char *fmt,...)
{
int errno_save = errno;
va_list ap;
va_start (ap, fmt);
check_sys (fflush (NULL) == 0);
cfprintf (stderr, "%s: ", progname);
check_sys (vfprintf (stderr, fmt, ap) >= 0);
if (flags & E_PERROR) {
errno = errno_save;
perror (" ");
} else {
check_sys (fputc ('\n', stderr) != EOF);
}
check_sys (fflush (stderr) == 0);
if (flags & E_ABORT)
abort ();
else
exit (EXIT_FAILURE);
}
/*@-compdef@*/
void *
#if MALLOC_DEBUG
xxmalloc (size_t s, char *file, int line)
{
void *p = malloc (s);
if (p == NULL)
error (0, "malloc(%lu)", (unsigned long) s);
cfprintf (debug, "a %p %s:%d %lu\n",
(void *) p, file, line, (unsigned long) s);
++alloc_free;
return p;
}
#else /* !MALLOC_DEBUG */
xxmalloc (size_t s)
{
void *p = malloc (s);
if (p == NULL)
error (0, "malloc(%lu)", (unsigned long) s);
++alloc_free;
return p;
}
#endif
/*@only@*/ void *
#if MALLOC_DEBUG
xxcalloc (size_t n, size_t s, char *file, int line)
{
void *p = calloc (n, s);
if (p == NULL)
error (0, "calloc(%lu, %lu)",
(unsigned long) n, (unsigned long) s);
cfprintf (debug, "a %p %s:%d %lu\n",
(void *) p, file, line, (unsigned long) n * s);
++alloc_free;
return p;
}
#else /* !MALLOC_DEBUG */
xxcalloc (size_t n, size_t s)
{
void *p = calloc (n, s);
if (p == NULL)
error (0, "calloc(%lu, %lu)",
(unsigned long) n, (unsigned long) s);
++alloc_free;
return p;
}
#endif
/*
* realloc hat 3 Arbeitsweisen:
* 1. realloc (0, s) wie malloc (s)
* 2. realloc (oldp, 0) wie free (oldp)
* 3. realloc (oldp, s) resize
*/
void *
#if MALLOC_DEBUG
xxrealloc (void *oldp, size_t newsize, char *file, int line)
{
void *newp;
if (oldp != NULL) {
--alloc_free;
cfprintf (debug, "f %p %s:%d\n",
(void *) oldp, file, line);
}
newp = realloc (oldp, newsize);
if (newsize == 0) /* free */
return (void *) 1; /* dummy; nicht NULL wg lclint */
if (newp == NULL)
error (0, "realloc(%lu)", (unsigned long) newsize);
cfprintf (debug, "a %p %s:%d %lu\n",
(void *) newp, file, line,
(unsigned long) newsize);
++alloc_free;
return newp;
}
#else /* !MALLOC_DEBUG */
xxrealloc (void *oldp, size_t newsize)
{
void *newp;
if (oldp != NULL)
--alloc_free;
newp = realloc (oldp, newsize);
if (newsize == 0) /* free */
return (void *) 1; /* dummy; nicht NULL wg lclint */
if (newp == NULL)
error (0, "realloc(%lu)", (unsigned long) newsize);
++alloc_free;
return newp;
}
#endif
/*@-nullpass@*/
void
#if MALLOC_DEBUG
xxfree (void *p, char *file, int line)
{
if (p == NULL) {
cfprintf (debug, "f NULL %s:%d\n", file, line);
return;
}
cfprintf (debug, "f %p %s:%d\n", (void *) p, file, line);
--alloc_free;
free (p);
}
#else /* !MALLOC_DEBUG */
xxfree (void *p)
{
if (p != NULL) {
--alloc_free;
free (p);
}
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1