/************************************************************
 * LinkList.c - an example of dynamic memory allocation and *
 *              of Linked Lists.                            *
 *                                                          *
 * Compiled Using: Lattice 4.0                              *
 *                                                          *
 * By Tom Krotchko for Jumpdisk                             *
 ************************************************************/
#include <stdio.h>
#include <stdlib.h>

/* this will be the template for our linked list */
struct Entry {
 struct Entry *next;
 char text[80];
};

struct Entry *start_of_list, *next_in_list, *free_ptr;
char input_text[80];
int done, entry_count;
     
void main() {
   
while(1) {
   printf("\nBegin new group...\n");

   /* Allocate a block of memory for the start of the list */
   start_of_list = (struct Entry *)
         malloc ( sizeof (struct Entry));

   /* Always check the memory allocation for success */
   if (start_of_list == NULL) {
      printf("Initial memory allocation failed. Exiting.\n");
      exit(99);
   } 

   done = 0;
   entry_count = 0;

   /* Make sure the next pointer points to NULL to indicate that this is the end
      of the list. */
   start_of_list->next = NULL;

   next_in_list = start_of_list;

   printf("Press ENTER to exit.\n");

   while(1) {
      printf("Enter a text string: ");

      /* Check for a NULL (carriage return with nothing entered) to indicate the
         user wishes to exit this portion and print the list */
      if(gets(input_text) == NULL) break;
      if(input_text[0] == '\0') break;

      /* Copy the entered text to an item in our linked list */
      strcpy(next_in_list->text,input_text);

      /* Now add a new entry in our linked list, returning the next_in_list
         that points to our newly allocated entry */
      next_in_list = add_entry(next_in_list);
   } 

   /* Check if the user wishes to exit */
   if (entry_count == 0) break;

   /* If they entered something, print it out */
   print_entry(start_of_list); 
}

} /* end of main() */

add_entry (list_ptr)
struct Entry *list_ptr;

{
   /* Look for the end of the linked list to add a new pointer. Note that it isn't
      necessary in this example, but always a good practice to assume that the
      calling function didn't send us the end of the list pointer */
   while (list_ptr->next != (struct Entry *) NULL)
         list_ptr = list_ptr->next;

   /* Add the new pointer to the end of the list */
   list_ptr->next = (struct Entry *)
           malloc ( sizeof (struct Entry));

   if (list_ptr->next != (struct Entry *) NULL)
      (list_ptr->next)->next = (struct Entry * ) NULL;
    else
      printf("bad allocation.\n");

   return (list_ptr->next);
}


print_entry (list_ptr)
struct Entry *list_ptr;
{
   printf("\n\nTEXT LIST...\n");

   /* This loops until the end of the linked list is found */
   while (list_ptr->next != (struct Entry *) NULL) {
    printf("%s\n",list_ptr->text);

    /* Free every area that was allocated after printing */
    free_ptr = list_ptr;
    free( (char *) free_ptr);

    /* Get the next pointer and loop */
    list_ptr = list_ptr->next;
   }
}
