/* @(#)create_full_ordertable.c */
/*===========================================================================
  Copyright (C) 2001 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 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding 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
  ===========================================================================*/

/*-------------------------------------------------------------------------*/
/**
 * @defgroup flames_full_ordertable   Add to an order-fibre table entries for ALL fibres-orders
 *
 */
/*-------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------
  Includes
  --------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <flames_create_full_ordertable.h>
#include <flames_striptblext.h>

#include <flames_def_drs_par.h>
#include <flames_midas_tblerr.h>
#include <flames_midas_tbldef.h>
#include <flames_midas_macrogen.h>
#include <flames_midas_atype.h>
#include <flames_midas_def.h>
#include <flames_uves.h>
#include <flames_freeordpos.h>
#include <flames_getordpos.h>
#include <uves_msg.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <flames_readordpos.h>
/*---------------------------------------------------------------------------
  Defines
  ---------------------------------------------------------------------------*/

#define MAXPOINTERSTOFREE 1000

/**@{*/

/*---------------------------------------------------------------------------
  Implementation
  ---------------------------------------------------------------------------*/
/**
   @name  flames_create_full_ordertable()  
   @short Add to an order-fibre table entries for ALL fibres-orders           
   @author G. Mulas  -  ITAL_FLAMES Consortium. Ported to CPL by A. Modigliani


   @param INORDTAB    User-defined name of the input order table        
   @param OUTORDTAB    Order-fibre table with missing order-fibres added     
   @param STEPX        Step to use when scanning over x's                   
                                                               
   @return 0 if success

                                                                         
   DRS Functions called: none                                             
                                                                        
   Pseudocode:                                                            
   Initialize an order table                                           

   @note
*/



int 
flames_create_full_ordertable(
			      const char *INORDTAB,
			      const char *OUTORDTAB,
			      double *STEPX)
{
  char tempordtab[CATREC_LEN+5];
  char inordtab[CATREC_LEN+5];
  int intid=0;
  char outordtab[CATREC_LEN+5];
  int outtid=0;
  orderpos *ordpos;

  char **pointerstofree;
  int32_t npointerstofree=0;
  double stepx=0;
  int stepix=0;
  int actvals=0;
  int unit=0;
  int null=0;
  char output[160];
  int i=0;
  int inordercol=0;
  int infibrecol=0;
  int inxcol=0;
  int inycol=0;
  int inordfibcol=0;
  int inyfitcol=0;
  int inresidcol=0;
  int incols=0;
  int inrows=0;
  //  int instore=0;
  int *indtype=0;
  int *initems=0;
  int *inbytes=0;
  int *outcol=0;
  int inrow=0;
  int incol=0;
  char inform[20];
  char inunit[80];
  char inlabel[80];
  int *ibuffer=0;
  float *fbuffer=0;
  double *dbuffer=0;
  char *cbuffer=0;
  int outordercol=0;
  int outfibrecol=0;
  int outxcol=0;
  int outycol=0;
  int outordfibcol=0;
  int outyfitcol=0;
  int outresidcol=0;
  int outrows=0;
  int outcols=0;
  int ifibre=0;
  int iorder=0;
  int found=0;
  int order=0;
  int fibre=0;
  int ix=0;
  double dx=0;
  double ordercentre=0;
  float fibrecentre=0;
  float fx=0;
  int outrow=0;
  char orderfibre[20];
  int size=0;

  memset(inordtab, 0, CATREC_LEN+5);
  memset(outordtab, 0, CATREC_LEN+5);
  memset(tempordtab, 0, CATREC_LEN+5);
  memset(output, 0, 160);
  memset(inform, 0, 20);
  memset(inlabel, 0, 80);
  memset(inunit, 0, 80);

  SCSPRO("create_full_ordertable");

  if ((pointerstofree = (char **) calloc(MAXPOINTERSTOFREE, sizeof(char *)))
      == NULL) {
    SCTPUT("Error allocating pointerstofree in create_full_ordertable");
    return flames_midas_fail();
  }
  else {
    pointerstofree[0] = (char *) pointerstofree;
    npointerstofree++;
  }

  if ((SCKGETC(INORDTAB, 1, CATREC_LEN+4, &actvals, tempordtab)!=0) ||
      (actvals==0)) {
    SCTPUT("Error reading INORDTAB in create_full_ordertable()");
    return flames_midas_fail();
  }

  if (striptblext(tempordtab, inordtab) != NOERR) {
    SCTPUT("Error: bad input table name");
    return flames_midas_fail();
  }

  memset(tempordtab, 0, CATREC_LEN+5);
  if((SCKGETC(OUTORDTAB, 1, CATREC_LEN+4, &actvals, tempordtab)!=0) ||
     (actvals==0)) {
    SCTPUT("Error reading OUTORDTAB in create_full_ordertable()");
    return flames_midas_fail();
  }

  if (striptblext(tempordtab, outordtab) != NOERR) {
    SCTPUT("Error: bad output table name");
    return flames_midas_fail();
  }

  if ((SCKRDD(STEPX, 1, 1, &actvals, &stepx, &unit, &null)!=0) ||
      (actvals==0)) {
    SCTPUT("Error reading stepx in create_full_ordertable()");
    return flames_midas_fail();
  }
  if (stepx==0) {
    SCTPUT("Error: STEPX must be non zero");
    return flames_midas_fail();
  }

  /* allocate the order structure */
  if ((ordpos = (orderpos *) calloc (1, sizeof(orderpos)))==NULL) {
    SCTPUT("Error allocating ordpos in create_full_ordertable");
    return flames_midas_fail();
  }
  pointerstofree[npointerstofree] = (char *) ordpos;
  npointerstofree++;

  /* read the old order-fibre structure from the old order-fibre table */
  if (readordpos(inordtab, ordpos) != NOERR) {
    sprintf(output, "Error reading %s order-fibre table", inordtab);
    SCTPUT(output);
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }
  stepix = (int) floor(fabs(stepx/ordpos->step[0]));
  if (stepix==0) {
    SCTPUT("Warning: STEPX is smaller than STEP(1) in the frame, \
overriding it");
    stepix = 1;
  }

  /* open the input table */
  if (TCTOPN(inordtab, F_IO_MODE, &intid) != 0) {
    sprintf(output, "Error opening table %s", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  if ((TCCSER(intid, "ORDER", &inordercol)!=0) || (inordercol==-1)) {
    sprintf(output, "Error searching ORDER column in %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  if ((TCCSER(intid, "FIBRE", &infibrecol)!=0) || (infibrecol==-1)) {
    sprintf(output, "Error searching FIBRE column in %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  if ((TCCSER(intid, "X", &inxcol)!=0) || (inxcol==-1)) {
    sprintf(output, "Error searching X column in %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  if ((TCCSER(intid, "Y", &inycol)!=0) || (inycol==-1)) {
    sprintf(output, "Error searching Y column in %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  if ((TCCSER(intid, "ORDERFIB", &inordfibcol)!=0) || (inordfibcol==-1)) {
    sprintf(output, "Error searching ORDFIB column in %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  if ((TCCSER(intid, "YFIT", &inyfitcol)!=0) || (inyfitcol==-1)) {
    sprintf(output, "Error searching YFIT column in %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  if ((TCCSER(intid, "RESIDUAL", &inresidcol)!=0) || (inresidcol==-1)) {
    sprintf(output, "Error searching RESIDUAL column in %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  /* how large is the input table? */
  if (TCIGET(intid, &incols, &inrows)
      !=0) {
    sprintf(output, "Error reading size of %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
      SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
  }

  /* are the input and output table the same file? */

  //  if ((outtid = TCTID(outordtab)) == -1) {
  //jmlarsen: always create the outordtab, also if the file exists
  if (1) {
  

    /* the output table is a different file, we create it
       from scratch and populate it */
    /* read the format on disk of the input table, so that we can create the 
       output table in the same storage format */

    /* jmlarsen: we don't need to know the storage

    if (TCDGET(intid, &instore) != 0) {
    sprintf(output, "Error reading storage type of %s table", inordtab);
    SCTPUT(output);
    if (freeordpos(ordpos)!=NOERR) {
    SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
    }
    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
    return flames_midas_fail();
    }
    */
    /* create the output table with the same characteristics */

    //jmlarsen: We changed the interface of this function, but we still
    //want to allocate more rows than in the input table. Therefore
    //use 'MAXROWS' instead of 'inrows'
    //    if (TCTINI(outordtab, F_O_MODE, inrows, &outtid)
    if (TCTINI(outordtab, F_O_MODE, MAXROWS, &outtid)  !=0) {
      sprintf(output, "Error creating %s table", outordtab);
      SCTPUT(output);
      if (freeordpos(ordpos)!=NOERR) {
	SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
      }
      for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
      return flames_midas_fail();
    }
    /* copy all nonstandard descriptors to the output table */
    //jmlarsen: Just copy all descriptors. Standard table descriptors
    //          will be removed by cpl_table_save
    //    if (SCDCOP(intid, outtid, 3, "") != 0) {
    if (SCDCOP(intid, outtid, 1) != 0) {
      sprintf(output, "Error copying descriptors from table %s to table %s",
	      inordtab, outordtab);
      SCTPUT(output);
      if (freeordpos(ordpos)!=NOERR) {
	SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
      }
      for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
      return flames_midas_fail();
    }
    /* loop over columns and create them exactly matching the input table */
    if ((indtype = (int *) calloc((size_t) incols, sizeof(int)))==NULL) {
      SCTPUT("Error allocating memory in create_full_ordertable");
      if (freeordpos(ordpos)!=NOERR) {
	SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
      }
      for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
      return flames_midas_fail();
    }
    else {
      pointerstofree[npointerstofree] = (char *) indtype;
      npointerstofree++;
      indtype--;
    }
    if ((initems = (int *) calloc((size_t) incols, sizeof(int)))==NULL) {
      SCTPUT("Error allocating memory in create_full_ordertable");
      if (freeordpos(ordpos)!=NOERR) {
	SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
      }
      for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
      return flames_midas_fail();
    }
    else {
      pointerstofree[npointerstofree] = (char *) initems;
      npointerstofree++;
      initems--;
    }

    if ((inbytes = (int *) calloc((size_t) incols, sizeof(int)))==NULL) {
      SCTPUT("Error allocating memory in create_full_ordertable");
      if (freeordpos(ordpos)!=NOERR) {
	SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
      }
      for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
      return flames_midas_fail();
    }
    else {
      pointerstofree[npointerstofree] = (char *) inbytes;
      npointerstofree++;
      inbytes--;
    }

    if ((outcol =  calloc((size_t) 2*incols, sizeof(int)))==NULL) {
      SCTPUT("Error allocating memory in create_full_ordertable");
      if (freeordpos(ordpos)!=NOERR) {
	SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
      }
      for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
      return flames_midas_fail();
    }
    else {
      pointerstofree[npointerstofree] = (char *) outcol;
      npointerstofree++;
      outcol--;
    }
    for (incol=1; incol<=incols; incol++) {
      if (TCBGET(intid, incol, indtype+incol, initems+incol, inbytes+incol)
	  !=0) {
	sprintf(output, "Error reading data type for col %d in table %s", 
		incol, inordtab);
	SCTPUT(output);
	if (freeordpos(ordpos)!=NOERR) {
	  SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
	}
	for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	return flames_midas_fail();
      }

      uves_msg_debug("dtype = %d, initems = %d, inbytes = %d\n", 
		     indtype[incol], initems[incol], inbytes[incol]);


      if (TCFGET(intid, incol, inform, indtype+incol)!=0) {
	sprintf(output, "Error reading format for col %d in table %s", 
		incol, inordtab);
	SCTPUT(output);
	if (freeordpos(ordpos)!=NOERR) {
	  SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
	}
	for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	return flames_midas_fail();
      }
      if (TCUGET(intid, incol, inunit)!=0) {
	sprintf(output, "Error reading units for col %d in table %s", 
		incol, inordtab);
	SCTPUT(output);
	if (freeordpos(ordpos)!=NOERR) {
	  SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
	}
	for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	return flames_midas_fail();
      }
      if (TCLGET(intid, incol, inlabel)!=0) {
	sprintf(output, "Error reading label for col %d in table %s", 
		incol, inordtab);
	SCTPUT(output);
	if (freeordpos(ordpos)!=NOERR) {
	  SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
	}
	for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	return flames_midas_fail();
      }
      /* create this column in the new table */
      switch(indtype[incol]) {
      case D_C_FORMAT:
	size = initems[incol]*inbytes[incol];
	break;
      case D_I1_FORMAT:
      case D_I2_FORMAT:
      case D_I4_FORMAT:
      case D_L4_FORMAT:
      case D_UI2_FORMAT:
      case D_R4_FORMAT:
      case D_R8_FORMAT:
	size = initems[incol];
	break;
      default:
	sprintf(output, "Unsupported data type %d in table %s", 
		indtype[incol], inordtab);
	SCTPUT(output);
	if (freeordpos(ordpos)!=NOERR) {
	  SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
	}
	for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	return flames_midas_fail();
	break;
      }
      if (TCCINI(outtid, indtype[incol], size, inform, inunit, 
		 inlabel, outcol+incol) != 0) {
	sprintf(output, "Error creating col %d in table %s", 
		incol, outordtab);
	SCTPUT(output);
	if (freeordpos(ordpos)!=NOERR) {
	  SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
	}
	for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	return flames_midas_fail();
      }
    }
    /* now we can proceed to copy all elements from the input table to the
       output table */
    for (incol=1; incol<=incols; incol++) {
      /* allocate the temporary buffer for the single array in this column */

      uves_msg_debug("DType is %d  initems = %d\n", 
		     indtype[incol], initems[incol]);

      switch(indtype[incol]) {
      case D_I1_FORMAT:
      case D_I2_FORMAT:
      case D_I4_FORMAT:
      case D_L4_FORMAT:
      case D_UI2_FORMAT:
        if ((ibuffer = (int *) calloc(initems[incol], sizeof(int)))==NULL) {
          SCTPUT("Error allocating memory in create_full_ordertable");
	  if (freeordpos(ordpos)!=NOERR) {
	    SCTPUT("Error returned by freeordpos() to \
                create_full_ordertable()");
	  }
          for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	  return flames_midas_fail();
	}
	else {
	  pointerstofree[npointerstofree] = (char *) ibuffer;
	  npointerstofree++;
	}
        /* run over the table rows in this column */
        for (inrow=1; inrow<=inrows; inrow++) {
	  /* read and write as integer */
          if (TCARDI(intid, inrow, incol, 1, initems[incol], ibuffer) 
	      != 0) {
	    sprintf(output, "Error reading row %d col %d of table %s", inrow, 
		    incol, inordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
            for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
            return flames_midas_fail();
	  }



	  if (TCAWRI(outtid, inrow, outcol[incol], 1, initems[incol], ibuffer)
	      != 0) {
	    sprintf(output, "Error writing row %d col %d of table %s", inrow,
		    outcol[incol], outordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
            for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
            return flames_midas_fail();
	  }
	}
	/* free the buffer */
	npointerstofree--;
	free(pointerstofree[npointerstofree]);
	break;
      case D_R4_FORMAT:
	if ((fbuffer = (float *) calloc(initems[incol], sizeof(float)))
	    == NULL) {
	  SCTPUT("Error allocating memory in create_full_ordertable");
	  if (freeordpos(ordpos)!=NOERR) {
	    SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	  }
	  for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	  return flames_midas_fail();
	}
	else {
	  pointerstofree[npointerstofree] = (char *) fbuffer;
	  npointerstofree++;
	}
	/* run over the table rows in this column */
	for (inrow=1; inrow<=inrows; inrow++) {
	  /* read and write as integer */
	  if (TCARDR(intid, inrow, incol, 1, initems[incol], fbuffer) 
	      != 0) {
	    sprintf(output, "Error reading row %d col %d of table %s", 
		    inrow, incol, inordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
	    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	    return flames_midas_fail();
	  }
	  if (TCAWRR(outtid, inrow, outcol[incol], 1, initems[incol], fbuffer)
	      != 0) {
	    sprintf(output, "Error writing row %d col %d of table %s", 
		    inrow, outcol[incol], outordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
	    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	    return flames_midas_fail();
	  }
	}
	/* free the buffer */
	npointerstofree--;
	free(pointerstofree[npointerstofree]);
	break;
      case D_R8_FORMAT:
	if ((dbuffer = (double *) calloc(initems[incol], sizeof(double)))
	    == NULL){
	  SCTPUT("Error allocating memory in create_full_ordertable");
	  if (freeordpos(ordpos)!=NOERR) {
	    SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	  }
	  for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	  return flames_midas_fail();
	}
	else {
	  pointerstofree[npointerstofree] = (char *) dbuffer;
	  npointerstofree++;
	}
	/* run over the table rows in this column */
	for (inrow=1; inrow<=inrows; inrow++) {
	  /* read and write as integer */
	  if (TCARDD(intid, inrow, incol, 1, initems[incol], dbuffer) 
	      != 0) {
	    sprintf(output, "Error reading row %d col %d of table %s", 
		    inrow, incol, inordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
	    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	    return flames_midas_fail();
	  }
	  if (TCAWRD(outtid, inrow, outcol[incol], 1, initems[incol], dbuffer)
	      != 0) {
	    sprintf(output, "Error writing row %d col %d of table %s", 
		    inrow, outcol[incol], outordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
	    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	    return flames_midas_fail();
	  }
	}
	/* free the buffer */
	npointerstofree--;
	free(pointerstofree[npointerstofree]);
	break;
      case D_C_FORMAT:
	size = initems[incol]*inbytes[incol];
	if ((cbuffer = (char *) calloc(initems[incol], inbytes[incol]))
	    == NULL){
	  SCTPUT("Error allocating memory in create_full_ordertable");
	  if (freeordpos(ordpos)!=NOERR) {
	    SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	  }
	  for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	  return flames_midas_fail();
	}
	else {
	  pointerstofree[npointerstofree] = (char *) dbuffer;
	  npointerstofree++;
	}
	/* run over the table rows in this column */
	for (inrow=1; inrow<=inrows; inrow++) {
	  memset(cbuffer, 0, size);
	  /* read and write as integer */
	  if (TCARDC(intid, inrow, incol, 1, size, cbuffer) 
	      != 0) {
	    sprintf(output, "Error reading row %d col %d of table %s", 
		    inrow, incol, inordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
	    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	    return flames_midas_fail();
	  }
	  if (TCAWRC(outtid, inrow, outcol[incol], 1, size, cbuffer)
	      != 0) {
	    sprintf(output, "Error writing row %d col %d of table %s", 
		    inrow, outcol[incol], outordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
	    for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	    return flames_midas_fail();
	  }
	}
	npointerstofree--;
	free(pointerstofree[npointerstofree]);
        free(cbuffer);
	break;
      default:
	sprintf(output, "Unsupported data type %d in table %s", 
		indtype[incol], inordtab);
	SCTPUT(output);
	if (freeordpos(ordpos)!=NOERR) {
	  SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
	}
	for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
	return flames_midas_fail();
	break;
      }
    }

    /* initialise the column indices for the output table */
    //    outordercol = outcol[inordercol];
    //    outfibrecol = outcol[infibrecol];
    //    outxcol = outcol[inxcol];
    //    outycol = outcol[inycol];
    //    outordfibcol = outcol[inordfibcol];
    //    outyfitcol = outcol[inyfitcol];
    //    outresidcol = outcol[inresidcol];

    TCCSER(outtid, "ORDER", &outordercol);
    TCCSER(outtid, "FIBRE", &outfibrecol);
    TCCSER(outtid, "X"    , &outxcol);
    TCCSER(outtid, "Y"    , &outycol);
    TCCSER(outtid, "ORDERFIB", &outordfibcol);
    TCCSER(outtid, "YFIT" , &outyfitcol);
    TCCSER(outtid, "RESIDUAL", &outresidcol);

    /* free temporary arrays */
    for (i=(npointerstofree-1); i>=(npointerstofree-4); i--) 
      free(pointerstofree[i]);
    npointerstofree -= 4;
  } /* if (1) */
  else {
    outordercol = inordercol;
    outfibrecol = infibrecol;
    outxcol = inxcol;
    outycol = inycol;
    outordfibcol = inordfibcol;
    outyfitcol = inyfitcol;
    outresidcol = inresidcol;
  }
  outrows = inrows;
  outcols = incols;

  /* now run a loop over the orders/fibres and create the missing entries */
  for (ifibre=0; ifibre<=(ordpos->maxfibres-1); ifibre++) {
    if (ordpos->fibremask[ifibre] == TRUE) {
      /* this fibre is lit in the fibremask, make sure all orders are 
	 present */
      /* scan the orders */
      for (iorder=ordpos->firstorder; iorder<=ordpos->lastorder; iorder++) {
	/* scan the table to see if we can find this order-fibre pair */
	found = 0;
	for (inrow=1; (found==0)&&(inrow<=inrows); inrow++) {
	  if (TCERDI(intid, inrow, inordercol, &order, &null)!=0) {
	    sprintf(output, "Error reading row %d col %d of table %s", inrow, 
		    inordercol, inordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
            for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
            return flames_midas_fail();
	  }
          if (TCERDI(intid, inrow, infibrecol, &fibre, &null)!=0) {
	    sprintf(output, "Error reading row %d col %d of table %s", inrow, 
		    inordercol, inordtab);
	    SCTPUT(output);
	    if (freeordpos(ordpos)!=NOERR) {
	      SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	    }
            for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
            return flames_midas_fail();
	  }
          if ((order==iorder)&&(fibre==ifibre+1)) found = 1;
	}
        /* was this order-fibre pair found? */
	if (found==0) {
	  /* no, it was not found, hence add it */
	  outrow = outrows;
	  memset(orderfibre, 0, 20);
	  fibre = ifibre+1;
	  sprintf(orderfibre,"%d,%d",iorder,fibre);
	  /* scan x's */
	  for (ix=0; ix<=(ordpos->npix[0]-1); ix+=stepix) {
	    dx = ordpos->start[0]+(((double) ix)*ordpos->step[0]);
	    /* find order centre */
            if (get_ordpos(ordpos, (double) iorder, dx, &ordercentre)!=NOERR) {
              SCTPUT("Error calling get_ordpos() from create_full_ordertable");
	      if (freeordpos(ordpos)!=NOERR) {
                SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	      }
              for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
              return flames_midas_fail();
	    }
            /* find fibre centre */
            fibrecentre = (float) ordercentre+ordpos->fibrepos[ifibre];
            fx = (float) dx;
            /* write table entries for this row */
            outrow++;
            if (TCEWRI(outtid, outrow, outfibrecol, &fibre)!=0) {
              sprintf(output, "Error writing row %d col %d of table %s", 
		      outrow, outfibrecol, outordtab);
	      SCTPUT(output);
              if (freeordpos(ordpos)!=NOERR) {
                SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	      }
              for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
              return flames_midas_fail();
	    }
            if (TCEWRI(outtid, outrow, outordercol, &iorder)!=0) {
              sprintf(output, "Error writing row %d col %d of table %s", 
		      outrow, outordercol, outordtab);
	      SCTPUT(output);
	      if (freeordpos(ordpos)!=NOERR) {
                SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	      }
              for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
              return flames_midas_fail();
	    }
            if (TCEWRC(outtid, outrow, outordfibcol, orderfibre)!=0) {
              sprintf(output, "Error writing row %d col %d of table %s", 
		      outrow, outordfibcol, outordtab);
	      SCTPUT(output);
              if (freeordpos(ordpos)!=NOERR) {
                SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	      }
              for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
              return flames_midas_fail();
	    }
            if (TCEWRR(outtid, outrow, outxcol, &fx)!=0) {
              sprintf(output, "Error writing row %d col %d of table %s", 
		      outrow, outxcol, outordtab);
	      SCTPUT(output);
              if (freeordpos(ordpos)!=NOERR) {
                SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	      }
              for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
              return flames_midas_fail();
	    }
            if (TCEWRR(outtid, outrow, outyfitcol, &fibrecentre)!=0) {
              sprintf(output, "Error writing row %d col %d of table %s", 
		      outrow, outyfitcol, outordtab);
	      SCTPUT(output);
              if (freeordpos(ordpos)!=NOERR) {
                SCTPUT("Error returned by freeordpos() to \
create_full_ordertable()");
	      }
              for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
              return flames_midas_fail();
	    }
	  }
          /* do the input and output table coincide? */
          if (outtid==intid) inrows += outrow-outrows;
	  outrows = outrow;
	}
      }
    }
  }

  /* ok, finished, clean up and exit */
  if (freeordpos(ordpos)!=NOERR) {
    SCTPUT("Error returned by freeordpos() to create_full_ordertable()");
  }
  for (i=(npointerstofree-1); i>=0; i--) free(pointerstofree[i]);
  
  /* close the tables */
  if (TCTCLO(intid)!=0) {
    sprintf(output, "Error closing table %s", inordtab);
    SCTPUT(output);
  }
  if (outtid!=intid) {
    /* the output table is separate from the input table */
    if (TCTCLO(outtid)!=0) {
      sprintf(output, "Error closing table %s", outordtab);
      SCTPUT(output);
    }
  }

  /* ok, it's over */
  return SCSEPI();

}
/**@}*/




