/*
 *  Unique - Report repeated lines in input.
 *  Copyright (C) 1989, 1992, 1993 Torsten Poulin
 *
 *  This program 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 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  The author can be contacted by s-mail at
 *    Torsten Poulin
 *    Banebrinken 99, 2, 77
 *    DK-2400 Copenhagen NV
 *    DENMARK
 *
 * $Id: Unique.c,v 37.7 93/06/20 17:14:14 Torsten Rel $
 * $Log:	Unique.c,v $
 * Revision 37.7  93/06/20  17:14:14  Torsten
 * SysBase removed.
 * Removed unsupported items from the template so as not
 * to confuse "lusers".
 * 
 * Revision 37.6  93/03/01  12:31:13  Torsten
 * Changed all occurrences of "struct DosBase *" to "struct DosLibrary *"
 * 
 * Revision 37.5  93/02/18  15:35:21  Torsten
 * Replaced explicit Stricmp() pragma and prototype with the
 * relevant include files.
 * 
 * Revision 37.4  93/02/14  10:49:48  Torsten
 * Replaced exec.library/SetSignal() with dos.library/CheckSignal().
 * Fixed "line repeated more than once" bug.
 * 
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <stdio.h>
#include <string.h>
#include "unique_rev.h"

#ifdef __SASC
#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/utility_pragmas.h>
#endif

#define PROGNAME "Unique"
#define MAXLINE (512+1)
#define MAXNAME 50
#define TEMPLATE "FROM,TO,REPEATED/S,UNIQUE=ONCE/S,COUNT/S"

#define OPT_FROM   0
#define OPT_TO     1
#define OPT_REPEAT 2
#define OPT_UNIQUE 3
#define OPT_COUNT  4

char const versionID[] = VERSTAG;
char const copyright[] = "$COPYRIGHT:© 1989,1992,1993 Torsten Poulin$";

static BOOL ioerr(struct DosLibrary *DOSBase);
static LONG unique(struct DosLibrary *DOSBase,
                   struct Library *UtilityBase, BPTR in, BPTR out,
                   BOOL rflag, BOOL uflag, BOOL cflag);

LONG entrypoint(VOID)
{
  BPTR in, out;
  ULONG err;
  LONG rc = RETURN_OK;
    
  struct DosLibrary *DOSBase;
  struct Library *UtilityBase;
  struct RDArgs  *args;
  LONG           arg[5];
        
  if (!(DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37L)))
  {
    rc = RETURN_FAIL;
    goto noDOS;
  }
  if (!(UtilityBase = OpenLibrary("utility.library", 37L)))
  {
    rc = RETURN_FAIL;
    goto noUtility;
  }
    
  arg[OPT_FROM] = arg[OPT_TO] = 
    arg[OPT_REPEAT] = arg[OPT_UNIQUE] = arg[OPT_COUNT] = 0L;
    
  if (args = ReadArgs(TEMPLATE, arg, NULL))
  {
    if (arg[OPT_FROM])
    {
      if (!(in = Open((UBYTE *) arg[OPT_FROM], MODE_OLDFILE)))
      {
	err = IoErr();
	PrintFault(err, (UBYTE *) arg[OPT_FROM]);
	rc = RETURN_ERROR;
	goto errExit;
      }
    }
    else
      in = Input();

    if (arg[OPT_TO])
    {
      if (!(out = Open((UBYTE *) arg[OPT_TO], MODE_NEWFILE)))
      {
	err = IoErr();
	PrintFault(err, (UBYTE *) arg[OPT_TO]);
	rc = RETURN_ERROR;
	goto errExit;
      }
    }
    else
      out = Output();
        
    rc = unique(DOSBase, UtilityBase, in, out,
		(BOOL) arg[OPT_REPEAT],
		(BOOL) arg[OPT_UNIQUE],
		(BOOL) arg[OPT_COUNT]);

    if (arg[OPT_FROM])
      Close(in);
    if (arg[OPT_TO])
      Close(out);

    FreeArgs(args);
  }
  else
  {
    LONG err = IoErr();
    PrintFault(err, PROGNAME);
    rc = RETURN_ERROR;
  }
    
 errExit:
  CloseLibrary(UtilityBase);
 noUtility:
  CloseLibrary((struct Library *) DOSBase);
 noDOS:
  return rc;
}


static LONG unique(struct DosLibrary *DOSBase,
                   struct Library *UtilityBase, BPTR in, BPTR out,
                   BOOL rflag, BOOL uflag, BOOL cflag)
{
  ULONG count;
  UBYTE prevline[MAXLINE];
  UBYTE nextline[MAXLINE];
  UBYTE *temp;
  UBYTE *prev = prevline;
  UBYTE *next = nextline;
    
  if (rflag && uflag)
    rflag = uflag = FALSE;

  count = 1;
  if (FGets(in, prev, MAXLINE) == NULL)
  {
    if (ioerr(DOSBase))
      return RETURN_FAIL;
  }
  else
  {
    while (FGets(in, next, MAXLINE) != NULL)
    {

      if (Stricmp(prev, next) == 0)
	++count;
      else if ((!rflag && !uflag) ||
	       (count >= 2 && !uflag) ||
	       (count == 1 && uflag))
      {
	if (cflag)
	  VFPrintf(out, "%10lu ", (LONG *) &count);
	FPuts(out, prev);
	count = 1;
      }
      else
	count = 1;
      temp = prev;
      prev = next;
      next = temp;

      if (CheckSignal(SIGBREAKF_CTRL_C))
      {
	PrintFault(ERROR_BREAK, NULL);
	return RETURN_WARN;
      }
    }
    if (ioerr(DOSBase))
      return RETURN_FAIL;

    if ((!rflag && !uflag) || (count >= 2 && !uflag)
	|| (count == 1 && uflag))
    {
      if (cflag)
	VFPrintf(out, "%10lu ", (LONG *) &count);
      FPuts(out, prev);
    }
  }
  return RETURN_OK;
}


static BOOL ioerr(struct DosLibrary *DOSBase)
{
    LONG err;
    
    if (!(err = IoErr()))
        return FALSE;
    PrintFault(err, PROGNAME);
    return TRUE;
}
