/* do not edit automatically generated by mc from lists.  */
/* Dynamic list library for pointers.
   Copyright (C) 2015-2025 Free Software Foundation, Inc.

This file is part of GNU Modula-2.

GNU Modula-2 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, or (at your option) any later
version.

GNU Modula-2 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 GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include <stdbool.h>
#   if !defined (PROC_D)
#      define PROC_D
       typedef void (*PROC_t) (void);
       typedef struct { PROC_t proc; } PROC;
#   endif

#   if !defined (TRUE)
#      define TRUE (1==1)
#   endif

#   if !defined (FALSE)
#      define FALSE (1==0)
#   endif

#   include "GStorage.h"
#if defined(__cplusplus)
#   undef NULL
#   define NULL 0
#endif
#define _lists_C

#include "Glists.h"
#   include "GStorage.h"

typedef struct symbolKey_performOperation_p symbolKey_performOperation;

#   define MaxnoOfelements 5
typedef struct lists__T1_r lists__T1;

typedef struct lists__T2_a lists__T2;

typedef lists__T1 *lists_list__opaque;

struct lists__T2_a { void * array[MaxnoOfelements-1+1]; };
struct lists__T1_r {
                     unsigned int noOfelements;
                     lists__T2 elements;
                     lists_list__opaque next;
                   };


/*
   initList - creates a new list, l.
*/

extern "C" lists_list lists_initList (void);

/*
   killList - deletes the complete list, l.
*/

extern "C" void lists_killList (lists_list *l);

/*
   putItemIntoList - places an ADDRESS, c, into list, l.
*/

extern "C" void lists_putItemIntoList (lists_list l, void * c);

/*
   getItemFromList - retrieves the nth WORD from list, l.
*/

extern "C" void * lists_getItemFromList (lists_list l, unsigned int n);

/*
   getIndexOfList - returns the index for WORD, c, in list, l.
                    If more than one WORD, c, exists the index
                    for the first is returned.
*/

extern "C" unsigned int lists_getIndexOfList (lists_list l, void * c);

/*
   noOfItemsInList - returns the number of items in list, l.
*/

extern "C" unsigned int lists_noOfItemsInList (lists_list l);

/*
   includeItemIntoList - adds an ADDRESS, c, into a list providing
                         the value does not already exist.
*/

extern "C" void lists_includeItemIntoList (lists_list l, void * c);

/*
   removeItemFromList - removes a ADDRESS, c, from a list.
                        It assumes that this value only appears once.
*/

extern "C" void lists_removeItemFromList (lists_list l, void * c);

/*
   isItemInList - returns true if a ADDRESS, c, was found in list, l.
*/

extern "C" bool lists_isItemInList (lists_list l, void * c);

/*
   foreachItemInListDo - calls procedure, P, foreach item in list, l.
*/

extern "C" void lists_foreachItemInListDo (lists_list l, symbolKey_performOperation p);

/*
   duplicateList - returns a duplicate list derived from, l.
*/

extern "C" lists_list lists_duplicateList (lists_list l);

/*
   removeItem - remove an element at index, i, from the list data type.
*/

static void removeItem (lists_list__opaque p, lists_list__opaque l, unsigned int i);


/*
   removeItem - remove an element at index, i, from the list data type.
*/

static void removeItem (lists_list__opaque p, lists_list__opaque l, unsigned int i)
{
  l->noOfelements -= 1;
  while (i <= l->noOfelements)
    {
      l->elements.array[i-1] = l->elements.array[i+1-1];
      i += 1;
    }
  if ((l->noOfelements == 0) && (p != NULL))
    {
      p->next = l->next;
      Storage_DEALLOCATE ((void **) &l, sizeof (lists__T1));
    }
}


/*
   initList - creates a new list, l.
*/

extern "C" lists_list lists_initList (void)
{
  lists_list__opaque l;

  Storage_ALLOCATE ((void **) &l, sizeof (lists__T1));
  l->noOfelements = 0;
  l->next = static_cast<lists_list__opaque> (NULL);
  return static_cast<lists_list> (l);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   killList - deletes the complete list, l.
*/

extern "C" void lists_killList (lists_list *l)
{
  if ((*l) != NULL)
    {
      if (static_cast<lists_list__opaque> ((*l))->next != NULL)
        {
          lists_killList (reinterpret_cast<lists_list *> (&static_cast<lists_list__opaque> ((*l))->next));
        }
      Storage_DEALLOCATE ((void **) &(*l), sizeof (lists__T1));
    }
}


/*
   putItemIntoList - places an ADDRESS, c, into list, l.
*/

extern "C" void lists_putItemIntoList (lists_list l, void * c)
{
  if (static_cast<lists_list__opaque> (l)->noOfelements < MaxnoOfelements)
    {
      static_cast<lists_list__opaque> (l)->noOfelements += 1;
      static_cast<lists_list__opaque> (l)->elements.array[static_cast<lists_list__opaque> (l)->noOfelements-1] = c;
    }
  else if (static_cast<lists_list__opaque> (l)->next != NULL)
    {
      /* avoid dangling else.  */
      lists_putItemIntoList (static_cast<lists_list> (static_cast<lists_list__opaque> (l)->next), c);
    }
  else
    {
      /* avoid dangling else.  */
      static_cast<lists_list__opaque> (l)->next = static_cast<lists_list__opaque> (lists_initList ());
      lists_putItemIntoList (static_cast<lists_list> (static_cast<lists_list__opaque> (l)->next), c);
    }
}


/*
   getItemFromList - retrieves the nth WORD from list, l.
*/

extern "C" void * lists_getItemFromList (lists_list l, unsigned int n)
{
  while (l != NULL)
    {
      if (n <= static_cast<lists_list__opaque> (l)->noOfelements)
        {
          return static_cast<lists_list__opaque> (l)->elements.array[n-1];
        }
      else
        {
          n -= static_cast<lists_list__opaque> (l)->noOfelements;
        }
      l = static_cast<lists_list> (static_cast<lists_list__opaque> (l)->next);
    }
  return static_cast<void *> (0);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   getIndexOfList - returns the index for WORD, c, in list, l.
                    If more than one WORD, c, exists the index
                    for the first is returned.
*/

extern "C" unsigned int lists_getIndexOfList (lists_list l, void * c)
{
  unsigned int i;

  if (l == NULL)
    {
      return 0;
    }
  else
    {
      i = 1;
      while (i <= static_cast<lists_list__opaque> (l)->noOfelements)
        {
          if (static_cast<lists_list__opaque> (l)->elements.array[i-1] == c)
            {
              return i;
            }
          else
            {
              i += 1;
            }
        }
      return static_cast<lists_list__opaque> (l)->noOfelements+(lists_getIndexOfList (static_cast<lists_list> (static_cast<lists_list__opaque> (l)->next), c));
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   noOfItemsInList - returns the number of items in list, l.
*/

extern "C" unsigned int lists_noOfItemsInList (lists_list l)
{
  unsigned int t;

  if (l == NULL)
    {
      return 0;
    }
  else
    {
      t = 0;
      do {
        t += static_cast<lists_list__opaque> (l)->noOfelements;
        l = static_cast<lists_list> (static_cast<lists_list__opaque> (l)->next);
      } while (! (l == NULL));
      return t;
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   includeItemIntoList - adds an ADDRESS, c, into a list providing
                         the value does not already exist.
*/

extern "C" void lists_includeItemIntoList (lists_list l, void * c)
{
  if (! (lists_isItemInList (l, c)))
    {
      lists_putItemIntoList (l, c);
    }
}


/*
   removeItemFromList - removes a ADDRESS, c, from a list.
                        It assumes that this value only appears once.
*/

extern "C" void lists_removeItemFromList (lists_list l, void * c)
{
  lists_list__opaque p;
  unsigned int i;
  bool found;

  if (l != NULL)
    {
      found = false;
      p = static_cast<lists_list__opaque> (NULL);
      do {
        i = 1;
        while ((i <= static_cast<lists_list__opaque> (l)->noOfelements) && (static_cast<lists_list__opaque> (l)->elements.array[i-1] != c))
          {
            i += 1;
          }
        if ((i <= static_cast<lists_list__opaque> (l)->noOfelements) && (static_cast<lists_list__opaque> (l)->elements.array[i-1] == c))
          {
            found = true;
          }
        else
          {
            p = static_cast<lists_list__opaque> (l);
            l = static_cast<lists_list> (static_cast<lists_list__opaque> (l)->next);
          }
      } while (! ((l == NULL) || found));
      if (found)
        {
          removeItem (p, static_cast<lists_list__opaque> (l), i);
        }
    }
}


/*
   isItemInList - returns true if a ADDRESS, c, was found in list, l.
*/

extern "C" bool lists_isItemInList (lists_list l, void * c)
{
  unsigned int i;

  do {
    i = 1;
    while (i <= static_cast<lists_list__opaque> (l)->noOfelements)
      {
        if (static_cast<lists_list__opaque> (l)->elements.array[i-1] == c)
          {
            return true;
          }
        else
          {
            i += 1;
          }
      }
    l = static_cast<lists_list> (static_cast<lists_list__opaque> (l)->next);
  } while (! (l == NULL));
  return false;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   foreachItemInListDo - calls procedure, P, foreach item in list, l.
*/

extern "C" void lists_foreachItemInListDo (lists_list l, symbolKey_performOperation p)
{
  unsigned int i;
  unsigned int n;

  n = lists_noOfItemsInList (l);
  i = 1;
  while (i <= n)
    {
      (*p.proc) (lists_getItemFromList (l, i));
      i += 1;
    }
}


/*
   duplicateList - returns a duplicate list derived from, l.
*/

extern "C" lists_list lists_duplicateList (lists_list l)
{
  lists_list__opaque m;
  unsigned int n;
  unsigned int i;

  m = static_cast<lists_list__opaque> (lists_initList ());
  n = lists_noOfItemsInList (l);
  i = 1;
  while (i <= n)
    {
      lists_putItemIntoList (static_cast<lists_list> (m), lists_getItemFromList (l, i));
      i += 1;
    }
  return static_cast<lists_list> (m);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

extern "C" void _M2_lists_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
{
}

extern "C" void _M2_lists_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
{
}