/*  ******************************************************************
 *                                                                   *
 * File             : rs.c                                           *
 *                                                                   *
 * Purpose          :                                                *         
 *                                                                   *
 * Version Number   : 1.6                                            *
 *                                                                   *
 * Revision History :                                                *
 *                                                                   *
 * Date                              Developer                       *
 * ----                              ---------                       *
 *  used to establish levels in a flat file                          *
*/

char rs_version[]="rs  version 1.6  28 Jan 99";
/*
 * 28 Jan 99                          wjs                            *
 *	Use path_info_routines to control PATH_INFO; change          *
 *	  PATH_INFO just before needed; change it back when done     *
 *	Add version string; reorder comments	                     *
 *	    [Needs path_info_routines 1.1 or later (.c & .h)]	     *
 *	    [Begin 1.6]						     *
 * June 1997 grf                                                     *
 *       changed sub names to in_xxxx, fixes for v 1.5               *
 * May 1997                         Glenn Flierl                     *
 *       changed error calls to use error_ in outer.c                *
 * May 21, 1996                       clh                            *
 *  iovalreal change to allow alpha vars to begin with digits        *
 * March 1996                         clh                            *
 *  use minbufsize.h to determine size of buffers                    *
 * January 1996                       clh                            *
 *  fixed rsw to respect the re-ordering of variables                *
 * July 1995                          clh                            *
 *  add subroutine to return column widths - iowidth_()              *
    ******************************************************************
*/
#if HP || IBM
#define jdbopen_ jdbopen
#define jdbreada_ jdbreada
#define jdbread_ jdbread
#define jdbclose_ jdbclose
#define jdbcomments_ jdbcomments
#define jdblevel_ jdblevel
#define jdbattributes_ jdbattributes
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include OPTIONS
#include INNEROPTIONS
#include "path_info_routines.h"

double strtod();

/* #define DEBUG */

int nlevels,nnames;
int firstvar[6];
char names[NVAR][VARNAMESIZE];
int fldwidths[NVAR];
int namesize=VARNAMESIZE;
char values[NVAR][DATUMSIZE];
char comp[NVAR][DATUMSIZE];
int valuesize=DATUMSIZE;
int handle;
int minlevelread;
char comments[COMMENTSIZE];

char ss[NVAR][DATUMSIZE];
int ns=0;
int newlev[NVAR];
int newpntr[NVAR];
int newlpntr[11];
int maxoutlev;

void in_getwidth();

int ioreadrec_(level)
int *level;
{
  int clevel,i;

  if(*level == minlevelread)
    {
      minlevelread= *level+1;
      return 1;
    }
  else if(*level >minlevelread) return 0;

  while(1){
    clevel=jdbreada_(&handle,values,&valuesize);
    /* printf("clevel %d\n",clevel); */
    if(clevel<0){
      minlevelread= -1;
      return 0;
    };
    
    for(i=firstvar[clevel];i<nnames;i++){
      if(newlev[i]<minlevelread)
	if(strcmp(values[i],comp[i]))minlevelread=newlev[i];
      strcpy(comp[i],values[i]);
    };
    
    if (minlevelread < *level) return 0;
    else if(minlevelread == *level){
      minlevelread++;
      return 1;
    };
  };
}

void ioclose_()
{
  jdbclose_(&handle);
}

int ioopen_(s,nparams,ntotal)
char *s[];
int *nparams;
int *ntotal;
{
  char tmp[INBUFSIZE],*sp;
  int i,j,k,m,maxclev;

    /*  PATH_INFO function and strings.					*/
  char *make_PATH_INFO_putenv_string();
      /* "PATH_INFO=" + getenv("PATH_INFO").  Must be static		*/
      /*  since it "survives" in process table after ioopen_ exits)	*/
  static char *PATH_INFO_orig_putenv;
      /* "PATH_INFO=" + getenv("PATH_INFO") w/ protocol = "jgof"	*/
  char *PATH_INFO_jgof_putenv;

    /*  Must be sure that methods down the line produce JGOFS	*/
    /*  protocol (or whatever jdbopen requires), and not html,	*/
    /*  flat, or whatever.  Do this by replacing proto string	*/
    /*  with "jgof" (WJS decision at this point... jgof has no	*/
    /*  meaning to system).					*/
    /*    Make 2 strings for putenv.  1 sets up existing 	*/
    /*    PATH_INFO; the other sets up PATH_INFO with "jgof"	*/
    /*    protocol						*/  
    /*    PATH_INFO_ENV_VAR & USE_EXISTING_LEVEL defined in	*/
    /*    path_info_routines.h					*/
  if (getenv(PATH_INFO_ENV_VAR) == NULL) {
    PATH_INFO_orig_putenv = NULL;
    PATH_INFO_jgof_putenv = NULL;
  } else {
    PATH_INFO_orig_putenv = 
      make_PATH_INFO_putenv_string(NULL,NULL,NULL,NULL,USE_EXISTING_LEVEL,NULL);
    if (PATH_INFO_orig_putenv == NULL)
      error_ ("&x Cannot make PATH_INFO_orig_putenv",
	      "Memory problems or PATH_INFO not in expected format");
    PATH_INFO_jgof_putenv = 
      make_PATH_INFO_putenv_string
				(NULL,NULL,NULL,"jgof",USE_EXISTING_LEVEL,NULL);
    if (PATH_INFO_jgof_putenv == NULL)
      error_ ("&x Cannot make PATH_INFO_jgof_putenv",
	      "Memory problems or PATH_INFO not in expected format");
  }

  if (PATH_INFO_jgof_putenv != NULL) 
    if (  (i = putenv(PATH_INFO_jgof_putenv)) != 0  )
      error_ ("&x putenv failure for PATH_INFO",strerror(i));

  strcpy(tmp,s[0]);
  nnames = -NVAR;

  maxclev=jdbopen_(&handle,tmp,names,&namesize,&nnames);

  if (maxclev<0){error_("&x Bad Object returned from jdbopen ",s[0]);};

    /*  Restore original PATH_INFO if we changed it		*/
  if (PATH_INFO_jgof_putenv != NULL) {
    if (  (i = putenv(PATH_INFO_orig_putenv)) != 0  )
       error_ ("&x putenv failure restoring PATH_INFO",strerror(i));
    free(PATH_INFO_jgof_putenv);
  }

  s[0][0]=0;
  *comments=0;
  while(jdbcomments_(&handle,tmp))
    {strcat(comments,tmp);strcat(comments,"\n");};
  for(i=1;i<*nparams;i++)if(s[i][0]>='0' && s[i][0]<='9' && s[i][1]==':'){
    strcpy(ss[ns++],s[i]);

    s[i][0]='\0';
  };
  
  j=0;
  firstvar[j]=0;
  for(i=0;i<nnames;i++){
    newlev[i]= -1;
    comp[i][0]=0;
    if((k=iovarlevel_(&handle,&i))>j)
      firstvar[++j]=i;
  };

  maxoutlev= -1;
  m=0;
  for(k=0;k<ns;k++){
    strcpy(tmp,ss[k]);
    i=tmp[0]-'0';
    if(i>maxoutlev){maxoutlev=i;newlpntr[maxoutlev]=m;};
    if(tmp[2]=='*'){
      for(j=0;j<nnames;j++)if(newlev[j]== -1){
	newlev[j]=maxoutlev;
	newpntr[m++]=j;
      };
    } else {
      for(j=0;j<nnames;j++)
	if(strcmp(names[j],tmp+2)==0)break;
      if(j<nnames){
	newlev[j]=maxoutlev;
	newpntr[m++]=j;
      };
    };
  };
  
  if(maxoutlev<0)maxoutlev=0;
  
  for(j=0;j<nnames;j++)
    if(newlev[j]<0){
      newlev[j]=maxoutlev;
      newpntr[m++]=j;
    };
  
  *ntotal=nnames;

  minlevelread = maxoutlev+1;
  return maxoutlev;
}

int iovarlevel_(vn)
int *vn;
{
  return newlev[newpntr[*vn]];
}

int ioattrout_(vn,str)
int *vn;
char *str;
{
   int j;

   j = newpntr[*vn];

   if ((jdbattributes_(&handle,&j,str)) == 0)
       return 0;
   else {
       if (strncmp(str,"width=",6) == 0) {
         in_getwidth(&j,str);
       }      
       return 1;
   }
}

void in_getwidth(vn, ptr)
/* read the width from the string 'ptr' (an attribute that has
        been tested prior to coming here for containing the 
        string 'width=') and write it to the fldwidths array
        element '*vn'
*/
int *vn;
char *ptr;
{
  char *p;
  int len;
  p = strchr(ptr,'=');

  sscanf(p+1,"%d", &len);

  fldwidths[*vn] = len;
  return;
}

void iovalreal_(vn,f)
int *vn;
float *f;
{
/* following line changed by clh, May 1996
if(strspn(values[i],"0123456789.+-"))
  to one below, to allow for strings that begin with digits
*/

  int i;
  char *end_char_ptr;

  i=newpntr[*vn];
  if(i<0) {*f=-9999.0; return;};

/* following line changed by clh, May 1996
  if(strspn(values[i],"0123456789.+-"))
  to one below, to allow for strings that begin with digits
*/

  *f=strtod(values[i],&end_char_ptr);
  if (*end_char_ptr != '\0')
   *f= -9999.0;

return;
}

void iovalstr_(vn,tmp)
int *vn;
char *tmp;
{
  char *s;

  s=values[newpntr[*vn]];
  s=s+strspn(s," ");
  strcpy(tmp,s);
}

void ioname_(vn,s)
int *vn;
char *s;
{
  strcpy(s,names[newpntr[*vn]]);
}

int iocommout_(str)
char *str;
{
char *at;

if (comments[0]){
  at=strchr(comments,'\n');
  if(at){
    *at = '\0';
    strcpy(str,comments);
    strcpy(comments,at+1);
  } else {
    strcpy(str,comments);
    comments[0]='\0';
  };
  return 1;
} else return 0;
}

int iowidth_(vn)
int *vn;
{
   int i;

   i = fldwidths[newpntr[*vn]];
return i;
}
