/* cmloop.f -- translated by f2c (version 19980913).
   You must link the resulting object file with the libraries:
	-lf2c -lm   (in that order)
*/

#include "f2c.h"

/* Table of constant values */

static integer c__2 = 2;
static integer c__7 = 7;
static integer c__3 = 3;
static integer c__1 = 1;
static integer c__78 = 78;
static logical c_false = FALSE_;

/* $Proceedure CMLOOP ( Command line loop ) */

/* Subroutine */ int cmloop_(char *delim, char *prompt, char *lognam, char *
	versn, S_fp greet, S_fp preprc, S_fp action, ftnlen delim_len, ftnlen 
	prompt_len, ftnlen lognam_len, ftnlen versn_len)
{
    /* Initialized data */

    static char spcial[8*2] = "        " "?       ";

    /* System generated locals */
    address a__1[2], a__2[7], a__3[3];
    integer i__1[2], i__2[7], i__3[3], i__4;

    /* Builtin functions */
    /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen), s_cat(char *,
	     char **, integer *, integer *, ftnlen);
    integer s_rnge(char *, integer, char *, integer);

    /* Local variables */
    extern /* Subroutine */ int echo_(char *, char *, ftnlen, ftnlen);
    extern logical have_(char *, ftnlen);
    static integer from;
    static logical trap;
    static integer rest, l;
    static logical dolog;
    extern integer ltrim_(char *, ftnlen);
    static char error[1760*2], com2do[1024];
    extern logical no_(char *, ftnlen);
    extern /* Subroutine */ int logchk_(char *, char *, logical *, ftnlen, 
	    ftnlen), cmredo_(char *, integer *, logical *, ftnlen);
    extern integer isrchc_(char *, integer *, char *, ftnlen, ftnlen);
    static char commnd[1024], errflg[32];
    extern logical cmmore_(char *, ftnlen);
    extern /* Subroutine */ int setdel_(char *, ftnlen), erract_(char *, char 
	    *, ftnlen, ftnlen);
    static char usenam[255];
    extern /* Subroutine */ int errdev_(char *, char *, ftnlen, ftnlen);
    static logical problm;
    extern /* Subroutine */ int setdap_(char *, char *, ftnlen, ftnlen), 
	    getcom_(char *, integer *, ftnlen), edtcom_(char *, char *, char *
	    , integer *, ftnlen, ftnlen, ftnlen), builtn_(char *, logical *, 
	    char *, ftnlen, ftnlen), nsplog_(char *, logical *, ftnlen), 
	    nspend_(void), trnlat_(char *, char *, ftnlen, ftnlen), nsplgs_(
	    char *, char *, char *, ftnlen, ftnlen, ftnlen);
    static char hstyle[120];
    extern /* Subroutine */ int nsperr_(char *, char *, ftnlen, ftnlen), 
	    nspopl_(char *, char *, ftnlen, ftnlen);
    static char lstyle[120];
    extern /* Subroutine */ int cmstup_(void);
    extern integer qrtrim_(char *, ftnlen);
    extern /* Subroutine */ int nspslr_(integer *, integer *);
    static char sstyle[120];
    extern /* Subroutine */ int ressym_(char *, char *, ftnlen, ftnlen);
    static char vstyle[120];
    extern /* Subroutine */ int nspsty_(char *, char *, ftnlen, ftnlen);
    static logical log__[4], hit;

/* $ Abstract */

/*     This routine handles the main processing loop of a */
/*     command driven program. */

/* $ Required_Reading */

/*     None. */

/* $ Keywords */

/*     INTERFACE */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     DELIM      I   Non-blank character used to delimit commands */
/*     PROMPT     I   Prompt to let the user know input is expected */
/*     LOGNAM     I   Name pattern of file where commands will be logged */
/*     VERSN      I   Program name and version */
/*     INTIZE     S   Subroutine that initializes I/O facilities */
/*     GREET      S   Displays a banner at program startup */
/*     ACTION     S   The command parser and processor. */

/* $ Detailed_Input */

/*     DELIM     is a character that will be used to tell the */
/*               program that a command has ended. Commands may */
/*               extend over as many lines as allowed by the */
/*               configuration include file.  They end on the */
/*               first line on which the delimiter character is */
/*               encountered. THIS CHARACTER MUST NOT BE "?" */

/*     PROMPT    is a string used to prompt the user for commands. */
/*               Typically, this is the name of the program that */
/*               calles CMLOOP. */

/*     LOGNAM    is a pattern to use when creating the name of */
/*               a file to which all commands will be written. */
/*               This can be hard coded in the calling */
/*               program, or may be determined by a file naming */
/*               convention such as is provided by Christen */
/*               and NOMEN. */

/*     VERSN     is a string that may contain anything you would */
/*               like to appear as descriptive text in the first */
/*               line of the log file (and possibly in the greeting */
/*               presented by the program)  Something like */
/*               '<program name> --- Version X.Y' would be appropriate. */
/*               For example if your programs name is KINDLE and you */
/*               are at version 4.2.3 of your program a good value for */
/*               VERSN would be */

/*               'KINDLE --- Version 4.2.3' */

/*               Your greeting routine can make use of this when */
/*               displaying your program's greeting.  In this way */
/*               you can centralize the name and version number of */
/*               your program at a high level or in a subroutine and */
/*               simply make the information available to CMLOOP so */
/*               that the automatic aspects of presenting this */
/*               information can be handled for you. */

/*     GREET     is a routine that displays a message at program */
/*               startup.  This should contain the version number */
/*               of the program, any general instructions such */
/*               as how to get help and who the author or organization */
/*               is that is responsible for this program. GREET */
/*               takes a single argument VERSN which you supply in */
/*               your call to CMLOOP.  It may also have */
/*               initializations that override various items set */
/*               up prior to the call to GREET such as the style */
/*               used for displaying error messages.  GREET */
/*               is the action taken by CMLOOP  before commencing the */
/*               loop of fetching and processing commands. */

/*     PREPRC    is a command preprocessor.  It might remove */
/*               non-printing characters such as TABS, resolve */
/*               symbols and convert units to expected ranges. */

/*     ACTION    is a routine responsible for action upon the commands */
/*               entered by a user at the keyboard. ACTION has two */
/*               arguments COMMAND a string input and ERROR a two */
/*               dimensional array for error and diagnostic output. */
/*               The first message should point to the the problem */
/*               assuming the user is aware of the context in which */
/*               the problem occurred.  The second message will */
/*               have more detailed information including trace */
/*               and other technical information. */

/* $ Detailed_Output */

/*     None. */

/* $ Parameters */

/*     The parameters COMSIZ and ERRSIZ are given in the include */
/*     file commdpar.inc. */

/*     COMSIZ  is maximum number of characters that can be present */
/*             in a command. */

/*     ERRSIZ  is the maximum number of characters that can be used */
/*             when creating a diagnostic message. */

/* $ Exceptions */

/*     None.  This routine cannot detect any errors in its inputs */
/*     and all commands are regarded as legal input at this level. */
/*     Some can be acted on while others cannot.  Commands that */
/*     can not be exercised are expected to return diagnostics */
/*     in the array ERROR.  These are then reported by the */
/*     program to the user via his/her terminal. */

/* $ Files */

/*     The file specified by LOGFIL will be opened if possible */
/*     and all user commands and messages will be written to this */
/*     file. */

/*     Other files may be used a run time by "STARTing" a command */
/*     sequence file. Or by some result of the activity of the */
/*     user supplied routines ACTION, GREET, PREPRC. */

/* $ Particulars */

/*     This routine organizes the main loop of a command line */
/*     program so that the calling program can automatically */
/*     log files that a user enters, report errors in a uniform */
/*     manner and make use of sequences of commands stored in */
/*     files. The calling program supplies routines that handle */
/*     the chores of greeting the user and performing special */
/*     program initializations and performing actions based upon */
/*     the commands supplied by the user.  By making use of this */
/*     routine and its subordinates, the user inherits a flexible */
/*     I/O system and command interface freeing him/her to concentrate */
/*     on the actions of the program. */

/*     However, there is a minor price incurred by making use of */
/*     this routine.  Several commands have specific meanings that */
/*     the user cannot override.  They are commands that start with: */

/*        start */
/*        exit */
/*        stop */
/*        quit */
/*        echo */
/*        no echo */
/*        demo on */
/*        demo off */
/*        wait on */
/*        wait off */
/*        pause */
/*        ? */
/*     These commands are case insensitive with respect to the */
/*     words presented above. */

/* $ Examples */

/*     None. */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     W.L. Taber    (JPL) */

/* $ Version */

/* -     Command Loop Configured Version 6.0.0, 20-JUN-2000 (WLT) */

/*         Added the ability to run the loop without logging */
/*         of inputs. */

/* -     Command Loop Configured Version 5.0.0, 23-MAR-2000 (WLT) */

/*         Modified the routine to call NSPEND instead of FINISH */
/*         now that NSPIO has been redone. */

/* -     Command Loop Configured Version 4.0.0, 20-NOV-1995 (WLT) */

/*         Added ability to run programs in batch mode and to */
/*         start procedures at program startup. */

/* -     Command Loop Configured Version 3.0.0, 1-AUG-1995 (WLT) */

/*         The routine was modified to better support command */
/*         pre-processing.  In particular symbol definition */
/*         and resolution is now supported. */

/* -     Command Loop Configured Version 2.0.0, 19-JUL-1995 (WLT) */

/*         A slight change was made so that the command delimiter */
/*         is now stored in the routine GETDEL.  Also errors */
/*         are now checked after command pre-processing has */
/*         been performed. */

/* -     Command Loop Configured Version 1.0.0, 3-MAY-1994 (WLT) */

/*         This is the configured version of the Command Loop */
/*         software as of May 4, 1994 */

/* -    Beta Version 1.0.0, 8-OCT-1993 (WLT) */

/* -& */

/*     Language Sensitive Strings */

/* $ Version */

/* -     Command Loop Configured Version 1.0.0, 3-MAY-1994 (WLT) */

/*         This is the configured version of the Command Loop */
/*         software as of May 4, 1994 */

/*     The following parameters are the system parameters required */
/*     by PERCY.  Be sure to read any notes before adjusting these */

/*     The maximum number of commands that can be buffered is */
/*     determined by the value of MAXCOM.  This parameter is */
/*     used primarily by NXTCOM. */

/*     The parameter FILEN is the maximum length of a file name */
/*     on a particular system. */

/*     The parameter COMSIZ is the maximum length allowed for a */
/*     command. */

/*     The parameter ERRSIZ is the maximum length allowed for */
/*     error messages. */

/*     The parameter STYSIZ is the maximum length expected for */
/*     a NICEPR style string. */

/*     The following are for special commands that will not be */
/*     processed by ACTION. */

/*     Store the delimiter used by the program incase someone */
/*     else needs to know later on. */

    setdel_(delim, delim_len);

/*     First, set up the SPICELIB error handling. */

    s_copy(error, " ", (ftnlen)1760, (ftnlen)1);
    s_copy(error + 1760, " ", (ftnlen)1760, (ftnlen)1);
    s_copy(commnd, " ", (ftnlen)1024, (ftnlen)1);
    log__[0] = FALSE_;
    log__[1] = FALSE_;
    log__[2] = TRUE_;
    log__[3] = TRUE_;
    erract_("SET", "RETURN", (ftnlen)3, (ftnlen)6);
    errdev_("SET", "NULL", (ftnlen)3, (ftnlen)4);

/*     Set the prompt for the program. */

    setdap_(delim, prompt, delim_len, prompt_len);

/*     The following styles are for reporting errors to the */
/*     screen and log file respectively. */

    trnlat_("ERRFLAG", errflg, (ftnlen)7, (ftnlen)32);
/* Writing concatenation */
    i__1[0] = 38, a__1[0] = "HARDSPACE ^ NEWLINE /cr VTAB /vt FLAG ";
    i__1[1] = 32, a__1[1] = errflg;
    s_cat(sstyle, a__1, i__1, &c__2, (ftnlen)120);
/* Writing concatenation */
    i__2[0] = 38, a__2[0] = "HARDSPACE ^ NEWLINE /cr VTAB /vt FLAG ";
    i__2[1] = 1, a__2[1] = delim;
    i__2[2] = qrtrim_(errflg, (ftnlen)32), a__2[2] = errflg;
    i__2[3] = 8, a__2[3] = " LEADER ";
    i__2[4] = 1, a__2[4] = delim;
    i__2[5] = 3, a__2[5] = "-- ";
    i__2[6] = 16, a__2[6] = "LEFT 1 RIGHT 72 ";
    s_cat(lstyle, a__2, i__2, &c__7, (ftnlen)120);

/*     The following styles will be used for logging of */
/*     commands and for commenting them out. */

    s_copy(vstyle, "LEFT 1 RIGHT 78 ", (ftnlen)120, (ftnlen)16);
/* Writing concatenation */
    i__3[0] = 23, a__3[0] = "LEFT 1 RIGHT 78 LEADER ";
    i__3[1] = 1, a__3[1] = delim;
    i__3[2] = 3, a__3[2] = "-- ";
    s_cat(hstyle, a__3, i__3, &c__3, (ftnlen)120);
    nspsty_(sstyle, lstyle, (ftnlen)120, (ftnlen)120);
    nsplgs_(vstyle, hstyle, delim, (ftnlen)120, (ftnlen)120, delim_len);
    nspslr_(&c__1, &c__78);

/*     See whether or not a log file should be used and if so */
/*     what it's name should be. */

    logchk_(lognam, usenam, &dolog, lognam_len, (ftnlen)255);

/*     Open a log file. */

    if (dolog) {
	nspopl_(usenam, versn, (ftnlen)255, versn_len);
    }
    if (have_(error, (ftnlen)1760)) {
	nsperr_(commnd, error, (ftnlen)1024, (ftnlen)1760);
    }

/*     Present a greeting to the user and perform any override */
/*     or special initializations that need to be local to this */
/*     routine. */

    (*greet)(versn, versn_len);

/*     Get the input command line.  This may have */
/*     several useful bits of information to tell us how */
/*     to run the program. */

/*     -b      means run the program in batch mode.  In this case */
/*             we should never prompt the user for information. */

/*     -start  means we have a startup file to use and we want to */
/*             use the name of that file to determine how to */
/*             proceed. */

    cmstup_();

/*     Fetch and log the first command. */

    trap = TRUE_;

/*     Get the next command and resolve any symbols or */
/*     queries that might show up in it, */

    while(trap) {
	getcom_(com2do, &from, (ftnlen)1024);
	edtcom_(delim, prompt, com2do, &from, delim_len, prompt_len, (ftnlen)
		1024);
	if (no_(error, (ftnlen)1760) && log__[(i__4 = from) < 4 && 0 <= i__4 ?
		 i__4 : s_rnge("log", i__4, "cmloop_", (ftnlen)405)]) {
	    nsplog_(com2do, &c_false, (ftnlen)1024);
	}
	if (no_(error, (ftnlen)1760)) {
	    ressym_(com2do, commnd, (ftnlen)1024, (ftnlen)1024);
	    echo_(com2do, commnd, (ftnlen)1024, (ftnlen)1024);
	}
	if (no_(error, (ftnlen)1760)) {
	    cmredo_(commnd, &from, &trap, (ftnlen)1024);
	}
	if (have_(error, (ftnlen)1760)) {
	    trap = FALSE_;
	}
    }

/*     Now apply the user's preprocessing software */
/*     to the comman. */

    s_copy(com2do, commnd, (ftnlen)1024, (ftnlen)1024);
    (*preprc)(com2do, commnd, (ftnlen)1024, (ftnlen)1024);

/*     Now process commands until we get an EXIT command. */

    while(cmmore_(commnd, (ftnlen)1024)) {

/*        Perform any preprocessing that can be performed easily */
/*        on this command. */

	if (no_(error, (ftnlen)1760)) {
	    builtn_(commnd, &hit, error, (ftnlen)1024, (ftnlen)1760);
	}
	if (no_(error, (ftnlen)1760) && ! hit) {
	    l = ltrim_(commnd, (ftnlen)1024);
	    rest = qrtrim_(commnd, (ftnlen)1024) + 1;
	    if (isrchc_(commnd + (l - 1), &c__2, spcial, rest - (l - 1), (
		    ftnlen)8) == 0) {
		(*action)(commnd, error, (ftnlen)1024, (ftnlen)1760);
	    }
	}
	problm = have_(error, (ftnlen)1760);

/*        Process any errors that were diagnosed. */

	nsperr_(commnd, error, (ftnlen)1024, (ftnlen)1760);

/*        Fetch and log the next command. */

	trap = TRUE_;
	while(trap) {
	    getcom_(com2do, &from, (ftnlen)1024);
	    edtcom_(delim, prompt, com2do, &from, delim_len, prompt_len, (
		    ftnlen)1024);
	    if (no_(error, (ftnlen)1760) && log__[(i__4 = from) < 4 && 0 <= 
		    i__4 ? i__4 : s_rnge("log", i__4, "cmloop_", (ftnlen)471)]
		    ) {
		nsplog_(com2do, &c_false, (ftnlen)1024);
	    }
	    if (no_(error, (ftnlen)1760)) {
		ressym_(com2do, commnd, (ftnlen)1024, (ftnlen)1024);
		echo_(com2do, commnd, (ftnlen)1024, (ftnlen)1024);
	    }
	    if (no_(error, (ftnlen)1760)) {
		cmredo_(commnd, &from, &trap, (ftnlen)1024);
	    }
	    if (have_(error, (ftnlen)1760)) {
		trap = FALSE_;
	    }
	}

/*        Now apply the user's preprocessing software */
/*        to the comman. */

	s_copy(com2do, commnd, (ftnlen)1024, (ftnlen)1024);
	(*preprc)(com2do, commnd, (ftnlen)1024, (ftnlen)1024);
    }

/*     Take care of closing files and so on. */

    if (log__[(i__4 = from) < 4 && 0 <= i__4 ? i__4 : s_rnge("log", i__4, 
	    "cmloop_", (ftnlen)501)]) {
	nspend_();
    }
    return 0;
} /* cmloop_ */