/* -*- Mode: C -*-
 *
 * $Header: /home/gene/library/website/docsrc/nrdl/RCS/nrdl0.c,v 395.1 2008/04/20 17:25:50 gene Exp $
 * 
 * Copyright (c) 2006 Gene Michael Stover.  All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL GENE MICHAEL STOVER BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * Except as contained in this notice, the name of Gene Michael Stover
 * shall not be used in advertising or otherwise to promote the sale, use
 * or other dealings in this Software without prior written authorization
 * from Gene Michael Stover.
 */

/* Standard C */
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* This */
typedef int Boolean;
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!0)
#endif

/*
 */
void *
xmalloc (size_t count)
{
  void *p;

  p = malloc (count);
  if (p == NULL) {
    fprintf (stderr, "\n%s:%d: malloc (%u) failed", __FILE__, __LINE__,
             (unsigned) count);
    abort ();
  }
  return p;
}

/*
 */
static void *
xfree (void *p)
{
  if (p == NULL) {
    fprintf (stderr, "\n%s:%d: Can't free NULL", __FILE__, __LINE__);
    abort ();
  }
  free (p);
  return NULL;
}

/*
 * To use in your own programs, copy-&-paste everything
 * between the "cut here" comment lines.
 */

/* --- cut here --- begin --- cut here --- */
/*
 */
static Boolean
is_good_terminator (FILE *fp, int c, int is_strict, size_t i,
                    size_t max)
{
  return (!is_strict && (c == -1 || c == 0x0A)) ||
    (c == 0x0D && fgetc (fp) == 0x0A);
}

/*
 */
char *
internet_readline (FILE *fp, Boolean is_strict, size_t max)
{
  char *x = NULL;
  int c, i = 0;

  c = fgetc (fp);
  if (c == -1) {
    /*
     * When the input source is already at end-of-file,
     * we return NULL.
     */
    assert (x == NULL);
  } else {
    /*
     * The input is not already empty, so we allocate space &
     * accumulate characters.
     */
    x = (char *) xmalloc (max + 1);
    while (c != -1 && c != 0x0D && c != 0x0A && i < max) {
      x[i++] = c;
      c = fgetc (fp);
    }
    if (is_good_terminator (fp, c, is_strict, i, max)) {
      x[i] = '\0';
    } else {
      /*
       * There was an error, so we ditch the memory we've
       * allocated.  We'll return NULL.
       */
      x = (char *) xfree (x);
    }
  }
  return x;
}
/* --- cut here --- end --- cut here */

/*
 * Null test.  Always succeeds.
 */
static Boolean
S_Test0000 ()
{
  return TRUE;
}

/*
 */
static Boolean
S_BasicTest (Boolean is_strict, size_t max, Boolean is_binary,
             char octets[], size_t octets_len, char *expected[])
{
  Boolean is_good = FALSE;
  char pathname[] = "test.txt";
  FILE *fp;
  size_t i;
  char *line;

  /* Create the input file */
  fp = fopen (pathname, "wb");
  if (fp != NULL) {
    if (octets_len == 0 || fwrite (octets,
                                   octets_len * sizeof octets[0],
                                   1, fp) == 1) {
      is_good = TRUE;
    } else {
      printf ("\n");
      perror ("fwrite");
      printf ("%s:%d:", __FILE__, __LINE__);
      printf (" Did not write the list of %u octets", octets_len);
      printf (" to the temporary file.");
      is_good = FALSE;
    }
    fclose (fp);
  } else {
    printf ("\n");
    perror ("fopen");
    printf ("%s:%d:", __FILE__, __LINE__);
    printf (" Could not create the temorary file, %s.", pathname);
    is_good = FALSE;
  }
  if (is_good) {
    /* Read the input file. */
    fp = fopen (pathname, is_binary ? "rb" : "r");
    if (fp != NULL) {
      i = 0;
      line = internet_readline (fp, is_strict, max);
      while (line != NULL && expected[i] != NULL &&
             strcmp (expected[i], line) == 0) {
        line = (char *) xfree (line);
        ++i;
        line = internet_readline (fp, is_strict, max);
      }
      is_good = expected[i] == NULL && line == NULL;
      if (line != NULL) {
        line = (char *) xfree (line);
      }
      fclose (fp);
    } else {
      printf ("\n");
      perror ("fopen");
      printf ("\n%s:%d:", __FILE__, __LINE__);
      printf (" Could not open %s to read from it.", pathname);
      is_good = FALSE;
    }
  }
  if (is_good) {
    remove (pathname);
  } else {
    /*
     * There was an error, so we don't delete the temporary
     * file.  It might be useful to inspect it later.
     */
  }
  return is_good;
}

/*
 */
#define entry(test) { &test, #test }
static struct {
  int (*fn) ();
  char *name;
} S_a[] = {
  entry (S_Test0000),
  { NULL, NULL }
};
static size_t S_alen = sizeof S_a / sizeof S_a[0];

int
main ()
{
  int rc = 0;
  size_t i;

  for (i = 0; rc == 0 && S_a[i].fn != NULL; ++i) {
    printf ("\n%3d%% %s =>", i * 100 / (S_alen - 1),
            S_a[i].name);
    if ((*S_a[i].fn) ()) {
      printf (" good");
    } else {
      printf (" FAIL");
      rc = 2057;
    }
  }
  printf ("\n");
  return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

/* --- end of file --- */
