/* t-common.h - Common code for the tests.
 * Copyright (C) 2013 g10 Code GmbH
 *
 * This file is part of libgpg-error.
 *
 * libgpg-error is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * libgpg-error is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, see <https://www.gnu.org/licenses/>.
 */

#include <stdarg.h>

#include "../src/gpgrt.h"

#ifndef PGM
# error Macro PGM not defined.
#endif
#ifndef DIM
# define DIM(array) (sizeof (array) / sizeof (*array))
#endif


static int verbose;
static int debug;
static int errorcount;
static const char *current_func;

static void die (const char *format, ...) GPGRT_ATTR_NR_PRINTF(1,2);
static void fail (const char *format, ...) GPGRT_ATTR_PRINTF(1,2);
static void show (const char *format, ...) GPGRT_ATTR_PRINTF(1,2);


/* Set the name of the function to be used in error messages.   */
#define enter_test_function() do { current_func = __func__; } while(0)
#define leave_test_function() do { current_func = NULL; } while(0)


static void *
xmalloc (size_t n)
{
  char *p = gpgrt_malloc (n);
  if (!p)
    die ("out of core\n");
  return p;
}

static char *
xstrdup (const char *s)
{
  char *p = gpgrt_strdup (s);
  if (!p)
    die ("out of core\n");
  return p;
}

static void
xfree (void *p)
{
  if (p)
    gpgrt_free (p);
}



static void
die (const char *format, ...)
{
  va_list arg_ptr ;

  fflush (stdout);
#ifdef HAVE_FLOCKFILE
  flockfile (stderr);
#endif
  if (current_func)
    fprintf (stderr, "%s:%s: ", PGM, current_func);
  else
    fprintf (stderr, "%s: ", PGM);
  va_start (arg_ptr, format) ;
  vfprintf (stderr, format, arg_ptr);
  va_end (arg_ptr);
  if (*format && format[strlen(format)-1] != '\n')
    putc ('\n', stderr);
#ifdef HAVE_FLOCKFILE
  funlockfile (stderr);
#endif
  xfree (xstrdup (""));  /* To avoid compiler warnings.  */
  xfree (xmalloc (16));  /* To avoid compiler warnings.  */
  exit (1);
}


static void
fail (const char *format, ...)
{
  va_list arg_ptr;

  fflush (stdout);
#ifdef HAVE_FLOCKFILE
  flockfile (stderr);
#endif
  if (current_func)
    fprintf (stderr, "%s:%s: ", PGM, current_func);
  else
    fprintf (stderr, "%s: ", PGM);
  va_start (arg_ptr, format);
  vfprintf (stderr, format, arg_ptr);
  va_end (arg_ptr);
  if (*format && format[strlen(format)-1] != '\n')
    putc ('\n', stderr);
#ifdef HAVE_FLOCKFILE
  funlockfile (stderr);
#endif
  errorcount++;
  if (errorcount >= 50)
    die ("stopped after 50 errors.");
}


static void
show (const char *format, ...)
{
  va_list arg_ptr;

  if (!verbose)
    return;
#ifdef HAVE_FLOCKFILE
  flockfile (stderr);
#endif
  if (current_func)
    fprintf (stderr, "%s:%s: ", PGM, current_func);
  else
    fprintf (stderr, "%s: ", PGM);
  va_start (arg_ptr, format);
  vfprintf (stderr, format, arg_ptr);
  if (*format && format[strlen(format)-1] != '\n')
    putc ('\n', stderr);
  va_end (arg_ptr);
#ifdef HAVE_FLOCKFILE
  funlockfile (stderr);
#endif
}
