/* seektext.c (emx+gcc) */

/* Test fseek() for text-mode streams.  This program assumes that
   newline is represented by CR and LF in files and that fseek() uses
   the file positions of the underlying binary file.  That assumption
   is not portable. */

#include <stdio.h>
#include <stdlib.h>

/* This constant should not be equal to sizeof (temp). */

#define JUMP    31


static FILE *inp_file;
static const char *inp_fname;
static char *buf;
static long length;


static void seek_test (long pos)
{
  char temp[16];
  long n;
  int k1, k2;

  if (!(pos > 0 && buf[pos-1] == '\r' && buf[pos] != '\n'))
    {
      if (fseek (inp_file, pos, SEEK_SET) != 0)
        {
          perror (inp_fname);
          exit (2);
        }
      n = length - pos;
      if (n > sizeof (temp))
        n = sizeof (temp);
      n = fread (temp, 1, (size_t)n, inp_file);
      if (n == 0)
        {
          if (ferror (inp_file))
            perror (inp_fname);
          else
            fprintf (stderr, "fread() failed at %ld\n", pos);
          exit (2);
        }
      k1 = k2 = 0;
      while (n > 0)
        {
          if (buf[pos+k1] == '\r')
            ++k1;
          if (buf[pos+k1] != temp[k2])
            break;
          --n; ++k1; ++k2;
        }
      if (n != 0)
        {
          fprintf (stderr, "fseek() mismatch at %ld+%d\n", pos, k1);
          exit (2);
        }
    }
}


static void usage (void)
{
  fprintf (stderr, "Usage: seektext <input_file>\n");
  exit (1);
}


int main (int argc, char *argv[])
{
  long pos1, pos2;

  if (argc != 2)
    usage ();

  inp_fname = argv[1];

  inp_file = fopen (inp_fname, "rb");
  if (inp_file == NULL)
    {
      perror (inp_fname);
      exit (2);
    }

  fseek (inp_file, 0L, SEEK_END);
  length = ftell (inp_file);
  if (length == -1)
    {
      perror (inp_fname);
      exit (2);
    }
  buf = malloc ((size_t)length);
  if (buf == NULL)
    {
      fprintf (stderr, "Out of memory\n");
      exit (2);
    }
  rewind (inp_file);
  if (fread (buf, 1, (size_t)length, inp_file) != length)
    {
      if (ferror (inp_file))
        perror (inp_fname);
      else
        fprintf (stderr, "fread() failed\n");
      exit (2);
    }

  if (freopen (inp_fname, "r", inp_file) == NULL)
    {
      perror (inp_fname);
      exit (2);
    }

  for (pos1 = 0; pos1 < JUMP; ++pos1)
    for (pos2 = pos1; pos2 < length; pos2 += JUMP)
      seek_test (pos2);

  srandom (1);
  for (pos1 = 0; pos1 < length; ++pos1)
    {
      pos2 = random () % length;
      seek_test (pos2);
    }
  fclose (inp_file);
  return 0;
}
