/* mailutil.c
   Copyright (C) 1995-1996 Eberhard Mattes

This file is part of GNU Emacs.

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

GNU Emacs 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 Emacs; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "mailutil.h"


void out_of_mem (void)
{
  fprintf (stderr, "Out of memory\n");
  exit (EX_OSERR);
}


void *xmalloc (size_t size)
{
  void *p;

  p = malloc (size);
  if (p == NULL) out_of_mem ();
  return (p);
}


void slist_init (struct slist *list)
{
  list->first = NULL;
  list->add = &list->first;
}


void slist_add (struct slist *list, const char *str)
{
  struct snode *node;

  node = xmalloc (sizeof (*node));
  node->next = NULL;
  node->str = strdup (str);
  if (node->str == NULL) out_of_mem ();
  *list->add = node;
  list->add = &node->next;
}


#define PUT(X) \
    if (len >= line_size) \
      { \
        line_size += 512; \
        line = realloc (line, line_size); \
        if (line == NULL) {errno = ENOMEM; return (EX_NOMEM);} \
      } \
    line[len++] = (X)

int read_line (FILE *f, int flags, char **result)
{
  static char *line = NULL;
  static int line_size = 0;
  int c, len, done;

  len = 0; done = 0; *result = 0;
  while (!done)
    {
      c = getc (f);
      switch (c)
        {
        case '\r':
          break;
        case '\n':
        case EOF:
          done = 1;
          break;
        case 0x1a:
          if ((flags & RL_CTRLZ_EOF) && len == 0)
            return (EX_EOF);
          /* fall through */
        default:
          PUT (c);
          break;
        }
    }
  if (ferror (f))
    return (EX_IOERR);
  if (c == EOF && len == 0)
    return (EX_EOF);
  PUT (0);
  *result = line;
  return (EX_OK);
}
