
/*
 *  Copyright t lefering
 *  Copyright Simon Speich 2013
 *
 *  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 3 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, see <http://www.gnu.org/licenses/>.
 *
 *  These are the four essential freedoms with GNU GPL software:
 *  1: freedom to run the program, for any purpose
 *  2: freedom to study how the program works, and change it to make it do what you wish
 *  3: freedom to redistribute copies to help your Free Software friends
 *  4: freedom to distribute copies of your modified versions to your Free Software friends
 *   ,           ,
 *  /             \
 * ((__-^^-,-^^-__))
 * `-_---'  `---_-'
 *  `--|o`   'o|--'
 *      \  `  /
 *       ): :(
 *       :o_o:
 *        "-"
 *
 * SPDX-License-Identifier: GPL-3.0+
 * License-Filename: LICENSE
 */

/**
 * all routines have prefix d4d_
 * all static routines and vars have prefix d4d___
 * the prefix d4d_ has no special meaning but hopefully
 * does not problems because of limited C namespace
 */

/* only in debug version linkage needed to printf */
#if D4D_DEBUG
#include <stdio.h>
#define print_debug(str, ...) printf(str" - %s:%u\n", ##__VA_ARGS__, __FILE__, __LINE__);
#endif

/* datatypoes used are
 * int, as signed 32bits integer value
 * unsigned int, as 32bits integer value
 * char, as signed 8bits integer value
 * unsigned char, as 8bits integer value
 */

/**
 * set here version number as int
 */
#define D4DAG_VERSION 10

/* defs and prototypes of routines for user program */
#include "d4dag.h"

/* mallocer/freeer */
typedef void *(*malloc_fn) (unsigned int n);
typedef void (*free_fn) (void *ptr);

/* toplevel control struct */
struct d4d__maing
{
  /* wrappers for malloc/free and all malloc's will be below 4Gb at once */
  malloc_fn d4d__malloc;
  free_fn d4d__free;
};

/* main control */
static struct d4d__maing *d4d__main = (struct d4d__maing *) 0;

/* forward decl. */
static void d4d__memzero (void *ptr, unsigned int n);
/**
 * returns version number as int
 */
int
d4d_version (void)
{
  return (D4DAG_VERSION);
}

/**
 *
 * returns:
 *  0 if oke
 * -1 if missing malloc/free pointer
 * -2 if malloc failed
 * For embedded devices this source has no linkage to libraries
 * which means here pointer to malloc/free must be supplied.
 * when malloc returns zero then these routines crashes
 */
int
d4d_init (void *(*mallocer) (unsigned int n), void (*freeer) (void *ptr))
{
  /* malloc/free pointers must be specified */
  {
    if (!(!mallocer))
      {
	goto d4dag__unloop_1;
      }
    {
      return (-1);
    }
  d4dag__unloop_1:;
  }
  {
    if (!(!freeer))
      {
	goto d4dag__unloop_2;
      }
    {
      return (-1);
    }
  d4dag__unloop_2:;
  }
  d4d__main =
    (struct d4d__maing *) (*mallocer) ((unsigned int)
				       sizeof (struct d4d__maing));
  {
    if (!(!d4d__main))
      {
	goto d4dag__unloop_3;
      }
    {
      return (-2);
    }
  d4dag__unloop_3:;
  }
/* set pointers to malloc/free in toplevel control */
  d4d__memzero (d4d__main, sizeof (struct d4d__maing));
  d4d__main->d4d__malloc = mallocer;
  d4d__main->d4d__free = freeer;
  return (0);
}

/**
 *
 */
int
d4d_deinit (void)
{
  /* check if active */
  {
    if (!(!d4d__main))
      {
	goto d4dag__unloop_4;
      }
    {
      return (0);
    }
  d4dag__unloop_4:;
  }
/* free structs */
  /* free control */
  d4d__main->d4d__free (d4d__main);
  d4d__main = (struct d4d__maing *) 0;
  return (0);
}

/* like memset(ptr,0,n) */
static void
d4d__memzero (void *ptr, unsigned int n)
{
  unsigned char *p = (unsigned char *) 0;
  p = (unsigned char *) ptr;
  {
  d4dag__unloop_5:
    if (!(n))
      {
	goto d4dag__unloop_6;
      }
    {
      *p = 0;
      p++;
      n--;
    }
    goto d4dag__unloop_5;
  d4dag__unloop_6:;
  }

  return;
}

/* end. */
