/******************************************************************************
 *
 *	I N I T _ A R I T H (void)
 *
 * Initialise arithmetic constants.
 *
 * All this does at the moment is initialise the static variable ICL_MIN_INT
 * and calculate ICL values for constants 180/PI and PI/180 for degrees and
 * radians conversion.
 *
 * ICL_MIN_INT is calculated by host independent calculation. It does this by
 * placing 1 in an integer and repeatedly shifting it left (guaranteed to be
 * logical shift by C language) until it becomes negative.  The resulting
 * pattern 100000000...00 will be the minimum integer value in 2's complement
 * form.
 * This avoids dependence on limits.h containing sensible value for INT_MIN
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	H D S _ F L U S H
 *
 * Flush the memory resident buffers to disk - simply need to call HDS_FREE
 * to do this.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N I T _ H D S F I L E (void)
 *
 * Create (or connect to an existing) HDS file used to communicate ICL
 * variables between ICL and ADAM tasks.
 *
 * Author: B.K. McIlwrath 25-NOV-1993
 *
 * The following HDS component structure is created:
 *
 *	ICLVARS			- top level
 *	   <PID>        	- structure name based on the current ICL pid.
 *		VARIABLES       - Structure containing ICL variables.
 *
 * Returns the inherited status code from the HDS routines - SAI__OK if this
 * routine succeeds
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	D E I N I T _ H D S F I L E (void)
 *
 * Close down HDS variable file - called during ICL termination.
 *
 * Author: B.K. McIlwrath 01-DEC-1993
 *
 * Returns the inherited status code from the HDS routines - SAI__OK if this
 * routine succeeds
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N A M E _ I N T E R P R E T _ H D S (node *n, int op)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	 R E L O A D _ V A R S _ H D S (void)
 *
 ******************************************************************************
 */


/*****************************************************************************
 * OPENPAR
 *
 * Purpose:
 *    Obtain a locator for a task parameter file.
 *
 * Arguments:
 *    taskname = *char (Given)
 *       The task name
 *    action = *char (Given)
 *       The action name
 *    mode = *char (Given)
 *       The mode in which the file is to be opened ( see HDS_OPEN ).
 *    loc = HDSLoc*  (Given)
 *       A locator for the top level of the file
 *    status = *int (Given and Returned)
 *       The global status
 *
 * Description:
 *    The filename is assembled by appending GLOBAL to hds_path which has
 *    been set in hds_init.
 *    If the file does not exist, and it is to be opened for writing, it is
 *    created.
 *
 * Author:
 *    AJC: A.J. Chipperfield (STARLINK)
 *
 *****************************************************************************
 */


/*
 ******************************************************************************
 *
 * P R O C _ G E T P A R ( node *n )
 *
 * GETPAR taskname parametername (variable)
 *
 * Get the value of a task's parameter from the task's parameter file
 *
 * Author: A J Chipperfield
 *
 * History:
 *   13-OCT-1993 (AJC)
 *      Original version
 *   14-JUN-1995 (BKM)
 *      Correct EMS usage
 *
 ******************************************************************************
 */


/*****************************************************************************
 * OPENGLOBAL
 *
 * Purpose:
 *    Obtain a locator for the GLOBAL parameter file - creating it if
 *    necessary.
 *
 * Arguments:
 *    mode = *char (Given)
 *       The mode in which the file is to be opened ( see HDS_OPEN ).
 *    loc = *char  (Given)
 *       A locator for the top level of the file.
 *    loc_length = int (Given)
 *       Length of loc
 *    status = *int (Given and Returned)
 *       The global status
 *
 * Description:
 *    The filename is assembled by appending GLOBAL to hds_path which has
 *    been set in hds_init.
 *    If the file does not exist, and it is to be opened for writing, it is
 *    created.
 *
 * Author:
 *    AJC: A.J. Chipperfield (STARLINK)
 *
 *****************************************************************************
 */


/*
 *****************************************************************************
 * ENSURE_EXISTS
 *
 * Purpose:
 *    To ensure that a component of the required type exists - creating it
 *    if necessary.
 *
 * Arguments:
 *    loc = *HDSLoc  (Given)
 *       A locator for the structure in which the named component is to exist
 *    parname = *char (Given)
 *       The name of the component which must exist
 *    type = *char (Given)
 *       The required type
 *    btype = *char (Given)
 *       The type to be created if type is "?" and the component does not
 *       exist.
 *    ploc = **HDSLoc (Returned)
 *       A locator for the named component.
 *    status = *int (Given and Returned)
 *       The global status
 *
 * Description:
 *    If the named component exists and is of the right type, a locator to
 *    it is returned. If the required type is given as "?", the type of the
 *    component may be any primitive type.
 *    If the component exists, and is of the wrong type, it is deleted and
 *    a component of the right type created.
 *    If the named component does not exist, a component of the right type
 *    created. If type is specified as "?",  a component of the type given
 *    by the btype argument is created.
 *    In all cases a locator for the named component is returned in ploc.
 *
 * Author:
 *    AJC: A.J. Chipperfield (STARLINK)
 *
 *****************************************************************************
 */


/*
 ******************************************************************************
 *
 * P R O C _ S E T P A R ( node *n )
 *
 * SETPAR taskname parametername value
 *
 * Set the value of a task's parameter in the task's parameter file
 * The specifed parameter file must exist and have the specified action
 * component in it. However, if a component for the specified parameter
 * does not exist, one will be created of type _CHAR*132 unless the
 * value starts with @, in which case it is assumed to be a name and a
 * `name' component will be created.
 *
 * Author: A J Chipperfield
 *
 * History:
 *   13-OCT-1993 (AJC)
 *      Original version
 *   14-JUN-1995 (BKM)
 *      Correct EMS usage
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ G E T G L O B A L ( node *n )
 *
 * GETGLOBAL parametername (variable)
 *
 * Get the value of a GLOBAL parameter from the GLOBAL parameter file
 *
 * Author: A J Chipperfield
 *
 * History:
 *   13-OCT-1993 (AJC)
 *      Original version
 *   14-JUN-1995 (BKM)
 *      Correct EMS usage
 *
 *********************************************************************
 */


/*
 ******************************************************************************
 *
 *	P R O C _ S E T G L O B A L ( node *n )
 *
 * SETGLOBAL parametername value
 *
 * Set the value of a GLOBAL parameter in the GLOBAL parameter file
 * If a component for the specified parameter does not exist, one will
 * be created of type _CHAR*132 unless the value starts with @, in
 * which case it is assumed to be a name and a `name' component will be
 * created.
 *
 * Author: A J Chipperfield
 *
 * History:
 *   13-OCT-1993 (AJC)
 *      Original version
 *   14-JUN-1995 (BKM)
 *      Correct EMS usage
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ C R E A T E G L O B A L ( node *n )
 *
 * CREATEGLOBAL parametername type
 *
 * Set the value of a GLOBAL parameter in the GLOBAL parameter file.
 * If a component for the specified parameter already exists, it will
 * deleted and one of the specified type created.
 * If type is ADAM_PARNAME, a 'name' structure will be created.
 *
 * Author: A J Chipperfield
 *
 * History:
 *   13-OCT-1993 (AJC)
 *      Original version
 *   14-JUN-1995 (BKM)
 *      Correct EMS usage
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N I T _ H D S (void)
 *
 * Initialise ICL's use of HDS - called during ICL initialisation.
 *
 * Author: B.K. McIlwrath 25-NOV-1993
 *
 * Returns the inherited status code from the HDS routines - SAI__OK if this
 * routine succeeds
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N I T R E C A L L (void)
 *
 * Initialize the memory storage for use by the command line recall system.
 * Up to SAVELINES of text are stored.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A D D T O R E C A L L (char line[])
 *
 * Add a line of text ('line') to the recall buffer at the current position.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R E V L I N E (void)
 *
 * Return a pointer to the previous input line or CHARNIL if none.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N E X T L I N E (void)
 *
 * Return a pointer to the next line in the buffer
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C O D E S P E C I A L K E Y (void)
 *
 * Examine the raw input buffer 'inbuff' for a sequence of characters
 * matching a special operation defined above. Also processes control keys
 * and DELETE .
 *
 * Can also return SUBSTRING (partial match - await more characters arriving)
 * or NOMATCH.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *      P O S B O L (int del, int prlen, int cpos, int epos)
 *
 * Position at beginning of current prompt line
 * Where prlen is the length of the prompt string.
 *       cpos is the current cursor position in the input string.
 *       epos is the current end of the input string (only used in deleting
 *            line.
 * If del is true, clear the line.
 *
 * Static variable COLS should be set to the current screen width.
 *
 * In the case of dumb terminals (i.e. where we cannot move the cursor up)
 * we position at the start of the current display line.
 *
 ******************************************************************************
*/


/******************************************************************************
 *
 *  R E D O L I N E ( int complete, int prlen, int cpos, int epos, int forwd )
 *
 * Re-display a line leaving the cursor in position cpos.
 * We assume that the static variables prompt and inputline are set up
 * correctly and the cursor is at the start of the line. (This is the complete
 * prompt and reply display on most terminals but only the current display
 * line on dumb terminals ie where we cannot move the cursor up.)
 * Static variable COLS must be set to the screen width.
 *
 * Arguments:
 *    complete - true if the line is to be completely re-written
 *    prlen    - the length of the prompt
 *    cpos     - the required position within inputline of the cursor
 *    epos     - the position within inputline of the end (null character).
 *    forwd    - true if we are proceeding forwards (if cursor at beginning
 *               of line, do we display the next or previous display line)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A D D T O Q U E U E (int type, char *prompt, char *retaddr, int seqno)
 *
 * Add an I/O request to the pending queue.
 *
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	M Y W N E W L I N E (WINDOW *win, int wrows)
 *
 * Generate a newline effect in window 'win' which is 'wrows' lines long
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	M Y W M O V E B A C K O N E (WINDOW *win)
 *
 * Move window position back one character position. If at start is line wrap
 * back to end of previous line
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	M Y W M O V E F O R W A R D O N E (WINDOW *win, int wrows)
 *
 * Move window position forward one position. If at the end of a row wrap to
 * the first character position of the next row.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	M Y W A D D S T R (WINDOW *win, char * str)
 *
 * Adds a string 'str' to a window 'win'. If the string would wrap off the
 * end of the window row it is truncated to fit
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C L E A R Q U E U E (void)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C E S S Q U E U E (void)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O I S E C H A R (char ch)
 *
 *      Is word separator for input editing
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	S P A C E C H A R (char ch)
 *
 *      Is filename separator for filename completion
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O R M A L C H A R A C T E R (char ch)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	R I N G B E L L (void)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C L E A R L I N E (void)
 *
 * Clear the current line when in LINEMODE
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	R E D I S P L A Y (char *w)
 *
 *  Redisplay the input line, including prompt. Leave cursor at end
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P O S I T I O N R E D I S P L A Y (char *w)
 *
 *  Redisplay the input line, including prompt, and reposition cursor within it
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F I L E N A M E _ C O M P L E T E ( )
 *
 * This routine is called to complete a filename in the keyboard input routine
 * It assumes the inputline is set up as normal with inpl_cpos pointing at
 * the current character and inpl_epos pointing at the end.
 ******************************************************************************
 */


/******************************************************************************
 *
 *	K E Y B O A R D _ I N P U T (int void)
 *
 * This routine is called when there is keyboard input to process.
 *
 * icl_io uses single character input and locally handles all buffering and
 * processing of characters. When a complete input line is obtained this is
 * send to the ICL process to arrive on its 'ast-input' messys queue.
 *
 * This routine is normally called from the main select() loop in main() but
 * is also used to process typeahead when it is called directly.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	S H E L L _ C O M M A N D ( char *command )
 *
 * This routine runs a command in the c-shell
 *
 * Returns either:
 *	TRUE and stdout from the command
 *	OR
 *	FALSE and any error text produced by the shell on error
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C O M M A N D _ I N P U T (void)
 *
 * This routine is called to process command to icl_io from the parent ICL
 * process. ICL creates a Unix pipe just before forking this process and
 * the commands (which are C structures passed as a byte stream) arrive here.
 *
 * This routine is called from the main select() loop in main()
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	R E S I Z E _ H A N D L E R ( int signo )
 *
 * This function is called when we get a window resize event (n.b. only on
 * local windows and remotely connected ones using rlogin - NOT telnet!) and
 * resets the variables 'COLS' and 'LINES' (declared in curses.h) accordingly.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C N T L C _ H A N D L E R ( int signo )
 *
 * We arrange for this handler to be called when the tty driver generates
 * a SIGINT or SIGQUIT.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C N T L Z _ H A N D L E R ( int signo )
 *
 * We arrange for this handler to be called when the tty driver generates
 * a SIGTSTP (CNTL/Z). A flag (interrupted) is set and an action routine
 * (do_cntlz) is called at an appropriate point.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	D O _ C N T L Z
 *
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	E X I T _ H A N D L E R ( int signo )
 *
 * We arrange for this handler to be called to restore terminal characteristics
 * on process exit.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	S I G  _ H A N D L E R ( int signo )
 *
 * We arrange for this handler to be called for signals which terminate the
 * process - it calls the exit handler to restore terminal characteristics
 * on process exit.
 *
 ******************************************************************************
 */


/*******************************************************************************
*	I N I T S C R E E N (int nolines)
*
* This routine handles the ICL output screen modes and changes between these.
*
* Initially ICL starts in screen state 'INITIAL' and we arrange to move from
* this to 'LINEMODE'.
*
* Further ICL SET (NO)SCREEN commands can change between LINEMODE and
* SCREENMODE and, further, when in SCREENMODE the "fixed" portion of the
* screen can be set to be 'nolines' in size.
*
*******************************************************************************/


/*****************************************************************************
 *
 *	S E T E N V (char *var, char *valu)
 *
 * Set a UNIX environment variable - while the Unix routine putenv() WILL
 * do this it is not guananteed to be available on all systems.
 * If the value is NULL, then delete the environment variable.
 *
 * environ (char **) is an array of strings made available by the environment
 * each string is of the form name=value.  Certain names have builtin
 * meanings such as PATH, HOME, TERM, SHELL, etc.
 *
 * We search each of the environment strings for a match on "var" and, if
 * found and "value" is null, the current environ is shuffled up to overwrite
 * the entry to be deleted.
 * If a match is found and we are changing it, then we, using malloc(),
 * get space for a new string of the form var=value, copy var and value into
 * it and reset the relevant environ element.
 * If the environment does not contain the var, we recreate a complete new
 * environ array using malloc(), copy the old values into it and add a new
 * var=value entry at the end ensuring the last entry is a null string pointer.
 *
 * Returns a zero if successful
 *
 *****************************************************************************
 */


/******************************************************************************
 *
 * 	P R O C _ S E T E N V ()
 *
 * Implements the ICL command SETENV
 *
 * By the time this routine is called get_args() will have been called from
 * builtin_interpret() and this will have set up the arguments to the SETENV
 * command in arglist[].
 * 'nargs' will have been set to the total number of arguments.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 * 	P R O C _ U N S E T E N V ()
 *
 * Implements the ICL command UNSETENV
 *
 * The inverse of SETENV - see above
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 * 	T I M E _ D A T E (int func)
 *
 * Helper function for the ICL TIME() and DATE() functions.
 *
 * Called with an argument of FUNC_DATE this function uses  time(time_t x) to
 * get the current time (seconds since 00:00:00 GMT 1/1/1970), and then
 * localtime(x) to adjust for time zones and breaks the time up into days
 * months etc. It then forms a string representing the day-month-year.
 *
 * FUNC_TIME uses gettimeofday() to get the time of day as a string HH:MM:SS
 *
 * May return CHARNIL if memory exhausts in strcopy().
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F U N C _ D A T E - returns the current date in the form  DD-MM-YY
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F U N C _ T I M E - returns the current time in the form  HH:MM:SS
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F U N C _ S T A T U S (void)
 *
 * This function returns the ICL value true of false depending on whether
 * a system command executed OK.
 *
 * Releated to the use of os_command() (which calls system()) or direct use
 * of system().  Use of system() sets the variable os_status to zero if call
 * executed OK, non zero otherwise
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F U N C _ O K (void)
 *
 * The ICL function OK is not yet implemented on Unix.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 * 	F U N C _ G E T E N V (char *s)
 *
 * getenv(char *s) returns the string associated with the environment
 * variable s  (refer Set_env() for a description of environment
 * variables.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F U N C _ G E T _ S Y M B O L (void)
 *
 * The ICL function GET_SYMBOL() is not yet implemented on Unix.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F U N C _ U N I M P L (void)
 *
 * func_unimpl() is used within the ICL symbol table to produce a suitable
 * message when a ICL function is not yet implemented in the Unix version.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ O S E R R (void)
 *
 * Function which is called when an ICL command which is inappropriate to the
 * Unix version is used.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 * 	F U N C _ F I L E _ E X I S T S (char *s)
 *
 * The function FILE_EXISTS(char *S) returns true if the file, with name s,
 * exists, false otherwise
 *
 * Uses the Unix supplied function access().
 *
 * Returns 0 on success, -1 on failure.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	O S _ C O M M A N D (char *command)
 *
 * Issue a command to Unix.
 *
 * Uses the fact that the iosubsystem process resets the terminal
 * characteristics to before stopping itself on receipt of an
 * IO_COMMAND_SUSPEND from icl. The iosubsystem then stops and awits
 * a SIGCONT signal before proceeding.
 *
 * Returns either the status returned from the shell running the command
 * or -1 if a system service fails.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ S H (node *n)
 *
 * Implements the ICL command "SH [unix_command]"
 *
 * The Unix command may have several parameters.  The whole abbut_interpret()
 * node list formed by the parser for this sequence is pointed to by 'n' and
 * interpreting this causes the command string and all of its parameters
 * to be concatenated together as strings.
 *
 * If no Unix command is given, then the environment variable SHELL is used
 * to run a shell which will accept a series of Unix commands and return to
 * ICL on logout.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ D C L (node *n)
 *
 * Implements the ICL command "DCL [command]"
 *
 * We detect direct mode as the system maintains a stack which is pushed by
 * the name of a procedure on each proc call, and popped on each procedure
 * return. The routine currentproc() returns the name of the currently active
 * procedure or CHARNIL if in direct mode.
 *
 * proc_sh(n) issues the string derived from interpreting the abstract syntax
 * nodes pointed to by n, seen as a string, to Unix.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ E D I T (node *n)
 *
 * Implements the ICL command "EDIT [proc]"
 *
 * Edit procedure 'proc' using the preferred editor (default or SET in
 * proc_set() by user issuing a SET EDITOR command). If the name of the proc
 * is unchanged during the editing session the new version replaces the old.
 * If, however, the name is changed a new procedure results, with the old
 * remaining.
 *
 * The default is set in the environment variable EDITOR or, failing that, vi.
 *
 * We first interpet() the argument in n which will point to the abstract
 * syntax of the proc arguement to the EDIT command. This, seen as a string,
 * forms "name". We lookup the procedure to see if it exists using
 * lookup_symbol(name, SYMPROC).
 * If it does we open a temporary file (name iclout.icldddddd
 * where ddddd is the current process's pid and save the procedure into it
 * using fileaproc().
 * We then call the editor passing it the file iclout.icldddddd
 * (note even if the procedure doe snot exist this still ocurs to allow a new
 * procedure  to be input).
 * On return from the editor with a success status , we use do_load() to
 * parse the file's contents.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *
 *	P R O C _ D E F A U L T (node *n)
 *
 * Implements the ICL command "DEFAULT directory".
 *
 * Set the current working directory for the process running ICL.
 * The directory may be specified in any of the forms accepted by the Unix
 * chdir command.
 *
 * DEFAULT with no parameter displays the current default directory.
 *
 * On entry, n will point to the parsed abstract syntax node form of
 * "directory".
 * This is interpreted and, seen as a string, passed to chdir().
 *
 * When 'n' is null or after changing directory, getcwd() is used to get the
 * current working directory.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ C D (node *n)
 *
 * Implements the ICL command "CD [directory]".
 *
 * Change the current directory.
 *
 * On entry n will point to the parsed abstract syntax node form of directory.
 * This is interpreted and, seen as a string, passed to chdir to change
 * directory.  If "directory" is not provided we change directory to that
 * associated with the HOME environment variable.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ V E R S I O N (node *n)
 *
 * Implements the ICL "VERSION" command.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N I T _ O S (void)
 *
 * Called from main() to initialise the symbol_table to contain entries for
 * Unix dependant functions.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N T E R P R E T _ F A I L (char *routine_name)
 *
 * This routine is only executed if any of the interpret routines are called
 * with an unknown operation code. It causes an icl abort.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U N D E F I N E D _ I N T E R P R E T (node *n, int op)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N T E G E R _ I N T E R P R E T (node *n, int op)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	L O G I C A L _ I N T E R P R E T (node *n, int op)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	R E A L _ I N T E R P R E T (node *n, int op)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	S T R I N G _ I N T E R P R E T (node *n, int op)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	Q U O T E D _ S T R I N G _ I N T E R P R E T (node *n, int op)
 *
 * This function is a derivative of string_interpret() but will return the
 * string with the quotes (removed by fixup_quotes() in lex.l) restored.
 * This is required to pass string values to ICL tasks.
 *
 * Note that the parser cannot generate calls to this function. The function
 * setup_args_task() (in interp.c) which alters the command parse tree to be
 * produce a suitable value string to pass to an ADAM task does this by
 * suistituting this function for string_interpret().
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	O P E N S T R I N G _ I N T E R P R E T (node *n, int op)
 *
 * An "openstring" in ICL is a non-quoted string of characters.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N A M E _ I N T E R P R E T (node *n, int op)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	O P T A R G _ I N T E R P R E T (node *n, int op)
 *
 * Used by the parser to indicate that a formal parameter of a PROCedure
 * (and all subsequent arguments) are optional and, if no actual argument(s)
 * are present the variable within the procedure will be of type <UNDEFINED>.
 * BKM, 04/05/95
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N A M E _ I N T E R P R E T _ N O H D S (node *n, int op)
 *
 * Used by the parser when it is certain that we want the value of the ICL
 * variable and it will never be passed to a task via HDS
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P A R E N _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for syntax of the form
 * ( E x p r e s s i o n ) (within an expression or as part of a comand line).
 *
 * The sub[0] member points to the node to be interpreted to evaluate the
 * expression. Note that this can simply be a name_interpret() node in the
 * case of paranthesised variable names.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C O N C A T _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for syntax of the form
 * "Expression & Expression".
 *
 * The concat_interpret() node has its sub[0] member pointing to the left
 * operand and its sub[1] member to the right operand.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A N D _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for syntax of the form
 * "Expression AND Expression".
 *
 * The and_interpret() node has its sub[0] member pointing to the left
 * operand and its sub[1] member to the right operand.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	O R _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for syntax of the form
 * "Expression OR Expression".
 *
 * The or_interpret() node has its sub[0] member pointing to the left operand
 * and its sub[1] member the right operand.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O T _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for syntax of the form "NOT Expression".
 *
 * The not_interpret() node has its sub[0] member pointing to the operand.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U N I A R Y A R I T H _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for syntax of the form
 * "- (NEGATE) or + (MAKE POSITIVE)  Expression".
 *
 * The uniaryarith_interpret() node has its sub[0] member pointing to the
 * operand and the value.integer component set to the internal code of either
 * SUBTRACT or ADD
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	B I N A R Y O P E R A T O R _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for syntax of the form
 * "expression BINARY ARITHMETIC OPERATOR expression".
 *
 * The binaryoperator_interpret() node is generated for a binary arithmetic
 * operator (add, subtract etc). The sub[0] and sub[1] members point to the
 * left operands respectively and the internal code of the arithmetic operation
 * is in the nodes value.integer component.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	R E L O P E R A T O R _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for ICL syntax of the form
 * "expression R E L A T I O N A L expression".
 *
 * The sub[0] member points to the left operand, sub[1] to the right while
 * the yacc code of the operator is held in the value.integer component of the
 * reloperator_interpret() node. Cannot cause overflow.
 *
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F O R M A T _ I N T E R P R E T (node *n, int op)
 *
 * The parser generates this node for expressions of the form:
 * 	"expression0 : expression1 : expression2"
 * OR	"expression0 : expression1"
 *
 * The sub[0] member of the format_interpret() node points to the expression
 * to be formatted, sub[1] the field_width expression and sub[2] is either NIL
 * or points to the decimal_precision expression.
 *
 * A quirk of the VMS ICL is that operands of the formatting operator (:) have
 * unusual type restrictions. In case this is important the behaviour is
 * faithfully reproduced here!!
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	S A V E _ A R G S (node ***saveloc)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	R E S T O R E _ A R G S (node ***saveloc)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F U N C T I O N _ C A L L _ I N T E R P R E T (node *n, int op)
 *
 * Calls a built-in function by name.
 *
 * We need to save and restore the current argument list as described above,
 * since it may be in use. Note that it must be initialised properly.
 *
 * If the function fails, we do not pop the call stack. This is so that, if the
 * exception is not handled, we can print the call stack at the point of
 * failure when we reach the top level again.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O N A R Y _ F U N C _ I N T E R P R E T (node *n, int op)
 *
 * Interpret a built-in function of no arguments .
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F U N C _ I N T E R P R E T (node *n, int op)
 *
 * Interpret a built-in function which does its own argument processing.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U N A R Y _ F U N C _ I N T E R P R E T (node *n, int op)
 *
 * Interpret a built-in function with one argument.
 *
 * We need to save the contents of arglist[] into local variables (arg1
 * and/or arg2) as in the call to interpret() an argument may call another
 * function which could destroy the the argument array contents.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	B I N A R Y _ F U N C _ I N T E R P R E T (node *n, int op)
 *
 * interpret a built-in function with two arguments .
 *
 * We need to save the contents of arglist[] into local variables (arg1
 * and/or arg2) as the call to interpret() an argument may call another
 * function which could destroy the the argument array contents
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U N A R Y _ I N T E G E R _ F U N C _ I N T E R P R E T
 *						(node *n, int op)
 *
 * Interpret a built-in function with one integer argument and an integer
 * result which cannot generate an exception.
 *
 * We need to save the contents of arglist[] into local variables (arg1 and/or
 * arg2) as the call to interpret() an argument may call another function
 * which could destroy the the argument array contents.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	B I N A R Y _ I N T E G E R _ F U N C _ I N T E R P R E T
 *						(node *n, int op)
 *
 * Interpret a built-in function with two integer arguments and an integer
 * result which cannot generate an exception.
 *
 * We need to save the contents of arglist[] into local variables (arg1 and/or
 * arg2) as the call to interpret() an argument may call another function
 * which could destroy the the argument array contents.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U N A R Y _ N U M E R I C _ F U N C _ I N T E R P R E T
 *						(node *n, int op)
 *
 * Interpret a built-in function with one numeric argument.
 *
 * We need to save the contents of arglist[] into local variables (arg1 and/or
 * arg2) as the call to interpret() an argument may call another function
 * which could destroy the the argument array contents.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	B I N A R Y _ N U M E R I C _ F U N C _ I N T E R P R E T
 *						(node *n, int op)
 *
 * Interpret a built-in function with two numeric arguments.
 *
 * We need to save the contents of arglist[] into local variables (arg1 and/or
 * arg2) as the call to interpret() an argument may call another function
 * which could destroy the the argument array contents.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U N A R Y _ S T R I N G _ F U N C _ I N T E R P R E T
 *						(node *n, int op)
 *
 * Interpret a built-in function with one string argument.
 *
 * We need to save the contents of arglist[] into local variables (arg1 and/or
 * arg2) as the call to interpret() an argument may call another function
 * which could destroy the the argument array contents.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	B I N A R Y _ S T R I N G _ F U N C _ I N T E R P R E T
 *						(node *n, int op)
 *
 * Interpret a built-in function with two string arguments.
 *
 * We need to save the contents of arglist[] into local variables (arg1 and/or
 * arg2) as the call to interpret() an argument may call another function
 * which could destroy the the argument array contents.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	E X C E P T _ I N T E R P R E T (node *n, int op)
 *
 * Actual exceptions are not often stored in nodes (as distinct from exception
 * handlers) One case where they are is when the parser wants to return an
 * exception because of a syntax error.
 *
 * This allows things like evaluation of DEFSTRINGs and the tratment of strings
 * as expressions to be handled robustly.
 *
 * Exception nodes should never be printed.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *  U F A C E _ S E L H E L P
 *
 *  Purpose:
 *     Select the required parameter help.
 *
 *  Language:
 *     C
 *
 *  Description:
 *     Depending on the help specifiers given and the response to the
 *     prompt, the appropriate returns are made in HELPLB, STRING and
 *     LBSRCH.
 *     If one-line help is to be output, return
 *        HELPLB=' ', STRING=' '.
 *     If help library module to be output, return
 *        HELPLB=library name, STRING=key string.
 *     If an error message is to be output, return
 *        HELPLB=' ', STRING=error message.
 *     LBSRCH is intended to indicate whether or not the help system
 *     should prompt for more keys before returning to the parameter
 *     prompt. It is set TRUE if a help library module is to be output
 *     in response to '??'.
 *
 *     The response in user_val is assumed to be either ? or ??.
 *
 *  Algorithm:
 *     The help specifiers will have been extracted from the task's
 *     interface file 'help' and 'helplib'/'helpkey' fields for the
 *     parameter.
 *          '?'  => if 'help' is specified, return blank HELPLB
 *                    and STRING unless it begins with % in which case
 *                    interpret the remainder as for 'helpkey'
 *                   if there is no 'help' specifier but there is a
 *                   'helpkey' specifer, use that.
 *          '??' => if 'helpkey' is specified, use it.
 *                  if there is no 'helpkey' specifier, use 'help'
 *                  specifier, if any.
 *     If multi-line help is indicated in response to a single '?', set
 *     LBSRCH false. If it is indicated in response to '??', set LBSRCH
 *     true to indicate that a search of the library is required.
 *
 *  Authors:
 *     AJC: A J Chipperfield (STARLINK)
 *     {enter_new_authors_here}
 *
 *  History:
 *     10-DEC-1993 (AJC):
 *        Original C version - from the Fortran
 *     {enter_further_changes_here}
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U F A C E _ I N F O R M (int path, char *svalue, int *status)
 *
 *  Purpose:
 *     To output an information message to the user
 *
 *  Language:
 *     C
 *
 *  Description:
 *     The supplied string is terminated correctly, then output via the
 *     normal ICL output mechanism.
 *
 *  Authors:
 *     BKM: B K McIlwrath (STARLINK)
 *     {enter_new_authors_here}
 *
 *  History:
 *     10-DEC-1993 (AJC):
 *        Original removed from adam.c
 *     {enter_further_changes_here}
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U F A C E _ M S G I N F O (int path, char *mname, char *mvalue,
 *                                 int mvlen, int messid,  int messtatus,
 *                                 int *status)
 *
 *  Purpose:
 *     To decode incoming messages
 *
 *  Language:
 *     C
 *
 *  Description:
 *
 *  Authors:
 *     SKR: S K Robinson (INFOMATICS)
 *     AJC: A J Chipperfield (STARLINK)
 *     {enter_new_authors_here}
 *
 *  History:
 *     10-DEC-1993 (AJC):
 *        Original removed from adam.c
 *     {enter_further_changes_here}
 *
 * ****************************************************************************
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U F A C E _ S P L I T V A L (char *valu, char param[], int *parlen,
 *			char prstr[], int *prlen,
 *			char dfault[],int * deflen,char hlptxt[], int *hlplen,
 *			char hlpkey[], int *hkylen, char errmes[], int *errlen,
 *                      int *status)
 *
 *  Purpose:
 *     To split a parameter request message into its constituent parts
 *
 *  Language:
 *     C
 *
 *  Description:
 *     The value string contains substrings separated by nulls as set up by
 *     SUBPAR_PROMPTL.  The substrings are the parameter name, its prompt,
 *     its default value, its one-line help info, and an error message if an
 *     earlier attempt to get its value failed.  This information is put into
 *     variables which can be used by uface_askparam().
 *
 *  Authors:
 *     SKR: S K Robinson (INFOMATICS)
 *     AJC: A J Chipperfield (STARLINK)
 *     {enter_new_authors_here}
 *
 *  History:
 *     10-DEC-1993 (AJC):
 *        Original moved from adam.c
 *     26-JUL-1994 (BKM):
 *        Simplified logic
 *     {enter_further_changes_here}
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U F A C E _ S T A R T O B E Y (char *taskname, char *actionname,
 *                                      char valu[], int *status)
 *  Purpose:
 *     Send OBEY with action 'actionname' and value 'value' to task 'taskname'
 *     Process parameter system interaction until the action starts (indicated
 *     by a DTASK__ACTSTART message).
 *
 *  Language:
 *     C
 *
 *  Description:
 *     The required OBEY message is sent to the task and a reply awaited.
 *
 *     On return status is SAI__OK or indicative of some error which may be
 *     qualified by string returned in value[] (no qualification will have
 *     value set to the null string).
 *
 *  Authors:
 *     BKM: B K McIlwrath (STARLINK)
 *     {enter_new_authors_here}
 *
 *  History:
 *     12-SEP-1994 (BKM):
 *        Original extracted from uface_obeyw()
 *     {enter_further_changes_here}
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U F A C E _ E N D O B E Y  ( int path, int messid, char valu[],
 *                                   int *status)
 *
 *  Purpose:
 *     To wait for completion of an OBEY and handle its return status.
 *
 *  Language:
 *     C
 *
 *  Description:
 *     SEND OBEY has sent an OBEY command to the task on the end of path
 *     'path', transaction 'messid'.  We now wait for its completion.
 *     On return status is SAI__OK or indicative of some error which may be
 *     qualified by returned 'value[]' (no qualification will have value set
 *     to the null string).
 *
 *  Authors:
 *     SKR: S K Robinson (INFOMATICS)
 *     AJC: A J Chipperfield (STARLINK)
 *     {enter_new_authors_here}
 *
 *  History:
 *     10-DEC-1993 (AJC):
 *        Original moved from adam.c
 *     {enter_further_changes_here}
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U F A C E _ O B E Y W (char *taskname, char *actionname, char valu[],
 *                             int *status)
 *  Purpose:
 *     Send OBEY with action 'actionname' and value 'value' to task 'taskname'
 *     and wait for completion.
 *
 *  Language:
 *     C
 *
 *  Description:
 *     The required OBEY message is sent to the task and a reply awaited.
 *
 *     On return status is SAI__OK or indicative of some error which may be
 *     qualified by string returned in value[] (no qualification will have
 *     value set to the null string).
 *
 *  Authors:
 *     SKR: S K Robinson (INFOMATICS)
 *     AJC: A J Chipperfield (STARLINK)
 *     {enter_new_authors_here}
 *
 *  History:
 *     10-DEC-1993 (AJC):
 *        Original moved from adam.c
 *     09-SEP-1994 (BKM):
 *        Correct logic to allow parameter system interaction and use
 *        uface_startobey()
 *     {enter_further_changes_here}
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *      U F A C E _ G E T C O M (char * line, int *status)
 *
 *  Purpose:
 *     Waits for and processes incoming messages to ICL.
 *
 *  Language:
 *     C
 *
 *  Description:
 *     This function loops waiting for messages to arrive. These messages
 *     may be from other ADAM tasks or from the io-subsystem containing ICL
 *     command input. The status of each message received determines the
 *     action to be taken and the appropriate function is called.
 *
 *     This function will return only when an io-subsystem message is received
 *     or in the event of an error
 *
 *  Authors:
 *     SKR: S K Robinson (INFOMATICS)
 *     AJC: A J Chipperfield (STARLINK)
 *     BKM: B K McIlwrath (STARLINK)
 *     {enter_new_authors_here}
 *
 *  History:
 *     10-DEC-1993 (AJC):
 *        Original moved from adam.c
 *     26-JUL-1994 (BKM):
 *        Use ams and extensively revised
 *     {enter_further_changes_here}
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	U F A C E _ I N T E R R U P T (void)
 *
 *  Purpose:
 *     Check for an user interface interrupt.
 *
 *  Method:
 *     The io-subsystem will send an "interrupt" message to our
 *	"external-interrupt" messys queue. We could check for the arrival of
 *	this message quite easily but it is presently ignored (see
 *	uface_getcom()). Instead we return the state of the interrupt flag
 *	set by the SIGINT handler in main()
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 * 	N A R G S _ S H O U L D _ B E (int n)
 *
 * Checks the argument count for an ICL procedure is correct by checking nargs.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N A R G S _ I N _ R A N G E (int low, int high)
 *
 * Checks the argument count for an ICL procedure is within an allowable range.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C O N C A T _ A R G S (int from )
 *
 * Concatenate a proc's evaluated argument list seen as strings into a buffer.
 * The arguments have been stored in arglist[] by get_args(), with nargs
 * set to their number.  As usual all_args points to the node representing
 * the complete argument list.
 * Only part of the argument list is so treated (from the 'from'th one)
 * For efficiency, we can work our way down the argument list held in
 * all_args to the 'from'th one and then rely on the fact that if we
 * interpret an abbut_interpret() node it will do the interpretation
 * and concatenation for us delivering a ICL value (string) result.
 *
 * ** Numbering starts from zero.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 * 	I N S T A L L _ A R G S ( node *n, node *procn)
 *
 * Initially,
 *
 * We are passed a pointer to formal parameter list of the procedure to be
 * executed and get_args() has been called so arglist[0] contains a pointer
 * to the first actual argument node, arglist[1] to the second etc.  nargs
 * is a count of the number of actual args and arglistp points to arglist[0]
 *
 * On a recursive call
 *
 * We are passed a pointer to a subpart of a formal parameter list of the
 * proc to be executed nargs has a count of the unprocessed actuals
 * arglistp points to the current unprocessed actual in arglist[]
 *
 * We note that we delete any existing entry from the proc's symbol table for
 * the parameter.  This is because it is possible, with the SET NOCHECKPARS
 * command to switch off the "too few parameters" exception.
 * This means that the parameter references in the proc are taken
 * as VARIABLE when too few parameters are given on a call and if the next
 * call gives a value to that parameter we end up with two entries in the
 * procs symbol table, one for the parameter and one for the variable from
 * the previous call.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N T E R P R E T (node *n)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	D E S T R O Y (node *n)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R I N T (node *n)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N T E R P R E T _ T O _ R E A L (node *n)
 *
 * A node n is interpreted and then converted to a real value (using
 * real_val() in value.c).
 * An exception may occur during this process and this is returned to the
 * caller if this occurs. If n is meaningless then realzeroval (0.0) is
 * returned.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N T E R P R E T _ T O _ N U M E R I C (node *n)
 *
 * A node 'n' is interpreted and then converted to a numeric value.
 * An exception may occur during this process and this is returned to the
 * calle. If n is meaningless then intzeroval (0) is returned.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N T E R P R E T _ T O _ I N T E G E R (node *n)
 *
 * A node n is interpreted and then converted to a integer value
 * (integer_val() in value.c).  An exception may occur during this process
 * and this is returned to the caller if this occurs. If n is meaningless
 * then intzeroval (0) is returned.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N T E R P R E T _ T O _ S T R I N G (node *n)
 *
 * A node n is interpreted and then converted to a string value (string_val()
 * in value.c).  An exception may occur during this process and this is
 * returned to the caller if this occurs. If n is meaningless then
 * nullstringvalval ((char *)0) is returned.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *		E X P L I S T _ I N T E R P R E T (node *n, int op)
 *
 * Explist nodes are generated to form the formal parameter list in a PROC
 * header and to form a list of actual arguments on a function call.
 * Both these are handled specially and should not be directly interpreted.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A B B U T _ I N T E R P R E T (node *n, int op)
 *
 * An abbut node is used to hold the list of arguments to a procedure call.
 *
 * It is a linked list formed through the the sub[1] member of each node.
 * The sub[0] member points EITHER to
 * 	a string_interpret() node or a open_string_interpret() node
 * OR
 * 	a paren_interpret() node (ie argument was of the form  (...) )
 *
 * The value.logical part of the abbut_interpret node controls the spacing
 * used. TRUE will cause a space to be inserted between the strings while
 * FALSE implies that the strings are concatonated.
 *
 * When interpreted abbut_interpret evaluates any evaluable actual arguments
 * a strings (the paren_interpret() nodes) and then concatenates these with
 * those obtained from string_interpret/open_string_interpret() into a
 * string value.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A B B U T _ Q S T R I N G _ I N T E R P R E T  (node *n, int op)
 *
 * This function is similar to abbut_interpret() but, rather than just
 * concatonating strings it will restore the quotes which were stripped by
 * fixup_quotes() in lex.
 *
 * Used to pass "value strings" to ADAM tasks when ICL and the task are
 * non-interlocked. For example SEND <task> OBEY <action> <parameters>
 * (cf setup_task_hds() )
 *
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P A R A M E T E R _ I N T E R P R E T (node *n, int op)
 *
 * Interpret a formal parameter to a procedure.
 *
 * As we call a procedure we pass the actual arguments to the formals by:
 *
 * Walking the formal parameter list (which is the sub[0] member of the PROC
 * entry) and for each we select the corresponding actual argument.  If the
 * actual argument is a name_interpret() node we are passing by reference and
 * we add the formal to the procedure's symbol table as SYM_PARAMETER with a
 * value node that points to a parameter_interpret() node whose sub[0] member
 * points to the actual's name_interpret() node (whose string_part() member is
 * the actual's identity). The val member is a TYPE_SYMTAB value with its
 * symboltable_part() member pointing to the symbol table of the proc owning
 * the actual.
 *
 * If the corresponding actual was an expression we evaluate it and set the
 * formal's SYM_PARAMETER entry's value member to point to the node
 * representing that value.
 *
 * In both action modes, we should never interpret OR print such a node.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F I N D _ H A N D L E R (node *n, value exc)
 *
 * This routine searches the exception list for the current procedure for an
 * exception handler which matches the given exception name 'exc'. An
 * exception value is a string, the first characters of which
 * contain the name of the exception terminated by a space.
 *
 * iclidentityequal(s,t,n) (utils.c) is used to compare two strings while
 * ignoring case and comparing only the first n characters.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	E X C E P T I O N _ I N T E R P R E T (node *n, int op)
 *
 * An exception is just a sub-tree. It is executed in the same context as the
 * rest of a procedure's statements, so no special action is necessary.
 *
 * The structure has been described earlier
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	E X C E P T I O N _ L I S T _ I N T E R P R E T (node *n, int op)
 *
 * This function ensures that exceptions in a procedure can be LISTed
 * correctly
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	B U I L T I N _ I N T E R P R E T (node *n, int op)
 *
 * Built-in commands are stored in a node as a function pointer.
 * They do all their own argument processing, as built-ins are so diverse.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	D E F S T R I N G _ I N T E R P R E T (node *n, int op)
 *
 * Implements the ICL command "DEFSTRING command equiv_string"
 *
 * This function up a HIDDEN_PROC on execution of proc_defstring() with the
 * name, the evaluated first argument (which must deliver a string) and sub[0]
 * member set pointing to a defstring_interpret() node with a val member
 * set to the value that resulted in evaluating the equivalence string.
 *
 * When the command is subsequently executed, interpreting the hidden
 * proc causes def_string_interpret() to be executed.
 *
 * To execute a DEFSTRING which has previously been created (by proc_defstring)
 * we need to append any arguments to the stored equivalence value (held in
 * n->val) interpreted as a string, and then re-parse * the resulting string.
 *
 * We use the push-down stack of input sources to allow the parser to be
 * re-invoked.
 *
 * Since syntax errors generate an exception now, we can be robust about
 * parsing failures.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	D E F P R O C _ I N T E R P R E T (node *n, int op)
 *
 * Implements the ICL command "DEFPROC command filename [procedure]".
 *
 * When a DEFPROC is encoutered a command_line node is created with
 * interpreter proc_defproc().
 *
 * When this is interpreted it sets up a PROC_HIDDEN symbol table entry (one
 * for each abbreviation) whose value member points to a defproc_interpret()
 * node whose string_part() member contains the filename and whose sub[0]
 * memberpoints to a string node. The  string_part() member of this node
 * records the  procedure name (same as the command name if no procedure name
 * given) and whose sub[1] member points to a string node whose string_part()
 * member records the command name
 *
 * To execute an existing DEFPROC definition, we need to load the named file
 * and interpret the procedure object which may (or may not) be defined by
 * the load.  The arguments provided to 'command' will have been processed by
 * get_args() for command and so are available to the procedure.
 *
 * We are supposed to delete the DEFPROC object and all its associated
 * abbreviations after this, but we don't currently. This is a bug.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	S T R I N G _ O P (int yaccopcode)
 *
 * This is a straight-forward mapping from YACC operator terminal integer
 * code to a printable string.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E B U I L D ( value (*interpreter)(), value val, int nsub)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E 0 (value (*interpreter)(), value val)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E 1 (value (*interpreter)(), value val, node *n0)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E 2 (value (*interpreter)(), value val, node *n0, node *n1)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E 3 (value (*interpreter)(), value val, node *n0, node *n1,
 *		   node *n2)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E 4 (value (*interpreter)(), value val, node *n0, node *n1,
 *		   node *n2, node *n3)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E C O P Y (node *n)
 *
 * Copy the node pointed to by n, including any sub[] nodes.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ R E A L (double f)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ I N T E G E R (int i)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ S T R I N G (char *s)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ L O G I C A L (int i)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ V A L U E (value v)
 *
 * CONSTRUCTOR for ICL values.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ C O M M E N T (node *n, char *s)
 *
 * Comment node.
 *
 * If the comment is NULL, we return the statement that it would have been
 * attached to. This saves a cumbersome test wherever node_comment is used.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ B U I L T I N (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ N O N A R Y _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ U N A R Y _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ U N A R Y _ N U M E R I C _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ B I N A R Y _ N U M E R I C _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ U N A R Y _ S T R I N G _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ B I N A R Y _ S T R I N G _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ U N A R Y _ I N T E G E R _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	N O D E _ B I N A R Y _ I N T E G E R _ F U N C (value (*fn)())
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F L O A T _ E X C E P T I O N (int)
 *
 * A function to handle a floating point exception.
 *
 * Called when a floating exception (SIG_FPE) occurs, it resets the signal
 * handler function to itself, and if the system is set up to handle floating
 * exception signals executes a longjmp() to continue execution at the point
 * set up in jmp_float. This should have been set just prior to executing a
 * floating point operation within carith.c.
 *
 * If the system does not expect floating signals then we have a system error
 * so we report failure and abort.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	M E M O R Y  _ E X C E P T I O N (int)
 *
 * A function to handle ICL memory access exceptions.
 *
 * Trys to close down the message system and the io subsystem and then aborts
 * with a core dump
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C N T L C _ H A N D L E R (int signo)
 *
 * Handler set for keyboard interrupts. Just sets the flag value 'sigint_flag'
 * which is picked up by the function uface_interrupt()
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C H E C K C A L L S T A C K (char *procname)
 *
 * Checks the stack of currently executing procs against 'procname'.
 * Used to prevent recursive calls to ICL procedures.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P U S H C A L L S T A C K (char * procname)
 *
 * Push the procname on the currently active procedures stack IF there is
 * space.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P U S H C A L L L E V E L (void)
 *
 * Save the current call_stack_level onto calllevel_stack[]
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P O P C A L L S T A C K (void)
 *
 * Pop the currently active procedure providing there is at least one.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	R E S T O R E C A L L L E V E L (void)
 *
 * Restore a saved call_stack_level from the calllevel_stack[]
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P O P C A L L L E V E L (void)
 *
 * Clear a saved call_stack_level from the calllevel_stack[]
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C U R R E N T P R O C (void)
 *
 * Return the top entry in the call stack if there is one .
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	E X E C U T E (void)
 *
 * yyparse() parses the current input source line (see input.c) and constructs
 * the abstract node syntax form. If this delivers anything to be interpreted
 * "todo" is set to point to the top of this node structure.
 *
 * This routine, using interpret() (in node.c), executes the abstract syntax.
 * If this returns an exception this is reported and the call_stack is printed
 * and cleared.
 * During normal execution the call stack is popped.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	K I L L I O S U B S Y S T E M (void)
 *
 * Kill off the io subsystem if it is running. This is done by sending the
 * appropriate message using MSP.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I O S U B S Y S T E M _H A N D L E R (void)
 *
 * Signal handler used for SIGCHLD events during ICL iosubsystem loading.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	S T A R T I O S U B S Y S T E M (char *filename, char *icl_argv[],
 *					 int nargs)
 *
 * The IO from ICL is handled by a cooperating iosubsystem process.
 *
 * This subprocess is either loaded from 'filename' or from the default file
 * defined by the macro IOPROCESSNAME if 'filename' is null.
 * 'icl_argv' and 'nargs' are used to pass parameters given on the icl command
 * line to the subsystem using the *argv[] mechanism - see below.
 *
 * We return (-1) if an error is detacted in loading the iosubsystem or it
 * fails to signon correctly.
 * Otherwise the return value is the identifier of the io subsystems
 * MSP command_q.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	Y Y W R A P (void)
 *
 * lex is used to tokenise the input line and allows the redefinition of its
 * library routine yywrap() which is called at an end_of_file.
 *
 * If it returns 1, lex continues with the normal wrap_up of input.
 *
 * Sometimes, however, it is convenient to arrange for more input to
 * arrive from a new source.  In this case the programmer should provide a
 * yywrap() which arranges for new input and returns 0.  This instructs
 * lex to continue processing.  The default yywrap returns 1 as does this
 * version which is present in case we need it later.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	Y Y E R R O R (char * s)
 *
 * We use yacc to parse the input line and this requires the definition of a
 * function yyerror(char *s) that can report an error message 's'.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N D E N T (void)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	D I S P L A Y _ I N T E R P R E T (node *n, int op)
 *
 * Assignment to an absent variable in ICL (eg. =EXPRESSION) prints the value
 * of the expression on the left. This generates a display_interpret() node
 * whose sub[0] member points to the expression node corresponding to the
 * expression on the right.
 *
 * This is treated as a distinct statement type
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A S S I G N _ I N T E R P R E T (node *n, int op)
 *
 * Processes the assignment statement.
 *
 * Expressions of the form VARIABLE = EXPRESSION generate an assign_interpret()
 * node whose sub[0] member points to a name_interpret() node whose string_part
 * points to the identifier of the l.h.s. and whose sub[1] member points to
 * the expression node corresponding to the right hand side.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I F _ I N T E R P R E T (node *n, int op)
 *
 * Processes the IF statement.
 *
 * The syntax:
 *
 * if expression comment
 *    line_list
 * else comment
 *    linelist
 * OR
 * if expression comment
 *    linelist
 * else if expression .....
 *
 * generate an if_interpret() node with sub[0] pointing to a comment node
 * whose sub[0] member points to an expression or the if_interpret() node's
 * sub[0] directly points to the expression node.  The if_interpret's
 * sub[1] member points to the if's linelist and the sub[2] member points to
 * the elsepart node which is either an else_interpret() node (string_part
 * being the comment string of the else) with the sub[0] member pointing to
 * the else's linelist.
 *
 * OR, in the case of an elseif, is another if_interpret() node but with
 * a integer_part set to 1.
 *
 * OR is nil when there is no elsepart
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	E L S E _ I N T E R P R E T (node *n, int op)
 *
 * Processes an ELSE statement.
 *
 * The sub[2] member of an if_interpret() node points to the elsepart node
 * which is either
 *
 * An else_interpret() node (string_part being the comment string of the else)
 * with the sub[0] member pointing to the else's linelist (DEALT with here)
 *
 * OR, in the case of an elseif, is another if_interpret() node but with
 * a integer_part set to 1.
 *
 * OR is nil when there is no elsepart
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	L O O P _ I N T E R P R E T (node *n, int op)
 *
 * Processes the LOOP syntax which is:
 *
 *	LOOP comment
 *	linelist
 *	ENDLOOP
 * or
 *	LOOP WHILE expression comment
 *	linelist
 *	ENDLOOP
 * or
 *	LOOP FOR name = expression TO expression [STEP expression] comment
 * 	linelist
 *	ENDLOOP
 *
 * The first case generates a loop_interpret() node whose sub[0] member points
 * to a while_interpret() node (whose string_part node holds the comment)
 * whose sub[0] member is nil. The loop_interpret's sub[1] member points to
 * the linelist.
 *
 * The second case generates a loop_interpret() node whose sub[0] member points
 * to a while interpret() node (whose string_part node holds the comment)
 * whose sub[0] member points to the while expression node.
 * The loop_interpret's sub[1] member points to the linelist.
 *
 * The third case generates a loop_interpret() node whose sub[1] member points
 * to the linelist and whose sub[0] member points to a for_interpret() node
 * (whose string_part member holds the comment).
 * The  for_interpret() has four sub[] members
 *   sub[0] points to a name_interpret() node (with string_part set to the
 *          control variable's identity)
 *   sub[1] points to the initial_expression node
 *   sub[2] points to the end_expression node
 * and
 *   sub[3] points to the step_interpret() node whose sub[0] member points to
 *	    the step expression (set to the constant 1 if no step part in the
 *	    parser)
 *
 * Checking of the exception type is centralised, as BREAK statements are
 * executed by a special exception.
 *
 * Each kind of loop has to check for keyboard interrupts, as although they all
 * execute line_lists, a empty line list is NULL and thus does not contain a
 * check.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	W H I L E _ I N T E R P R E T (node *n, int op)
 *
 * Processes syntax of the form:
 *	LOOP WHILE expression comment
 *	linelist
 *	ENDLOOP
 *
 * This case generates a loop_interpret() node whose sub[0] member points to
 * a while interpret() node (whose string_part node holds the comment) and
 * whose sub[0] member points to the while expression node.
 *
 * As such the while_interpret() node is never directly executed here (see
 * loop_interpret()) but it can be printed.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	S T E P _ I N T E R P R E T (node *n, int op)
 *
 * Processes syntax of the form:
 *	LOOP FOR name = expression TO expression [STEP expression] comment
 *	linelist
 *	ENDLOOP
 *
 * This case generates a loop_interpret() node whose sub[1] member points to
 * the linelist and whose sub[0] member points to a for_interpret() node
 * (whose string_part member holds the comment).
 *
 * The for_interpret() node has four sub[] members
 *   sub[0] points to a name_interpret() node (with string_part set to
 *          the control variable's identity)
 *   sub[1] points to the initial_expression node
 *   sub[2] points to the end_expression node
 * and
 *   sub[3] points to the step_interpret() node
 *          whose sub[0] member points to the step expression
 *          (set to the constant 1 if no step part in the parser)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	F O R _ I N T E R P R E T (node *n, int op)
 *
 * Processes syntax of the form:
 *	LOOP FOR name = expression TO expression [STEP expression] comment
 *	linelist
 *	ENDLOOP
 *
 * This case generates a loop_interpret() node whose sub[1] member points to
 * the linelist and whose sub[0] member points to a for_interpret() node
 * (whose string_part member holds the comment).
 *
 * The  for_interpret() has four sub[] members
 *   sub[0] points to a name_interpret() node (with string_part set to
 *          the control variable's identity)
 *   sub[1] points to the initial_expression node
 *   sub[2] points to the end_expression node
 * and
 *   sub[3] points to the step_interpret() node
 *          whose sub[0] member points to the step expression
 *          (set to the constant 1 if no step part in the parser)
 *
 * As such the for_interpret node is never executed here (see loop_interpret()
 * but is responsible for printing.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	B R E A K _ I N T E R P R E T (node *n, int op)
 *
 * The ICL command "BREAK" generates a break_interpret() node.
 *
 * The BREAK statement is implemented by raising a NULL exception.
 *
 * This cannot happen under any other circumstance and is trapped by the loop
 * interpreter.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	P R O C _ C A L L _ I N T E R P R E T (node *n, int op)
 *
 * Interpret a ICL procedure call OR an ICL command (which are treated in
 * a similar manner by this version.
 *
 * First we look to see if the procedure object is defined anywhere. If it
 * is not we assume it is an external command and hand the interpreted call
 * line to the operating system.
 *
 * To call a procedure, we first get the arguments into the global arglist[]
 * array using get_args(), then record the name of the procedure we are
 * calling on the call stack, interpret the procedure object we found and
 * finally pop the name off the call stack.
 *
 * If the procedure failed, we do not pop the call stack. This is so that if
 * the exception is not handled, we can print the call stack at the point of
 * failure when we reach the top level again.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	B U I L T I N _ C A L L _ I N T E R P R E T (node *n, int op)
 *
 * This routine is called if a command has a # in front of it.
 *
 * The semantics are slightly different, because we are only prepared to
 * execute SYM_BUILTIN type objects. We do not allow  UNIX commands as being
 * built-ins.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	C O M M E N T _ I N T E R P R E T (node *n, int op)
 *
 * Comments have to be stored in the parse tree, as the LIST command does its
 * work by regenerating the source from the internal form. The VMS ICL stored
 * both source and internal forms. The new ICL canonicalises layout, which is
 * no bad thing.
 *
 * The comment_interpret() node either has a nil sub[0] member or the sub[0]
 * member points to the line node that the comment terminated.  The
 * exceptions to this are
 *	(1) Comments terminating an IF expression line when the comment
 * 	    node hangs off the sub[0] of the if_interpet() node and its own
 * 	    sub[0] member points to the expression of the if.
 *	(2) The comment after an ELSE when the commment is the string_part value
 *	    of the else_interpret() node.
 *	(3) The comment on a LOOP, LOOP WHILE or LOOPFOR statement when it
 *	    forms the string_part value of the while_interpret() or
 *	    for_interpret() node which hangs off the sub[0] member of the
 *	    loop_interpret() node.
 *	(4) The comment at the end of a PROC header hangs off the sub[0]
 *	    member of the procedure_interpret() node (pointed to from the
 *	    symbol table entry for the proc) and whose sub[0] member
 *	    points to the formal parameter list.
 *	(5) The comment on the ENDPROC statement which hangs off the sub[2]
 *	    member of the procedure_interpret() node (pointed to from the
 *	    symbol table entry for the procedure).
 *	(6) The comment at the end of an EXCEPTION header has, as its
 *	    sub[0] member a pointer to the exception_interpret() node
 *	(7) The comment of an ENDPROC statement hangs off the sub[0] member
 *	    of the exception_interpret() node
 *
 * Only the non-exceptional cases will be interpreted.
 *
 * Comments are added to statements by arranging that a comment object
 * contains the statement rather than the reverse.
 *
 * This means that we don't need a comment field on every statement node.
 * There is a trivial execution overhead associated with comments, however...
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	L I N E _ L I S T _ I N T E R P R E T (node *n, int op)
 *
 * A list of statements is actually stored as a tree of linelist_interpret()
 * nodes. The left subtree (sub[0]) is the first statement,the right subtree
 * (sub[1]) is the rest of statements.
 *
 * Expression lists are stored the same way.
 *
 * We check for exceptions and keyboard interrupts after every statement
 * executed.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	I N T _ C O N T E X T
 *
 * int_context(s) tests the string 's' for one of the possible GET, SET, OBEY,
 * CANCEL or CONTROL context and returns the appropriate integer internal code
 * for this context.
 *
 * Otherwise returns zero
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	T A S K _ C R E A T E
 *
 * Creates a new (empty) task entry linked into the internal task tables and
 * returns either a pointer to this structure or TASKNULL if memory allocation
 * fails
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	T A S K _ D E S T R O Y
 *
 * Unlinks and frees the memory associated with the given task table entry.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	T A S K _ F R O M _ N A M E
 *
 * Returns a pointer to the task structure for the named task OR NULL if
 * the task is not found.
 *
 * 'name' can be supplied in one of two forms depending on 'istask':-
 *
 *	1) The task name as used by the message system
 *	2) The file name used to load the process
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A D A M _ S T O P
 *
 * Called as part of ICL rundown to kill all attached tasks.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A D A M _ P A T H
 *
 * Returns the message system path assocated with a given task.  Does not
 * concern itself if the path was already open and so, if ams_path()
 * returns MESSYS__PATHOPEN this routine returns SAI__OK.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A D A M _ S E N D
 *
 * Sends a message to start a transaction on a given path and returns
 * the 'value' field of the reply in and the newly established transaction
 * identifier to allow the caller to continue with the transacton.
 *
 * This routine will only return when a reply is received from this transaction
 * (ie other mesages will not be confused with the expected reply)
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A D A M _ S E N D T
 *
 * This routine functions like adam_send() (above) except that a timeout (in
 * seconds) can be specified for the reply.
 *
 * Note that (after a timeout) a reply may subsequently arrive and will queue
 * until a message system call which accepts messages from all transactions
 * (either adam_receive() or adam_getreply() ) is called.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	A D A M _ C O N T R O L
 *
 * Sends a task CONTROL context message to a task ot tasks. At present this
 * new facility is only used to send "DEFAULT" messages to ADAM tasks to
 * allow them to change their home directory.
 *
 * 'name' can be a valid taskname or 'CACHED' which will cause the message
 * to be sent to all attached tasks
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 * 	A D A M _ W A I T
 *
 * Return after a specified millisecond wait ( without causing a SIG_ALARM)
 *
 * Note: Any other signal will interrupt the select system call but this is
 * desirable behaviour in this case.
 *
 ******************************************************************************
 */


/******************************************************************************
 *
 *	T A S K _ F I N D _ O R _ L O A D
 *
 * This routine first checks the task structure to see if the given task has
 * already been loaded and if so returns a pointer to the associated data
 * structure.
 *
 * If it is not loaded and the global variable (see the SET command) 'autold'
 * is true, we call load_and_run_command() to fork and run the command
 * (possibly as a detached process dependent on the boolean 'detached').
 *
 * We then enter the taskname and process id in the internal task table.
 *
 * If the task is not loaded and autold is false, a message is output and
 * TASKNULL is returned.
 *
 * We then establish a path to the task using adam_path() and record the path
 * end index in the task table.
 *
 ******************************************************************************
 */