/* listss: test recursive printing of linked lists */
#include <stdio.h>
#include <stdlib.h>

struct snode {           /* self-referential struct */
   char c;               /* char field */
   struct snode *next;   /* pointer to same kind of struct */
};

char pop(void);                         /* pop an item. */
void push(char);                        /* push an item. */
int empty(void);                        /* check if empty */
int full(void);                         /* check if full (never is) */
void printstack(struct snode *);        /* print in top-down order */
void printstackrecurs(struct snode *);  /* print recursively top town */
void printstackreverse(struct snode *); /* print recursively bottom up */

struct snode *s = NULL;  /* global variable for simplicity */

void main(void)
{
   char ch;
   struct snode *t;
   while ((ch = getchar()) != '\n' && !full()) { /* read a line */
      push(ch);
   }
   printstack(s); putchar('\n');
   printstackrecurs(s); putchar('\n');
   printstackreverse(s); putchar('\n');
   for (t = s; t != NULL; t = t -> next)
      putchar(t -> c);
   putchar('\n');
}

/* pop: pop the linked list stack (remove from front) */
char pop(void)
{
   char ch;
   struct snode *ssave;
   if (empty()) {
      fprintf(stderr, "Stack underflow\n");
      exit(1);
   }
   ch = s -> c;
   ssave = s;
   s = s -> next;
   free(ssave);
   return ch;
}

/* push: push onto the linked list stack (add at front) */
void push(char ch)
{
   struct snode *t = (struct snode *)
      malloc(sizeof(struct snode));
   if (t == NULL) {
      fprintf(stderr, "Allocation failed\n");
      exit(1);
   }
   t -> next = s;
   t -> c = ch;
   s = t;
}

/* empty: NULL pointer indicates empty stack */
int empty(void)
{
   return s == NULL;
}

/* full: stack is only full if storage gives out */
int full(void)
{
   return 0;
}

/* printstack: chase down stack, printing as you go */
void printstack(struct snode *s)
{
   while (s != NULL) {  /* standard while loop */
      putchar(s -> c);
      s = s -> next;
   }
}

/* printstackrecurs: chase down stack and print, but recursively */
void printstackrecurs(struct snode *s)
{
   if (s != NULL) {  /* Note: no loop, just an if */
      putchar(s -> c);
      printstackrecurs(s -> next);
   }
}

/* printstackreverse: chase down stack and chase again recursively, */
/*    before printing */
void printstackreverse(struct snode *s)
{
   if (s != NULL) {  /* Note: no loop, just an if */
      printstackreverse(s -> next);
      putchar(s -> c);
   }
}

