list.c 10.3 KB
/**
 * \file list.c
 * \author  Georg Steffers <georg@steffers.org>
 * \brief   Internal implementations for list handling.
 *
 * This implements the internals for the typesafe linked list
 * implementation provided by \link scot/list.h list.h\endlink,
 * \link scot/list_proto.h list_proto.h\endlink and
 * \link scot/list_impl.h list_impl.h\endlink.
 * The only thing one has to remember when one only wants to
 * use linked lists within the own code is to link the code agains
 * an object of this. This is normally done by linking agains
 * libscot with an -lscot or similar compiler switch.
 * 
 * Copyright (C)2006    Georg Steffers <georg@steffers.org>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include <stdio.h>
#include <stdlib.h>

#include <scot/list.h>
#include <scot/exception.h>
#include <scot/scot_exceptions.h>
#include <scot/memory.h>
#include <scot_common.h>
#include <scot/scot_types.h>

/**
 * \internal
 * \brief Error messages given.
 *
 * This holds all error messages that go either to the exception system
 * or will be printed on stderr if an error occurs within a list function.
 */
const char *list_err_msg[] = 
{
   N_("[LIST]Failed to create new list."),
   N_("[LIST]Failed to free list."),
   N_("[LIST]Failed to check for begin of list."),
   N_("[LIST]Failed to check for end of list."),
   N_("[LIST]Failed to check for list emptiness."),
   N_("[LIST]Failed to get first list node."),
   N_("[LIST]Failed to get last list node."),
   N_("[LIST]Failed to get next list node."),
   N_("[LIST]Failed to get previous list node."),
   N_("[LIST]Failed to find list node."),
   N_("[LIST]Failed to find list anchor."),
   N_("[LIST]Failed to retrive the node's value."),
   N_("[LIST]Failed to set the node's value."),
   N_("[LIST]Failed to insert node."),
   N_("[LIST]Failed to delete node."),
   N_("[LIST]Failed to concatanate the lists."),
   N_("[LIST]Failed to count list nodes."),
   N_("[LIST]Node is no anchor."),
   N_("[LIST]Malformed list."),
   NULL
};

/**
 * \internal
 * \brief Warning messages given.
 *
 * This holds all warning messages that go either to the exception system
 * or will be printed on stderr if an error occurs within a list function.
 */
const char *list_wrn_msg[] = 
{
   N_("[LIST]tried to delete on an empyt list"),
   NULL
};

/**
 * \internal
 * \param   lvl   either ERROR or WARNING
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 * \param   id    the error or warning id. (Used to pick the correct message)
 *
 * \pre     None
 * \returns Nothing
 * \post    An error or warning message printed to stderr. In case of an 
 *          ERROR the program is aborted.
 *
 * \brief Print error or warning to stderr.
 */
static
void
list_ew_print (
      const enum exclvl_t  lvl, 
      const char           *file,
      const int            line,
      const int            id)
{
   bindtextdomain (PACKAGE, LOCALEDIR);
   fprintf (
         stderr,
         "[%s(%s:%d)]\n(%d) %s\n",
         (lvl == EXC_ERROR)?D_("ERROR"):D_("WARNING"),
         file,
         line,
         id,
         (lvl == EXC_ERROR)?D_(list_err_msg [id]):D_(list_wrn_msg [id]));

   if (lvl == EXC_ERROR)
   {
      abort ();
   }
}

/**
 * \internal
 * \param   lvl   either ERROR or WARNING
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 * \param   id    the error or warning id. (Used to pick the correct message)
 *
 * \pre     An exception environment created by a previous call of TRY.
 * \returns Nothing
 * \post    An exception thrown into the exception environment.
 *
 * \brief Throw error or warning in an exception environment.
 */
static
void
list_ew_throw (
      enum exclvl_t  lvl, 
      const char     *file,
      int            line,
      int            id)
{
   THROW (exc_new (lvl, file, line, id, D_(list_err_msg [id])));
}

/**
 * \internal
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 * \param   id    the error id. (Used to pick the correct message)
 *
 * \pre     None
 * \returns Nothing
 * \post    An error message printed to stderr. The program is aborted.
 *
 * \brief Print error to stderr.
 */
void
list_error_print (const char *file, int line, const int id)
{
   list_ew_print (EXC_ERROR, file, line, id);
}
/**
 * \internal
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 * \param   id    the warning id. (Used to pick the correct message)
 *
 * \pre     None
 * \returns Nothing
 * \post    An warning message printed to stderr.
 *
 * \brief Print warning to stderr.
 */
void
list_warning_print (const char *file, int line, int id)
{
   list_ew_print (EXC_WARNING, file, line, id);
}
/**
 * \internal
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 * \param   id    the error id. (Used to pick the correct message)
 *
 * \pre     An exception environment created by a previous call of TRY.
 * \returns Nothing
 * \post    An exception thrown into the exception environment.
 *
 * \brief Throw error.
 */
void
list_error_throw (const char *file, int line, int id)
{
   list_ew_throw (EXC_ERROR, file, line, id);
}
void
/**
 * \internal
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 * \param   id    the warning id. (Used to pick the correct message)
 *
 * \pre     An exception environment created by a previous call of TRY.
 * \returns Nothing
 * \post    An exception thrown into the exception environment.
 *
 * \brief Throw warning.
 */
list_warning_throw (const char *file, int line, int id)
{
   list_ew_throw (EXC_WARNING, file, line, id);
}

/**
 * \internal
 * \param   size  SIZE_T size of memory to be allocates (see man malloc).
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 *
 * \pre     None
 * \returns A pointer to the memory location reserved by malloc.
 * \post    Either memory is allocated on the heap or an error messege is
 *          printed to stderr and the program aborted.
 *
 * \brief Malloc wrapper with error handling.
 *
 * This calls malloc and if it fails gives an error message to stderr.
 * If this malloc fails it is assumed a serious error and thus the program
 * is aborted in this case.
 */
void *
list_malloc_print (SIZE_T size, const char *file, int line)
{
   void *a;
   
   bindtextdomain (PACKAGE, LOCALEDIR);
   a = SCOT_MEM_GET (size);

   if (a == NULL)
   {
      fprintf (
            stderr,
            "[ERROR(%s:%d)]\n(%d) %s\n",
            file,
            line,
            MALLOC_ERR,
            D_(scot_err_msg [MALLOC_ERR]));

      abort ();
   }
}

/**
 * \internal
 * \param   size  SIZE_T size of memory to be allocates (see man malloc).
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 *
 * \pre     An exception environment created by a previous call of TRY.
 * \returns A pointer to the memory location reserved by malloc.
 * \post    Either memory is allocated on the heap or an exception thrown
 *          into the exception environment.
 *
 * \brief Malloc wrapper with error handling.
 *
 * This calls malloc and if it fails throws an exception.
 * This malloc fails it is assumed a serious error and thus an ERROR
 * is thrown into the exception system causing the calling function to
 * be aborted and goes to exception handling CATCH of the current 
 * exception environment.
 */
void *
list_malloc_throw (SIZE_T size, const char *file, int line)
{
   return exc_malloc_fl (size, file, line);
}

/**
 * \internal
 * \param   val   Pointer to be checked.
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 *
 * \pre     None
 * \returns Nothing.
 * \post    If val is NULL an error messege is
 *          printed to stderr and the program aborted.
 *
 * \brief Checks the given value for beeing NULL.
 *
 * This checks the given \a val for beeing NULL and if is gives an 
 * error message to stderr. If this check fails within the list
 * code it is a serious error and thus the program is aborted.
 */
void
list_check_null_print (const void *val, const char *file, int line)
{
   bindtextdomain (PACKAGE, LOCALEDIR);

   if (val == NULL)
   {
      fprintf (
            stderr,
            "[ERROR(%s:%d)]\n(%d) %s\n",
            file,
            line,
            NULL_PTR_ERR,
            D_(scot_err_msg [NULL_PTR_ERR]));

      abort ();
   }
}

/**
 * \internal
 * \param   val   Pointer to be checked.
 * \param   file  the filename of the source file from where this is called
 * \param   line  the line in the source file from where this is called
 *
 * \pre     An exception environment created by a previous call of TRY.
 * \returns Nothing.
 * \post    If val is NULL an exception thrown
 *          into the exception environment.
 *
 * \brief Checks the given value for beeing NULL.
 *
 * This checks the given \a val for beeing NULL and if is throws
 * an exception. If this check fails within the list code it is a 
 * serious error and thus an ERROR is throw into the exception system,
 * causing the calling function to abort and go to exception handling
 * CATCH of the actual exception environment.
 */
void
list_check_null_throw (const void *val, const char *file, int line)
{
   check_null_fl (val, file, line);
}