
/* "MT", a GPIB interface to view program,
   Copyright (C) 1987, 1990 California Institute of Technology.
   Original author: John Lazzaro
   Unix Port Maintainer: John Lazzaro
   Maintainers's address: lazzaro@hobiecat.cs.caltech.edu;
                          CB 425/ CU Boulder/Boulder CO 91125. 


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 (Version 1, Feb 1989).

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; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

/* Output from p2c, the Pascal-to-C translator */
/* From input file "mt.text" */


#include <p2c/p2c.h>

/* SEARCHME for new device places */

#define MT_G
#include "mt.h" 
#include "mmmt.h" 
#include "fcmt.h" 
#include "fgmt.h" 



#define maxnumdev       32   /*maximum number of devices in the system*/

#define lnten           2.302585093


/*device table records*/


typedef struct devinfo {
  _PROCEDURE proc;
  Char devname[9];
} devinfo;


Static devinfo devlist[maxnumdev];   /*table of device names*/
Static long numdev;   /*size of table*/



/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/
/* Commands that install devices - add yourself to avoid user initialization   */
/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/


/*****************************************************************************/
/*                attempt a device installation                              */

Static boolean MT_install(newproc,keyname)
Anyptr newproc;
Char *keyname;
{

/*****************************************************************************/

  numdev++;
  strupper(devlist[numdev - 1].devname, keyname);
  devlist[numdev - 1].proc.proc = newproc; 
  devlist[numdev - 1].proc.link = NULL; 
  return 1;
}


/* SEARCHME for new device places */

/*****************************************************************************/
/* try to install all popular devices at runtime                             */

Static Void MT_Init_devlist()
{
/*****************************************************************************/
 
  boolean found;

  if (ieeeinit()==-1) 
    printf("HPIB board not found\n");
  else    
    printf("HPIB board found\n");
  ieeewt("TIME OUT 120\n"); /* time out period of two minutes */
  numdev = 0;
  found = MT_install(MT_MM_MAIN,"MM");
  found = MT_install(MT_FC_MAIN,"FC");
  found = MT_install(MT_FG_MAIN,"FG");

/*found = MT_install("FG");
  found = MT_install("FC");
  found = MT_install("VS");
  found = MT_install("EL");
  found = MT_install("MU"); */
}


/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/

/*       Global procedures that use indiviual instrument procedures            */

/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/


/*******************************************************************************/
/*      does an action to all instrument (*, '') or a list of instruments      */

Static Void MT_allinst_execute(action_, buffer_)
mt_action action_;
Char *buffer_;
{

  /*******************************************************************************/
  Char buffer[256];
  long Count;
  Char tmpbuf[256], parse[256];
  boolean Found;
  long FORLIM;
  
  strcpy(buffer, buffer_);
  if (*buffer == '\0' || !strcmp(buffer, "*")) {
    FORLIM = numdev;
    for (Count = 0; Count < FORLIM; Count++) {
      if (devlist[Count].proc.link != NULL)
	(*(Void(*) PP((mt_action action_, Anyptr _link)))
	  devlist[Count].proc.proc)(action_, devlist[Count].proc.link);
      else
	(*(Void(*) PP((mt_action action_)))devlist[Count].proc.proc)(action_);
    }
    return;
  }
  strcpy(tmpbuf, buffer);
  while (*tmpbuf != '\0') {
    strword(tmpbuf, parse);
    strupper(parse, parse);
    Found = false;
    Count = 1;
    while (!Found && Count <= numdev) {
      if (!strcmp(devlist[Count - 1].devname, parse)) {
	if (devlist[Count - 1].proc.link != NULL)
	  (*(Void(*) PP((mt_action action_, Anyptr _link)))
	    devlist[Count - 1].proc.proc)(action_,
					  devlist[Count - 1].proc.link);
	else
	  (*(Void(*) PP((mt_action action_)))devlist[Count - 1].proc.proc)(action_);
	Found = true;
      } else
	Count++;
    }
  }
}



/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/

/*               Definitions of all MT view commands                           */

/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/



/*******************************************************************************/
/*Command to reset (all) instruments, sanitize, and update values              */
/*******************************************************************************/

/*******************************************************************************/

Static Void MT_DoCmd_reset(buffer)
Char *buffer;
{

  /*******************************************************************************/
  MT_allinst_execute(mt_reset, buffer);
  MT_allinst_execute(mt_update, buffer);
}


/*******************************************************************************/

Static Void MT_AddCmd_reset()
{

  /*******************************************************************************/
  _PROCEDURE TEMP;

  TEMP.proc = (Anyptr)MT_DoCmd_reset;
  TEMP.link = (Anyptr)NULL;
  v_addcmd("MT_Reset", TEMP, "MT_Reset",
	   "Resets, and reinitializes (all) instruments to sane values");
  v_addhelp("MT_Reset");
  v_addhelp("Sets parameters of (all) instruments to sane values");
}


/*******************************************************************************/
/*Command to sanitize (all) instruments  and update values              */
/*******************************************************************************/

/*******************************************************************************/

Static Void MT_DoCmd_init(buffer)
Char *buffer;
{

  /*******************************************************************************/
    MT_allinst_execute(mt_init, buffer);
    MT_allinst_execute(mt_reset, buffer);
    MT_allinst_execute(mt_update, buffer);
  
}


/*******************************************************************************/

Static Void MT_AddCmd_init()
{

  /*******************************************************************************/
  _PROCEDURE TEMP;

  TEMP.proc = (Anyptr)MT_DoCmd_init;
  TEMP.link = (Anyptr)NULL;
  v_addcmd("MT_Init", TEMP, "MT_Init", "Resets and reinitializes instruments");
  v_addhelp("MT_Init");
  v_addhelp("Initializes (all) instruments");
}


/*******************************************************************************/
/*Command to update values of (all) instruments                                */
/*******************************************************************************/

/*******************************************************************************/

Static Void MT_DoCmd_update(buffer)
Char *buffer;
{

  /*******************************************************************************/
  MT_allinst_execute(mt_update, buffer);
}


/*******************************************************************************/

Static Void MT_AddCmd_update()
{

  /*******************************************************************************/
  _PROCEDURE TEMP;

  TEMP.proc = (Anyptr)MT_DoCmd_update;
  TEMP.link = (Anyptr)NULL;
  v_addcmd("MT_Update", TEMP, "MT_Update",
	   "Updates state of (all) instruments");
  v_addhelp("MT_Update");
  v_addhelp("Updates state of (all) instruments");
}


/*******************************************************************************/
/*              Command to install new instruments                             */
/*******************************************************************************/

/*******************************************************************************/

Static Void MT_DoCmd_install(buffer)
Char *buffer;
{

  /*******************************************************************************/
  Char newinst[256], tmpbuf[256];
  long count;
  boolean found;
  long FORLIM;

  strcpy(tmpbuf, buffer);
  while (*tmpbuf != '\0') {
    strword(tmpbuf, newinst);
    strupper(newinst, newinst);
    found = false;
    FORLIM = numdev;
    for (count = 0; count < FORLIM; count++) {
      if (!strcmp(devlist[count].devname, newinst))
	found = true;
    }
    if (found) {
      printf("%s already installed\n", newinst);
      continue;
    }
    found = MT_install(newinst);
    if (found) {
      MT_allinst_execute(mt_makeparam, newinst);
      printf("%s now installed\n", newinst);
    } else
      printf("MT%s has not been permed\n", newinst);
  }
}


/*******************************************************************************/

Static Void MT_AddCmd_Install()
{

  /*******************************************************************************/
  _PROCEDURE TEMP;

  TEMP.proc = (Anyptr)MT_DoCmd_install;
  TEMP.link = (Anyptr)NULL;
  v_addcmd("MT_Install", TEMP, "MT_Install",
	   "Installs new instrument libraries");
  v_addhelp("MT_Install");
  v_addhelp("MT_Install <instname> <instname> <instname> ");
  v_addhelp("Installs new instrument libraries");
}


/*******************************************************************************/
/*      Command to uninitialize unconnected instruments                        */
/*******************************************************************************/

/*******************************************************************************/

Static Void MT_DoCmd_uninit(buffer)
Char *buffer;
{

  /*******************************************************************************/
  MT_allinst_execute(mt_uninit, buffer);
}


/*******************************************************************************/

Static Void MT_AddCmd_uninit()
{

  /*******************************************************************************/
  _PROCEDURE TEMP;

  TEMP.proc = (Anyptr)MT_DoCmd_uninit;
  TEMP.link = (Anyptr)NULL;
  v_addcmd("MT_Uninit", TEMP, "MT_Uninit", "Uninitializes (all) instruments");
  v_addhelp("MT_Uninit");
  v_addhelp("Uninitializes (all) instruments");
}


/*******************************************************************************/
/*          Command to fill up a curve with appropriate data                   */
/*******************************************************************************/

/*******************************************************************************/
/*                 does the work for fill command                              */

Static Void Fillup(fcurve, xparam, yparam, dirforward, delay)
v_curverec *fcurve;
v_paramrec *xparam, *yparam;
boolean dirforward;
long delay;
{
  /*curve to be filled*/
  /*parameters to fill them with*/
  /*direction of fill*/
  /*wait time (cs) for each datapoint*/

  /*******************************************************************************/
  long count, wait;
  Char tmpstr[256];
  long FORLIM;
  Char STR1[256];


  if (dirforward) {
    FORLIM = fcurve->base->len;
    for (count = 0; count < FORLIM; count++) {
      if (fcurve->base->vec[count] == v_badvalue)
	fcurve->vec[count] = v_badvalue;
      else {
	sprintf(tmpstr, "%g", fcurve->base->vec[count]);
	if (xparam->kind->chproc.link != NULL)
	  (*(Void(*) PP((v_paramrec *pp, Char *val, Anyptr _link)))
	    xparam->kind->chproc.proc)(xparam, tmpstr,
				       xparam->kind->chproc.link);
	else
	  (*(Void(*) PP((v_paramrec *pp, Char *val)))xparam->kind->chproc.proc)(
	    xparam, tmpstr);
	if (delay > 0) {
	  wait = delay + timers_sysclock();
	  while (wait > timers_sysclock()) ;
	}
	strcpy(tmpstr, "never filled");
	if (yparam->kind->fmtproc.link != NULL)
	  (*(Void(*) PP((v_paramrec *pp, Char *val, Anyptr _link)))
	    yparam->kind->fmtproc.proc)(yparam, tmpstr,
					yparam->kind->fmtproc.link);
	else
	  (*(Void(*) PP((v_paramrec *pp, Char *val)))
	    yparam->kind->fmtproc.proc)(yparam, tmpstr);
	TRY(try1);
	  fcurve->vec[count] = atof(tmpstr);
	RECOVER(try1);
	  sprintf(STR1, "y parameter returned bad value: %s", tmpstr);
	  v_failmsg(STR1);
	ENDTRY(try1);
      }
    }
    return;
  }
  for (count = fcurve->base->len - 1; count >= 0; count--) {
    if (fcurve->base->vec[count] == v_badvalue)
      fcurve->vec[count] = v_badvalue;
    else {
      sprintf(tmpstr, "%g", fcurve->base->vec[count]);
      if (xparam->kind->chproc.link != NULL)
	(*(Void(*) PP((v_paramrec *pp, Char *val, Anyptr _link)))
	  xparam->kind->chproc.proc)(xparam, tmpstr,
				     xparam->kind->chproc.link);
      else
	(*(Void(*) PP((v_paramrec *pp, Char *val)))xparam->kind->chproc.proc)(
	  xparam, tmpstr);
      if (delay > 0) {
	wait = delay + timers_sysclock();
	while (wait > timers_sysclock()) ;
      }
      strcpy(tmpstr, "never filled");
      if (yparam->kind->fmtproc.link != NULL)
	(*(Void(*) PP((v_paramrec *pp, Char *val, Anyptr _link)))
	  yparam->kind->fmtproc.proc)(yparam, tmpstr,
				      yparam->kind->fmtproc.link);
      else
	(*(Void(*) PP((v_paramrec *pp, Char *val)))yparam->kind->fmtproc.proc)(
	  yparam, tmpstr);
      TRY(try2);
	fcurve->vec[count] = atof(tmpstr);
      RECOVER(try2);
	sprintf(STR1, "y parameter returned bad value: %s", tmpstr);
	v_failmsg(STR1);
      ENDTRY(try2);
    }
  }
}


/*******************************************************************************/
/*         Do parsing for fill command - last procedure does the work          */

Static Void MT_DoCmd_Fill(buffer_)
Char *buffer_;
{

  /*******************************************************************************/
  Char buffer[256], fcurvename[256];
      /*parsed name of curve, direction, delay*/
  Char dirname[256], delayname[256];
  v_curverec *fcurve;   /*pointer to curve*/
  v_paramrec *xparam, *yparam;   /*pointer to parameters*/
  boolean dirforward;   /*direction of datataking, temporary*/
  long delay;   /*delay time for datataking*/
  Char STR1[256];

  strcpy(buffer, buffer_);
  v_exstrword(buffer, fcurvename);
  strcompress(buffer, " ", true);
  strcpy(dirname, "+");
  if (*buffer != '\0') {
    v_needsep(buffer, ':');
    v_exstrword(buffer, dirname);
  }
  strcompress(buffer, " ", true);
  strcpy(delayname, "0");
  if (*buffer != '\0') {
    v_needsep(buffer, ':');
    v_exstrword(buffer, delayname);
  }
  v_curvelist(fcurvename, &fcurve, v_clone);
  if (fcurve == NULL) {
    sprintf(STR1, "%s not a curve", fcurvename);
    v_failmsg(STR1);
    return;
  }
  yparam = v_findparam(strupper(STR1, fcurve->units));
  if (yparam == NULL) {
    sprintf(STR1, "%s is not a parameter", fcurve->units);
    v_failmsg(STR1);
    return;
  }
  xparam = v_findparam(strupper(STR1, fcurve->base->units));
  if (xparam == NULL) {
    sprintf(STR1, "%s is not a parameter", fcurve->base->units);
    v_failmsg(STR1);
  }
  if (!strcmp(dirname, "+"))
    dirforward = true;
  else {
    if (!strcmp(dirname, "-"))
      dirforward = false;
    else {
      sprintf(STR1, "%s is not a valid direction", dirname);
      v_failmsg(STR1);
    }
  }
  if (v_parseinteger(delayname, &delay)) {
    if (delay < 0) {
      sprintf(STR1, "%s is negative", delayname);
      v_failmsg(STR1);
    }
  } else {
    sprintf(STR1, "%s is not a number", delayname);
    v_failmsg(STR1);
  }
  Fillup(fcurve, xparam, yparam, dirforward, delay);
}


/*******************************************************************************/

Static Void MT_AddCmd_Fill()
{

  /*******************************************************************************/
  _PROCEDURE TEMP;

  TEMP.proc = (Anyptr)MT_DoCmd_Fill;
  TEMP.link = (Anyptr)NULL;
  v_addcmd("MT_Fill", TEMP, "MT_Fill", "Fills a curve with appropriate data");
  v_addhelp("MT_Fill");
  v_addhelp("MT_Fill <curve> : <+,->: <delay>");
  v_addhelp("Fills a curve with appropriate data");
  v_addhelp("X and Y Units hold parameter names");
  v_addhelp("X (basis) gives data to send to X parameter");
  v_addhelp("Y is returned filled with data from Y parameter");
  v_addhelp("Optional sign gives direction of datataking");
  v_addhelp("Optional delay time (integer centiseconds) for each data point");
}


/*******************************************************************************/
/*                   Command to make a log basis                               */
/*******************************************************************************/

/*******************************************************************************/
/*                         makes a log basis                                   */

Static Void MT_DoCmd_LogBasis(buffer_)
Char *buffer_;
{

  /*******************************************************************************/
  Char buffer[256], lcurvename[256];   /*string for name for basis*/
  Char minname[256], maxname[256], ppdecname[256], xunitsname[256],
       yunitsname[256];
      /*strings for units*/
  double min, max, realdec, realppdec;
      /*actual values for min,max, # decades, # ppd*/
  long dec, ppdec;   /*integers for # points per decade,  # decades*/
  long points;   /*total number of points*/
  double *xvec, *yvec;


  v_curverec *fcurve;   /*pointer to curve*/
  v_paramrec *yparam;   /*pointer to parameters*/


  boolean Ok;   /*status of parsing*/
  long count1, count2;   /*counting variables*/
  double bot, top;   /*counting variables*/
  Char STR1[256], STR3[256];



  strcpy(buffer, buffer_);
  v_exstrword(buffer, lcurvename);
  v_needsep(buffer, '=');
  v_exstrword(buffer, minname);
  v_needsep(buffer, ':');
  v_exstrword(buffer, maxname);
  v_needsep(buffer, ':');
  v_exstrword(buffer, ppdecname);
  v_needsep(buffer, ':');
  v_exstrword(buffer, xunitsname);
  v_needsep(buffer, ':');
  v_exstrword(buffer, yunitsname);

  Ok = false;
  if (v_parsereal(minname, &min)) {
    if (v_parsereal(maxname, &max)) {
      if (v_parsereal(ppdecname, &realppdec)) {
	Ok = true;
	if (max <= min) {
	  sprintf(STR3, "%g less than or equal to %g", max, min);
	  v_failmsg(STR3);
	  Ok = false;
	}
	if (max == 0 || min == 0) {
	  v_failmsg("zero values for max or min not allowed");
	  Ok = false;
	}
	if (max > 0 && min < 0 || max < 0 && min > 0) {
	  v_failmsg("max and min must have the same sign");
	  Ok = false;
	}
	ppdec = (long)floor(realppdec + 0.5);
	if (ppdec <= 0) {
	  sprintf(STR1, "%ld not a positive integer ", ppdec);
	  v_failmsg(STR1);
	  Ok = false;
	}
      } else
	v_failmsg("<points per decade> not a number");
    } else
      v_failmsg("<max> not a number");
  } else
    v_failmsg("<min> not a number");

  if (!Ok)
    return;
  realdec = fabs(log(max / min)) / lnten;
  if (realdec - (long)realdec < 0.001)
    dec = (long)(fabs(log(max / min)) / lnten);
  else
    dec = (long)(fabs(log(max / min)) / lnten) + 1;
  points = dec * ppdec;
  v_newvector(&xvec, points);
  v_newvector(&yvec, points);
  bot = min;
  for (count1 = 0; count1 < dec; count1++) {
    top = bot * 10;
    if (top > max)
      top = max;
    for (count2 = 1; count2 <= ppdec; count2++) {
      xvec[count1 * ppdec + count2 - 1] =
	(top * (count2 - 1) + bot * (ppdec - count2)) / (ppdec - 1);
      yvec[count1 * ppdec + count2 - 1] = v_badvalue;
    }
    bot = top;
  }
  v_addcurve(points, xvec, yvec, xunitsname, yunitsname, lcurvename);
  v_disposevector(&xvec, points);
  v_disposevector(&yvec, points);
}


/*******************************************************************************/

Static Void MT_AddCmd_LogBasis()
{

  /*******************************************************************************/
  _PROCEDURE TEMP;

  TEMP.proc = (Anyptr)MT_DoCmd_LogBasis;
  TEMP.link = (Anyptr)NULL;
  v_addcmd("MT_logbasis", TEMP, "MT_logbasis", "makes a logarithmic basis");
  v_addhelp("MT_logbasis");
  v_addhelp("MT_logbasis <curve> = <min>:<max>:<points/decade>:<xunits>:<xunits>");
  v_addhelp("makes a logarithmic basis");
}



/*******************************************************************************/
/*                   Command to make a lin basis                               */
/*******************************************************************************/

/*******************************************************************************/
/*                      makes a linear basis                                   */

Static Void MT_DoCmd_LinBasis(buffer_)
Char *buffer_;
{

  /*******************************************************************************/
  Char buffer[256], lcurvename[256];   /*string for name for basis*/
  Char minname[256], maxname[256], ppdecname[256], xunitsname[256],
       yunitsname[256];
      /*strings for units*/
  double min, max, realpoints;   /*actual values for min,max, # points*/
  long points;   /*total number of points*/
  double *xvec, *yvec;


  v_curverec *fcurve;   /*pointer to curve*/
  v_paramrec *yparam;   /*pointer to parameters*/


  boolean Ok;   /*status of parsing*/
  long count1;   /*counting variables*/
  Char STR1[256], STR3[256];



  strcpy(buffer, buffer_);
  v_exstrword(buffer, lcurvename);
  v_needsep(buffer, '=');
  v_exstrword(buffer, minname);
  v_needsep(buffer, ':');
  v_exstrword(buffer, maxname);
  v_needsep(buffer, ':');
  v_exstrword(buffer, ppdecname);
  v_needsep(buffer, ':');
  v_exstrword(buffer, xunitsname);
  v_needsep(buffer, ':');
  v_exstrword(buffer, yunitsname);

  Ok = false;
  if (v_parsereal(minname, &min)) {
    if (v_parsereal(maxname, &max)) {
      if (v_parsereal(ppdecname, &realpoints)) {
	Ok = true;
	if (max <= min) {
	  sprintf(STR3, "%g less than or equal to %g", max, min);
	  v_failmsg(STR3);
	  Ok = false;
	}
	points = (long)floor(realpoints + 0.5);
	if (points <= 0) {
	  sprintf(STR1, "%ld not a positive integer ", points);
	  v_failmsg(STR1);
	  Ok = false;
	}
      } else
	v_failmsg("<points per decade> not a number");
    } else
      v_failmsg("<max> not a number");
  } else
    v_failmsg("<min> not a number");
  if (!Ok)
    return;
  v_newvector(&xvec, points);
  v_newvector(&yvec, points);
  for (count1 = 1; count1 <= points; count1++) {
    xvec[count1 - 1] = (max * (count1 - 1) + min * (points - count1)) /
		       (points - 1);
    yvec[count1 - 1] = v_badvalue;
  }
  v_addcurve(points, xvec, yvec, xunitsname, yunitsname, lcurvename);
  v_disposevector(&xvec, points);
  v_disposevector(&yvec, points);
}


/*******************************************************************************/

Static Void MT_AddCmd_LinBasis()
{

  /*******************************************************************************/
  _PROCEDURE TEMP;

  TEMP.proc = (Anyptr)MT_DoCmd_LinBasis;
  TEMP.link = (Anyptr)NULL;
  v_addcmd("MT_linbasis", TEMP, "MT_linbasis",
	   "makes a linear basis with units");
  v_addhelp("MT_linbasis");
  v_addhelp("MT_linbasis <curve> = <min>:<max>:<points>:<xunits>:<xunits>");
  v_addhelp("makes a linear basis with units");
}




/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/

/*  Highest level procedures that view expects to recieve, and relatives       */

/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/


/*******************************************************************************/
/*    Add Procedures for Global Commands                                       */

Static Void MT_allinst_addcmd()
{

  /*******************************************************************************/
  MT_AddCmd_init();   /*Inits all instruments*/
  MT_AddCmd_uninit();   /*Uninits all instruments*/
  MT_AddCmd_reset();   /*Resets state of all instruments*/
  MT_AddCmd_update();   /*Updates all instruments*/
  MT_AddCmd_Install();   /*Installs new instruments*/
  MT_AddCmd_Fill();   /*Fills a curve with appropriate data*/
  MT_AddCmd_LogBasis();   /*Makes nice logarithmic bases*/
  MT_AddCmd_LinBasis();   /*Makes nice linear bases*/
}


/*******************************************************************************/
/* initializes viewtool                                                        */

Void MT_viewinit()
{

  /*******************************************************************************/
  /*set up device table*/

  MT_Init_devlist();

  /*make parameters for all instruments*/

  MT_allinst_execute(mt_makeparam, "*");

  /*next, add global commands*/

  MT_allinst_addcmd();   /*add all commands that affect all instruments*/

}


/*******************************************************************************/
/* provides safe exit for viewtool                                             */

Void MT_exit()
{

  /*******************************************************************************/
}





/* End. */
