/* UPDOBSLT.C */
/*--------------------------------------------------------------------*/
/*! Remove obsolete entries from .UPD transaction files               */
/*# Update UNIX                                                       */
/*--------------------------------------------------------------------*/
/*;  Copyright (C) 1995                                               */
/*;  Associated Universities, Inc. Washington DC, USA.                */
/*;                                                                   */
/*;  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 Massachusetts Ave, Cambridge,     */
/*;  MA 02139, USA.                                                   */
/*;                                                                   */
/*;  Correspondence concerning AIPS should be addressed as follows:   */
/*;         Internet email: aipsmail@nrao.edu.                        */
/*;         Postal address: AIPS Project Office                       */
/*;                         National Radio Astronomy Observatory      */
/*;                         520 Edgemont Road                         */
/*;                         Charlottesville, VA 22903-2475 USA        */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/*   Given an AIPS .UPD transaction file sorted by name (primary sort */
/*   key) and date (secondary sort key) and a REMOVE.UPD transaction  */
/*   file sorted by name and date, named as command line arguments 1  */
/*   and 2 respectively, generate a .UPD transaction file with        */
/*   obsolete entries removed.  An obsolete entry is one for which an */
/*   entry with the same name and a later time stamp exists in the    */
/*   REMOVE.UPD file.  The revised transaction file is written to     */
/*   standard output.                                                 */
/*--------------------------------------------------------------------*/

#include <stdio.h>
#ifdef __STDC__
#include <string.h>
#else
#include <strings.h>
#endif

struct UpdRecord {
   char   datestr[12];                 /* Date in the form DD-MMM-YYYY*/
   char   time[9];                     /* Time in the form HH:MM:SS   */
   char   date[9];                     /* Date in the form YYYYMMDD   */
   char   versn[4];                    /* AIPS version                */
   char   area[9];                     /* AIPS area                   */
   char   fname[36];                   /* file name                   */
 };

main(argc, argv)
int argc;
char *argv[];
{
   FILE               *transaction, *remove;
   struct UpdRecord   TransRec, RemoveRec, LastRemoveRec;
   struct UpdRecord   *getrec();
                                     
                                       /* Check command line args     */
   if (argc != 3) {
      fprintf(stderr, "Usage: UPDOBSLT transaction_file remove_file\n");
      exit(1);
      }
   
                                       /* Open files                  */
   if ((transaction = fopen(argv[1], "r")) == NULL) {
      fprintf(stderr, "Can not open file %s\n", argv[1]);
      exit(1);
      }
   if ((remove = fopen(argv[2], "r")) == NULL) {
      fprintf(stderr, "Can not open file %s\n", argv[2]);
      exit(1);
      }

                                       /* Check records in turn      */
    while (getrec(transaction, &TransRec) != NULL) {
       while ((getrec(remove, &RemoveRec) != NULL) && 
          before(&RemoveRec, &TransRec))
	  clone(&RemoveRec, &LastRemoveRec);
                                       /* LastRemoveRec either      */
                                       /* refers to a file other    */
                                       /* than TransRec or has an   */
                                       /* earlier time stamp.       */
       if (!obsolete(&TransRec, &LastRemoveRec))
	  printf("%11s %8s %8s %3s %-8s %s\n", TransRec.datestr,
             TransRec.time, TransRec.date, TransRec.versn,
	     TransRec.area, TransRec.fname);
     }
}

struct UpdRecord *getrec(file, record)
/*--------------------------------------------------------------------*/
/* Read an update record from the given file.  Return a pointer to    */
/* the record if a record was read successfully or return NULL if     */
/* there are no more records to read.                                 */
/*--------------------------------------------------------------------*/
FILE             *file;
struct UpdRecord *record;
{
   char rec[256];

   /* read a line and THEN decode it.  Takes care of extra stuff */

   if (fgets(rec, 255, file) == NULL) {
      return NULL;
   } else {
      if (sscanf(rec, "%11s %8s %8s %3s %8s %s", record->datestr, 
		 record->time, record->date, record->versn, record->area,
		 record->fname) == EOF)
	 return NULL;
      else
	 return record;
   }
}

int before(rec1, rec2)
/*--------------------------------------------------------------------*/
/* Return 1 (true) if the full name (version, area and filename) of   */
/* the file referenced in rec1 comes before that of rec2 in           */
/* alphabetical order or if the file referenced in rec1 is identical  */
/* to that referenced in rec2 and the timestamp in rec1 is earlier    */
/* than that in rec2; otherwise return zero (false).                  */
/*--------------------------------------------------------------------*/
struct UpdRecord *rec1, *rec2;
{
   int ct, cd, cv, ca, cf;
   int r;

   ct = strcmp(rec1->time, rec2->time);
   cd = strcmp(rec1->date, rec2->date);
   cv = strcmp(rec1->versn, rec2->versn);
   ca = strcmp(rec1->versn, rec2->versn);
   cf = strcmp(rec1->fname, rec2->fname);

   if ((cv < 0) || (cv == 0 && ca < 0) || 
      (cv == 0 && ca == 0 && cf < 0) || 
      (cv == 0 && ca == 0 && cf == 0 && cd < 0) ||
      (cv == 0 && ca == 0 && cf == 0 && cd == 0 && ct < 0))
      r = 1;
   else
      r = 0;

   return r;
}

int obsolete(rec1, rec2)
/*--------------------------------------------------------------------*/
/* Return 1 (true) if record 2 obsoletes record 1; otherwise return 0 */
/* (false).  Record 2 should come before record 1 in the ordering     */
/* defined by function before().                                      */
/*--------------------------------------------------------------------*/
struct UpdRecord *rec1, *rec2;
{
   int r;

   if ((strcmp(rec1->versn, rec2->versn) == 0) && 
      (strcmp(rec1->area, rec2->area) == 0) &&
      (strcmp(rec2->fname, rec2->fname) == 0))
      r = 1;
   else
      r = 0;

   return r;
}

int clone(rec1, rec2)
/*--------------------------------------------------------------------*/
/* Make rec2 a copy of rec1.                                          */
/*--------------------------------------------------------------------*/
struct UpdRecord *rec1, *rec2;
{
  strcpy(rec2->datestr, rec1->datestr);
  strcpy(rec2->time, rec1->time);
  strcpy(rec2->date, rec1->date);
  strcpy(rec2->versn, rec1->versn);
  strcpy(rec2->area, rec2->area);
  strcpy(rec2->fname, rec2->fname);
}

