/*
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
  Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/* Error reporting. */
#include <stdarg.h>

#include <vppinfra/clib.h>	/* for HAVE_ERRNO */

#ifdef CLIB_LINUX_KERNEL
#include <linux/unistd.h>	/* for write */
#include <linux/kernel.h>	/* for printk */
#endif

#ifdef CLIB_UNIX
#include <unistd.h>		/* for write */
#include <stdio.h>		/* for printf */
#define HAVE_ERRNO
#endif

#ifdef CLIB_STANDALONE
#include <vppinfra/standalone_stdio.h>	/* for printf */
#endif

#include <vppinfra/string.h>
#include <vppinfra/mem.h>
#include <vppinfra/vec.h>
#include <vppinfra/format.h>
#include <vppinfra/error.h>
#include <vppinfra/hash.h>
#include <vppinfra/os.h>	/* for os_panic/os_exit/os_puts */

typedef struct
{
  clib_error_handler_func_t *func;
  void *arg;
} clib_error_handler_t;

static clib_error_handler_t *handlers = 0;

void
clib_error_register_handler (clib_error_handler_func_t func, void *arg)
{
  clib_error_handler_t h = {.func = func,.arg = arg, };
  vec_add1 (handlers, h);
}

static void
debugger (void)
{
  os_panic ();
}

static void
error_exit (int code)
{
  os_exit (code);
}

static u8 *
dispatch_message (u8 * msg)
{
  word i;

  if (!msg)
    return msg;

  for (i = 0; i < vec_len (handlers); i++)
    handlers[i].func (handlers[i].arg, msg, vec_len (msg));

  /* If no message handler is specified provide a default one. */
  if (vec_len (handlers) == 0)
    os_puts (msg, vec_len (msg), /* is_error */ 1);

  return msg;
}

void
_clib_error (int how_to_die,
	     char *function_name, uword line_number, char *fmt, ...)
{
  u8 *msg = 0;
  va_list va;

  if (function_name)
    {
      msg = format (msg, "%s:", function_name);
      if (line_number > 0)
	msg = format (msg, "%wd:", line_number);
      msg = format (msg, " ");
    }

  va_start (va, fmt);
  msg = va_format (msg, fmt, &va);
  va_end (va);

#ifdef HAVE_ERRNO
  if (how_to_die & CLIB_ERROR_ERRNO_VALID)
    msg = format (msg, ": %s (errno %d)", strerror (errno), errno);
#endif

  if (vec_end (msg)[-1] != '\n')
    vec_add1 (msg, '\n');

  msg = dispatch_message (msg);

  vec_free (msg);

  if (how_to_die & CLIB_ERROR_ABORT)
    debugger ();
  if (how_to_die & CLIB_ERROR_FATAL)
    error_exit (1);
}

clib_error_t *
_clib_error_return (clib_error_t * errors,
		    any code, uword flags, char *where, char *fmt, ...)
{
  clib_error_t *e;
  va_list va;

#ifdef HAVE_ERRNO
  /* Save errno since it may be re-set before we'll need it. */
  word errno_save = errno;
#endif

  va_start (va, fmt);
  vec_add2 (errors, e, 1);
  if (fmt)
    e->what = va_format (0, fmt, &va);

#ifdef HAVE_ERRNO
  if (flags & CLIB_ERROR_ERRNO_VALID)
    {
      if (e->what)
	e->what = format (e->what, ": ");
      e->what = format (e->what, "%s", strerror (errno_save));
    }
#endif

  e->where = (u8 *) where;
  e->code = code;
  e->flags = flags;
  va_end (va);
  return errors;
}

void *
clib_error_free_vector (clib_error_t * errors)
{
  clib_error_t *e;
  vec_foreach (e, errors) vec_free (e->what);
  vec_free (errors);
  return 0;
}

u8 *
format_clib_error (u8 * s, va_list * va)
{
  clib_error_t *errors = va_arg (*va, clib_error_t *);
  clib_error_t *e;

  vec_foreach (e, errors)
  {
    if (!e->what)
      continue;

    if (e->where)
      {
	u8 *where = 0;

	if (e > errors)
	  where = format (where, "from ");
	where = format (where, "%s", e->where);

	s = format (s, "%v: ", where);
	vec_free (where);
      }

    s = format (s, "%v\n", e->what);
  }

  return s;
}

clib_error_t *
_clib_error_report (clib_error_t * errors)
{
  if (errors)
    {
      u8 *msg = format (0, "%U", format_clib_error, errors);

      msg = dispatch_message (msg);
      vec_free (msg);

      if (errors->flags & CLIB_ERROR_ABORT)
	debugger ();
      if (errors->flags & CLIB_ERROR_FATAL)
	error_exit (1);

      clib_error_free (errors);
    }
  return 0;
}

#ifdef TEST

static error_t *
foo1 (int x)
{
  return error_return (0, "x is odd %d", x);
}

static error_t *
foo2 (int x)
{
  return error_return (0, "x is even %d", x);
}

static error_t *
foo (int x)
{
  error_t *e;
  if (x & 1)
    e = foo1 (x);
  else
    e = foo2 (x);
  if (e)
    return error_return (e, 0);
}

static void
error_handler (void *arg, char *msg, int msg_len)
{
  write (2, msg, msg_len);
}

int
main (int argc, char *argv[])
{
  error_t *e;

  register_error_handler (error_handler, 0);

  e = foo (getpid ());
  if (e)
    error_report (e);
  return 0;
}

#endif

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
