/* do not edit automatically generated by mc from wlists.  */
/* wlists.mod word lists module.

Copyright (C) 2015-2025 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius@glam.ac.uk>.

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 GNU Modula-2; 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 _wlists_C

#include "Gwlists.h"
#   include "GStorage.h"

typedef struct wlists_performOperation_p wlists_performOperation;

#   define maxNoOfElements 5
typedef struct wlists__T1_r wlists__T1;

typedef struct wlists__T2_a wlists__T2;

typedef wlists__T1 *wlists_wlist__opaque;

struct wlists__T2_a { unsigned int array[maxNoOfElements-1+1]; };
struct wlists__T1_r {
                      unsigned int noOfElements;
                      wlists__T2 elements;
                      wlists_wlist__opaque next;
                    };


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

extern "C" wlists_wlist wlists_initList (void);

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

extern "C" void wlists_killList (wlists_wlist *l);

/*
   putItemIntoList - places an WORD, c, into wlist, l.
*/

extern "C" void wlists_putItemIntoList (wlists_wlist l, unsigned int c);

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

extern "C" unsigned int wlists_getItemFromList (wlists_wlist l, unsigned int n);

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

extern "C" unsigned int wlists_getIndexOfList (wlists_wlist l, unsigned int c);

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

extern "C" unsigned int wlists_noOfItemsInList (wlists_wlist l);

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

extern "C" void wlists_includeItemIntoList (wlists_wlist l, unsigned int c);

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

extern "C" void wlists_removeItemFromList (wlists_wlist l, unsigned int c);

/*
   replaceItemInList - replace the nth WORD in wlist, l.
                       The first item in a wlists is at index, 1.
                       If the index, n, is out of range nothing is changed.
*/

extern "C" void wlists_replaceItemInList (wlists_wlist l, unsigned int n, unsigned int w);

/*
   isItemInList - returns true if a WORD, c, was found in wlist, l.
*/

extern "C" bool wlists_isItemInList (wlists_wlist l, unsigned int c);

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

extern "C" void wlists_foreachItemInListDo (wlists_wlist l, wlists_performOperation p);

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

extern "C" wlists_wlist wlists_duplicateList (wlists_wlist l);

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

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


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

static void removeItem (wlists_wlist__opaque p, wlists_wlist__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 (wlists__T1));
    }
}


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

extern "C" wlists_wlist wlists_initList (void)
{
  wlists_wlist__opaque l;

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


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

extern "C" void wlists_killList (wlists_wlist *l)
{
  if ((*l) != NULL)
    {
      if (static_cast<wlists_wlist__opaque> ((*l))->next != NULL)
        {
          wlists_killList (reinterpret_cast<wlists_wlist *> (&static_cast<wlists_wlist__opaque> ((*l))->next));
        }
      Storage_DEALLOCATE ((void **) &(*l), sizeof (wlists__T1));
    }
}


/*
   putItemIntoList - places an WORD, c, into wlist, l.
*/

extern "C" void wlists_putItemIntoList (wlists_wlist l, unsigned int c)
{
  if (static_cast<wlists_wlist__opaque> (l)->noOfElements < maxNoOfElements)
    {
      static_cast<wlists_wlist__opaque> (l)->noOfElements += 1;
      static_cast<wlists_wlist__opaque> (l)->elements.array[static_cast<wlists_wlist__opaque> (l)->noOfElements-1] = c;
    }
  else if (static_cast<wlists_wlist__opaque> (l)->next != NULL)
    {
      /* avoid dangling else.  */
      wlists_putItemIntoList (static_cast<wlists_wlist> (static_cast<wlists_wlist__opaque> (l)->next), c);
    }
  else
    {
      /* avoid dangling else.  */
      static_cast<wlists_wlist__opaque> (l)->next = static_cast<wlists_wlist__opaque> (wlists_initList ());
      wlists_putItemIntoList (static_cast<wlists_wlist> (static_cast<wlists_wlist__opaque> (l)->next), c);
    }
}


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

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


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

extern "C" unsigned int wlists_getIndexOfList (wlists_wlist l, unsigned int c)
{
  unsigned int i;

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


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

extern "C" unsigned int wlists_noOfItemsInList (wlists_wlist l)
{
  unsigned int t;

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


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

extern "C" void wlists_includeItemIntoList (wlists_wlist l, unsigned int c)
{
  if (! (wlists_isItemInList (l, c)))
    {
      wlists_putItemIntoList (l, c);
    }
}


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

extern "C" void wlists_removeItemFromList (wlists_wlist l, unsigned int c)
{
  wlists_wlist__opaque p;
  unsigned int i;
  bool found;

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


/*
   replaceItemInList - replace the nth WORD in wlist, l.
                       The first item in a wlists is at index, 1.
                       If the index, n, is out of range nothing is changed.
*/

extern "C" void wlists_replaceItemInList (wlists_wlist l, unsigned int n, unsigned int w)
{
  while (l != NULL)
    {
      if (n <= static_cast<wlists_wlist__opaque> (l)->noOfElements)
        {
          static_cast<wlists_wlist__opaque> (l)->elements.array[n-1] = w;
        }
      else
        {
          n -= static_cast<wlists_wlist__opaque> (l)->noOfElements;
        }
      l = static_cast<wlists_wlist> (static_cast<wlists_wlist__opaque> (l)->next);
    }
}


/*
   isItemInList - returns true if a WORD, c, was found in wlist, l.
*/

extern "C" bool wlists_isItemInList (wlists_wlist l, unsigned int c)
{
  unsigned int i;

  do {
    i = 1;
    while (i <= static_cast<wlists_wlist__opaque> (l)->noOfElements)
      {
        if (static_cast<wlists_wlist__opaque> (l)->elements.array[i-1] == c)
          {
            return true;
          }
        else
          {
            i += 1;
          }
      }
    l = static_cast<wlists_wlist> (static_cast<wlists_wlist__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 wlist, l.
*/

extern "C" void wlists_foreachItemInListDo (wlists_wlist l, wlists_performOperation p)
{
  unsigned int i;
  unsigned int n;

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


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

extern "C" wlists_wlist wlists_duplicateList (wlists_wlist l)
{
  wlists_wlist__opaque m;
  unsigned int n;
  unsigned int i;

  m = static_cast<wlists_wlist__opaque> (wlists_initList ());
  n = wlists_noOfItemsInList (l);
  i = 1;
  while (i <= n)
    {
      wlists_putItemIntoList (static_cast<wlists_wlist> (m), wlists_getItemFromList (l, i));
      i += 1;
    }
  return static_cast<wlists_wlist> (m);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

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

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