/* @(#)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();

}
/**@}*/




