/*===========================================================================
  Copyright (C) 1993-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
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE        Module
.NAME        tbapplyrul.c
.LANGUAGE    C
.AUTHOR      IPG-ESO Garching
.CATEGORY    Data Organizer utilities
.COMMENTS       This module implements the following Midas commands:
\begin{TeX}
\begin{enumerate}
\item {\tt CLASSIFY/IMAGE} table rule column outchar
\end{enumerate}
\end{TeX}

.VERSION  1.0   15-Mar-1993   Definition     M. Peron

 090831		last modif
-----------------------------------------------------------------------*/

#include <atype.h>
#include <tbldef.h>
#include <tblsys.h>
#include <tblerr.h>
#include <midas_def.h>
#include <macrogen.h>

#include <stdlib.h>
#include <str.h>


#define issign(c)  ((c == '+') || (c == '-'))
#define BUFM 30				/* synchronize with tbcomsel !!  */
#define MAXS 30
#define PARLEN 256
#define MAXLEN 80

extern int get_token();
extern int level00();
extern int tbl_hist();

void deco();


char *token,*line;
double tdtrue,tdfalse;
int token_type,first,nochar,refrow,action,exist;
int tmno[BUFM],tmnoc[BUFM];
char *stringstar[MAXS];
int occ[PARLEN],ocp[PARLEN],principal;

/*

*/

void classify(intable,assod,column,mycval)
char intable[60],column[1+TBL_LABLEN],assod[256],*mycval;
{
int status,tid,nrow;
int null, dummy, type;
int col,cstar[PARLEN],nstar,nstring,pnull[PARLEN];
int i,j,*index, lola,k,pos,pos1,pos2,ntimes,itimes,tidass,nline,ntoken ;
int coldescr,colout,colchar,meth,selass,mylen;
int ibuf[BUFM],nconst[BUFM], unit;
int kk;
char colstar[1+TBL_LABLEN];
char *selecrit;
char *final,*stringtok[MAXS];
char descr[256], *cval;
double *data[BUFM],consta[BUFM];
char *string[BUFM],*cdata[BUFM];
float tblsel;


action = 1;
exist = 0;
cval = osmmget(MAXLEN+1);
line = osmmget(PARLEN);
token = osmmget(PARLEN);
TCMCON(&tblsel,&tdtrue,&tdfalse);
for (i=0; i<MAXS; i++) {
    stringstar[i] = (char *)0;
    stringtok[i] = (char *)0;
    }
final = (char *)0;
selecrit = osmmget(PARLEN+1);
for (i=0 ; i<BUFM; i++) {
      data[i] = (double *)0;
      cdata[i] = (char *)0;
      string[i] = (char *)0;
      tmno[i] = -1;
      tmnoc[i] = -1;
      }
if (assod[strindex(assod,".tbl")]) {
     meth = 1;
     TCTOPN(assod,F_I_MODE,&tidass);
     TCIGET(tidass,&dummy,&ntimes,&dummy,&dummy,&dummy);
     TCLSER(tidass,"DESCR",&coldescr);
     if (coldescr <= 0 ) {
        SCTPUT("Column DESCR not found");
        SCSEPI();
        }
     TCLSER(tidass,"OUTCOL",&colout);
     if (colout <= 0 ) {
        SCTPUT("Column OUTCOL not found");
        SCSEPI();
        }
     TCLSER(tidass,"OUTCHAR",&colchar);
     if (colchar <= 0 ) {
        SCTPUT("Column OUTCHAR not found");
        SCSEPI();
        }
} 
else {
   ntimes = 1;
   meth = 0;
   }
tid = TCTID(intable);
if (tid == -1) 
status = TCTOPN(intable,F_IO_MODE,&tid);
status = TCIGET(tid,&dummy,&nrow,&dummy,&dummy,&dummy);
for (itimes=1; itimes<=ntimes; itimes++) {
   if (!assod[strindex(assod,".tbl")]) {
      strcpy(cval,mycval);
      strcpy(descr,assod);
      }
   else {
      TCSGET(tidass,itimes,&selass);
      if (!selass) continue;
      TCERDC(tidass,itimes,coldescr,descr,&null);
      TCERDC(tidass,itimes,colout,column,&null);
      TCERDC(tidass,itimes,colchar,cval,&null);
   }
status = TCCSER(tid,column,&col);
if (col == -1) TCCINI(tid,D_C_FORMAT,32L,"A16"," ",column,&col);

   for (i=0; i<PARLEN; i++) selecrit[i] = '\0';
   if (assod[strindex(assod,":")])  strcpy(selecrit,descr);
   else status = SCDRDC(tid,descr,1,1,255,&dummy,selecrit,&unit,&null);
   ibuf[0] = tid;
   ibuf[2] = nrow;
   ibuf[3] = -1;
   ibuf[4] = -1;
   ibuf[5] = -1;
   ibuf[6] = -1;
   strcpy(line,selecrit);
   nline = strlen(line);
   get_token();
   level00(ibuf,data,cdata,consta,nconst,string);
   line = line - nline; 
   for (i=0; i<PARLEN; i++) *(line+i) = '\0';
   for (i=0; i<PARLEN; i++) ocp[i] = 0; 
   strncpy(line,selecrit,256L);
   type = 0;
   index = &lola;
   i = *index = 0;
   mylen = strlen(cval);
   while (cval[0] != '\0') {
   pos1 = strscans(cval,"[&");
   if (!cval[pos1]) break;
   else  type = 1;
         pos2 = strloc(cval,'[');
         if (!cval[pos2]) {
             pos1 = strloc(cval,'&');
             if (cval[pos1]) {
                if (!stringstar[*index]) stringstar[*index] = osmmget(MAXLEN);
                oscfill(stringstar[*index],MAXLEN,'\0');
                strncpy(stringstar[*index],cval,pos1);
                while (pos1--) cval++;
                cval++;
                occ[*index] = atoi(cval);
                *index +=1;
                while (isdigit(*cval)) cval++;
                }
             else {
                if (!stringstar[*index]) stringstar[*index] = osmmget(MAXLEN);
                oscfill(stringstar[*index],MAXLEN,'\0');
                strncpy(stringstar[*index],cval,pos1);
                occ[*index]=0;
                *index +=1;
                cval+=pos1; 
                }
             }
         else {
              deco(index,1,&cval);
              }
 
 }
if (type ==1 )cval -= mylen;
nstring = *index;

  if (type == 1) {
  nstar = 0;
  while (*line) {
   get_token();
   if (token_type == 2) strcpy(colstar,token);
   if (token_type ==6 ) {
         ntoken = strlen(token);
         pos = strloc(token,'*'); 
         if (token[pos]) {
              if (!stringtok[nstar]) stringtok[nstar] = osmmget(MAXLEN);
              oscfill(stringtok[nstar],MAXLEN,'\0');
              strncpy(stringtok[nstar],token,MAXLEN);
              TCCSER(tid,colstar,&cstar[nstar]);
	      nstar++;
              token = token + pos +1;
              while(token[strloc(token,'*')]) {
                 pos = strloc(token,'*'); 
                 *(stringtok[nstar-1] + pos + 1 ) = '\0';
                 if (!stringtok[nstar]) stringtok[nstar] = osmmget(MAXLEN);
                 oscfill(stringtok[nstar],MAXLEN,'\0');
                 strncpy(stringtok[nstar],token,MAXLEN);
                 TCCSER(tid,colstar,&cstar[nstar]);
	         nstar++;
                 token = token + pos +1;
                 }
	       }
         token = token - ntoken;
         }
 }
}
   if (type == 0) {
    for (i=0; i<nrow; i++) {
       if (*(data[0] + i)) status = TCEWRC(tid,i+1,col,cval);
       } 
}
   else {
    if (!final) final = osmmget(PARLEN);
    for (i=0; i<PARLEN; i++) {
       final[i] = '\0';
  }

   for (i=0; i<nrow; i++) {
       if (*(data[0]+i)) {
          for (j=0; j<PARLEN; j++) final[j] = '\0';
          for (j=0; j<nstring;  j++) { 
             if (occ[j] == 0) strcat(final,stringstar[j]);
             else if (occ[j] > 0) {
                status = TCERDC(tid,i+1,cstar[occ[j]-1],cval,&pnull[j]);
                if (pnull[j] == 0) {
                 if (ocp[j] && final[0] != 0) strcat(final,"+");
                 if (*stringtok[occ[j]-1] == '*') {
                   strcat(final,stringstar[j]);
                   kk = strskip(cval,' ');
                   k = strbskip(cval+kk,' ');
                   if (cval[k+kk+1]) cval[k+kk+1] = '\0';
                   k = strlen(cval)-strlen(stringtok[occ[j]-1])+1;
                   cval[k] = '\0';
                   strcat(final,cval+strskip(cval,' '));
                   }
                 else {
                 strcat(final,stringstar[j]);
                   kk = strskip(cval,' ');
                   k = strloc(cval+kk,' ');
                   if (cval[k+kk]) cval[k+kk] = '\0';
                 strcat(final,cval+strlen(stringtok[occ[j]-1])-1+strskip(cval,' '));
                 }
                }
              }
               else 
                   if (pnull[-occ[j]-1] == 0) strcat(final,stringstar[j]);
             }   
          TCEWRC(tid,i+1,col,final);
          }
      } 
} 
/*for (i=0; i<BUFM; i++) if (data[i]) osmmfree((char *)data[i]);
for (i=0; i<BUFM; i++) if (cdata[i]) osmmfree(cdata[i]);*/

for (i=0; i<BUFM;i++) {
   if (tmno[i] != -1) SCFCLO(tmno[i]);
   if (tmnoc[i] != -1 ) SCFCLO(tmnoc[i]);
   }
for (i=0; i<BUFM; i++) if (string[i]) osmmfree(string[i]);
for (i=0; i<BUFM; i++) {
      data[i] = (double *)0;
      cdata[i] = (char *)0;
      string[i] = (char *)0;
}
ibuf[3] = -1;
ibuf[4] = -1;
ibuf[5] = -1;
ibuf[6] = -1;
if (type == 1) line = line-nline;
}
osmmfree(line);
osmmfree(token);
osmmfree(selecrit);
osmmfree(cval);
if(final) osmmfree(final);
status = tbl_hist(tid);
if (meth==1) TCTCLO(tidass);
status = TCTCLO(tid);
}

/*

*/

void  deco(index,flag,decval)
int *index,flag;
char **decval;
{
char *mydecval;
int pos1,pos2;
mydecval = *decval;
pos1 = strloc(mydecval,'[');
if (pos1 != 0) {
   if (!stringstar[*index]) stringstar[*index] = osmmget(MAXLEN);
   oscfill(stringstar[*index],MAXLEN,'\0');
   strncpy(stringstar[*index],mydecval,pos1);
   while (pos1--) mydecval++;
   occ[*index] = 0;
   *index += 1;
   }
mydecval++;
pos1 = strloc(mydecval,'[');
pos2 = strloc(mydecval,']');
if (pos1 > pos2) {
   pos1 = strloc(mydecval,'&');
   if (!stringstar[*index]) stringstar[*index] = osmmget(MAXLEN);
   oscfill(stringstar[*index],MAXLEN,'\0');
   strncpy(stringstar[*index],mydecval,pos1);
   while (pos1--) mydecval++;
   mydecval++;
   occ[*index] = atoi(mydecval);
   if (flag == 1)  ocp[*index] = 1;
   *index += 1;
   while(isdigit(*mydecval)) mydecval++;
   if (*mydecval == ']') mydecval++;
   *decval = mydecval;
   }
else {
   pos2 = strloc(mydecval,'[');
   while (pos2) {
          pos1 = strloc(mydecval,'&');
          if (mydecval[pos1] && (pos1 < pos2)) {
            if (!stringstar[*index]) stringstar[*index] = osmmget(MAXLEN);
            oscfill(stringstar[*index],MAXLEN,'\0');
            strncpy(stringstar[*index],mydecval,pos1);
            while (pos1--) {mydecval++;pos2--;} 
            mydecval++; pos2--;
            occ[*index] = atoi(mydecval);
            if (flag == 1) ocp[*index] = 1;
            principal = *index;
            *index += 1;
            while (isdigit(*mydecval)) {mydecval++; pos2--;}
            }
          else {
            if (!stringstar[*index]) stringstar[*index] = osmmget(MAXLEN);
            oscfill(stringstar[*index],MAXLEN,'\0');
            strncpy(stringstar[*index],mydecval,pos2);
            mydecval += pos2;
            pos2 = 0;
            occ[*index] = -principal -1 ;
          /*  ocp[*index] = 1; */
            *index += 1;
            }
          }
*decval = mydecval;
deco(index,0,decval);
mydecval = *decval;
pos1 = strloc(mydecval,']');
if (pos1 != 0) {
   if (!stringstar[*index]) stringstar[*index] = osmmget(MAXLEN);
   oscfill(stringstar[*index],MAXLEN,'\0');
   strncpy(stringstar[*index],mydecval,pos1);
   while (pos1--) mydecval++;
   occ[*index] = -1- principal;
   *index += 1;
   mydecval++;
   if (*mydecval == ']') mydecval++;
    }
else mydecval++;
*decval = mydecval;
}
}
