/****************************************************************
 *								*
 *	This include was written to be able to use		*
 *								*
 *		LINKED LISTS					*
 *								*
 *								*
 *==============================================================*
 *	Author	Date	Comment					*
 *	Jos Horemans	From the book 'De C Taal', Jos Horemans *
 *			(place:) Geel, Cipal Institue 1989	*
 *	KvGend	06Jun91	typed it in, corrected a BIG BUG.	*
 *			rewrote half of the routines, added:	*
 *			-opruimen()  -> cleanup			 *
 *			-makeinfo()  -> create a INFO_T structure*
 *			-gimmelinnr() ->return the address of the*
 *					INFO_T structure	*
 *								*
 *								*
 ****************************************************************/

#define MALLOC(x)  ((x*) malloc(sizeof(x)))
#define BOOLEAN int
#define TRUE 1
#define FALSE 0

struct info
{
  int linnr;
  int token;
  char *string;
};
typedef struct info INFO_T;
struct node
{
  INFO_T *item;
  struct node *next;
};
typedef struct node NODE_T;
struct head
{
  int length;
  NODE_T *first;
  NODE_T *last;
};
typedef struct head HEAD_T;

/************** create the head of a linked list */
HEAD_T *
create ()
{
  HEAD_T *newh = NULL;
  if (newh = MALLOC (HEAD_T))
    {
      newh->length = 0;
      newh->first = newh->last = NULL;
    }
  return (newh);		/* if no mem exists, then return NULL */
}

/*************** create a new node */
NODE_T *
inst_node (INFO_T * val, NODE_T * ptr)
{
  NODE_T *new = NULL;
  if (new = MALLOC (NODE_T))
    {
      new->item = val;
      new->next = ptr;
    }
  return (new);
}

/********* insert an item at the end of a list */
BOOLEAN
append (INFO_T * data, HEAD_T * list)
{
  NODE_T *new = NULL;
  if (new = inst_node (data, NULL))
    {
      if (list->length)
	list->last->next = new;	/*set the 'next' of the previous one*/
      else
	list->first = new;
      list->last = new;
      list->length++;
      return (TRUE);
    }
  return (FALSE);
}

/*
 *******************************makeinfo(int linnr,int tok, char *str)***
 */
INFO_T *
makeinfo (int linnr, int tok, char *str)
{
  char *newstr = NULL;
  INFO_T *newi = NULL;
  int i;

  newi = MALLOC (INFO_T);	/* geheugen alloceren voor INFO_T */
  newstr = (char *) malloc (strlen (str) + 1);	/* alloc mem for string  */
  if (newi && newstr)
    {
      /* de INFO opzetten */
      newi->linnr = linnr;
      newi->token = tok;
      newi->string = newstr;
      /* en de string copieren */
      for (i = 0; i < strlen (str); i++)
	newstr[i] = str[i];
      newstr[i] = '\0';
    }
  if (!newstr && newi)		/* no mem for newstr, but there was for newi */
    {
      free (newi);
      newi = NULL;
    }
  return (newi);
}


/*
 **************************************opruimen(HEAD_T koppie)***********
 */
BOOLEAN
opruimen (HEAD_T * koppie)
{
  int i;
  NODE_T *nod, *nod2;
/* van voorafaan beginnen */
  nod = koppie->first;
  for (i = 0; nod != NULL; i++)
    {
      free (nod->item->string);	/* ruim string op */
      free (nod->item);		/*ruim INFO_T op */
      nod2 = nod->next;
      free (nod);		/* ruim NODE_T op */
      nod = nod2;
    }
  koppie->first = NULL;
  koppie->last = NULL;
  return (TRUE);		/* geslaagd ! */
}

/*
 ************************************gimmelinnr(HEAD_T *kop,linenr)*****
 */
INFO_T *
gimmelinnr (HEAD_T * kop, linenr)
{
  NODE_T *nod;

/* start at the beginning */
  nod = kop->first;

/* search whole stuff through */
  while (nod->item->linnr != linenr && nod != NULL)
    nod = nod->next;

/* got 'em ? */
  if (nod->item->linnr == linenr)
    return (nod->item);

/* OH NO , linenr was not in the list.*/
  return (NULL);
}
