/*===========================================================================
  Copyright (C) 1995-2009 European Southern Observatory (ESO)
 
  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 ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++
.IDENTIFICATION tctold.c
.LANGUAGE       C
.AUTHOR         ESO-IPG, Garching (Francois Ochsenbein)
.ENVIRONMENT    Midas
.KEYWORDS       Forward Compatibility
.VERSION  1.0   07-Dec-1990
.COMMENTS       Modifies a Table to go back to Version 0
\begin{TeX}
	This routine is just temporary. 
	Please delete when it's not necessary to go back to
	old Table System...
\end{TeX} 

.VERSION

 090406		last modif
---------------*/

#include <midas_def.h>		/* General MIDAS Symbols	*/
#include <tblsys.h>		/* Table System parameters	*/
#include <tbldef.h>		/* Symbols used for Tables	*/
#include <tblerr.h>		/* List of Table Errors		*/

#include <macrogen.h>		/* Classical macros		*/
#include <atype.h>		/* Character classification 	*/

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



	/* Mnemonics for some operations */
	
#define OnError_Continue    {	int flags[3];	\
				SCECNT("GET", flags, flags+1, flags+2);\
				SCECNT("PUT", &one,   flags+1, &zero);
#define OnError_Reset 				\
				SCECNT("PUT", flags, flags+1, flags+2);\
			    }


/*=======================================================================
 *		Conversion of NULL values from old to New
 *=======================================================================*/

#ifdef __STDC__
static int convert_nulls(TABLE *tp)
#else
static int convert_nulls(tp)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE  Change NULL values to MAX Values
.METHOD   Assume that table is MAPPED.
.RETURNS  Number of Modified Columns
>REMARKS  The dtypes array ia already changed to OLD values.
------------------------------------------------------------------*/
	TABLE	*tp;	/* MOD: Table concerned	*/
#endif
{
	int	i, j, di, o, cols;
	char	*pv;
	float	fnull, fmax;
	double	dnull, dmax;

  TBL_toMAX ((TBL_D_R4<<TBL_D_BITS)|1, (char *)&fmax );
  TBL_toNULL((TBL_D_R4<<TBL_D_BITS)|1, (char *)&fnull);
  TBL_toMAX ((TBL_D_R8<<TBL_D_BITS)|1, (char *)&dmax );
  TBL_toNULL((TBL_D_R8<<TBL_D_BITS)|1, (char *)&dnull);
  cols = 0;
  for (j = 0; j < tp->cols; j++) {
	if (tp->swise == F_TRANS)
		o = tp->offset[j] * tp->arows, di = tp->bytes[j];
	else	o = tp->offset[j],		di = tp->reclen;

	switch(tp->dtypes[j]) {
	  default:		continue;
	  case -4:
		cols++;
		for (pv = tp->addres + o, i = tp->arows; --i >= 0; pv += di) {
			if (*((float *)pv) == fnull)	*(float *)pv = fmax;
		}
		break;
	  case -8:
		cols++;
		for (pv = tp->addres + o, i = tp->arows; --i >= 0; pv += di) {
			if (*((double *)pv) == fnull)	*(double *)pv = dmax;
		}
		break;
	}
  }
  return(cols);
}

/*=======================================================================
 *		Public Routines
 *=======================================================================*/

int TCTOLD(name)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Reformat a Table to Reconvert to Version 0
.RETURNS Status e.g. ERR_TBLRFM
.REMARKS In case of error, table is NOT modified.
------------------------------------------------------------------*/
	char 	*name;	/* IN: Table To Modify */
{
	int	tid;	/* IN: Table to Modify */
	TABLE	*tp;	
	int	status, i, j, o, dtype, items;
	char	buf[12];

                                                /*   check argument     */
  if ((status = TCTOPN(name, F_MAP_FORCE|F_IO_MODE, &tid)))
	return(status);

  tp = TBL_ptr(tid);
  if ((status = CheckTable(tp)))          return(TBL_errs(tid, status,0));

  if (tp->version == 0) {	/* It's already OLD ... */
	SCTPUT("++++ Your Table is already an old timer ... ");
	return(ERR_TBLRFM);
  }

	/* Check First if it's possible to Convert Back the table.
 	   For this, we must check that:
	   => All offsets (TBLOFFST descriptor) are consecutive and aligned
	   => No array
 	   => No I*2 I*1 
	*/
  
  o = 4;
  for (j=0; j < tp->cols; j++) {
	dtype = tp->dtypes[j] >> TBL_D_BITS;
	items = tp->dtypes[j] &  TBL_D_MASK;
	if ((items > 1) && (dtype != TBL_D_A1)) {
		status = ERR_TBLRFM;
		TBL_errf(status, 
			"Arrays (Column #d) not supported in old version", j);
		break;
	}
	if ((dtype != TBL_D_A1) && ((dtype & 010) == 0)) {
		status = ERR_TBLRFM;
		TBL_errf(status, 
			"Datatype (Column #d) not supported in old version", j);
		break;
	}
	if (tp->offset[j] != o)	{
		status = ERR_TBLRFM;
		TBL_errf(status, 
			"Column #d can't be converted to old version", j);
		break;
	}
	if (dtype == TBL_D_A1)	o += items;
	else	o += 1 << (dtype&3);
	if (o&3)	o = (o+3) & ~3;		/* Convert to multiple of 4 */

	switch(dtype) {
	  case TBL_D_R4: 	tp->dtypes[j] =  -4; break;
	  case TBL_D_R8: 	tp->dtypes[j] =  -8; break;
	  case TBL_D_I1: 	tp->dtypes[j] = -11; break;
	  case TBL_D_I2: 	tp->dtypes[j] = -12; break;
	  case TBL_D_I4: 	tp->dtypes[j] = -14; break;
	}
  }
  if (status)	return(status);

	/* Conversion is Possible. 
	   We've to modify the Labels, and the NULL values.
	*/

  for (j=0; j < tp->cols; j++) {
	if ((status = GetLabel(tp, j+1, 33, 9, buf)))	break;
        dtype = tp->dtypes[j] >> TBL_D_BITS;
	sprintf(buf+6, "%3d", atoi(buf+1));	/* Exists in Old Version... */
	buf[0] = toupper(buf[0]);
	switch(buf[0]) {	/* Just take I or F Formats */
	  case 'T': case 'O': case 'X': case 'Z': case 'R': case 'S':
		for (i=1; isdigit(buf[i]); i++);
		buf[0] = (buf[i] == '.' ? 'F' : 'I');
	}
	if ((status = PutLabel(tp, j+1, buf, 33, 9)))	break;
  }
  if (status)	return(status);
  tp->version = 0;
  tp->selected = -1;
 
		/* Modify NULL values */
  convert_nulls(tp);
  tp->tflags |= (TBL__MODIFIED | TBL__KEEPVERS);

		/* Finally, Close Table */
  status = TCTCLO(tid);
  return(status);
}
