/****************************************************************************/
/*                                                                          */
/*  Module:         jamexec.c                                               */
/*                                                                          */
/*                  Copyright (C) Altera Corporation 1997                   */
/*                                                                          */
/*  Description:    Contains the main entry point urj_jam_execute(), and    */
/*                  other functions to implement the main execution loop.   */
/*                  This loop repeatedly calls urj_jam_get_statement() and  */
/*                  urj_jam_execute_statement() to process statements in    */
/*                  the JAM source file.                                    */
/*                                                                          */
/*  Revisions:      1.1 added support for VECTOR CAPTURE and VECTOR COMPARE */
/*                  statements                                              */
/*                  added support for dynamic memory allocation             */
/*                  1.2 fixed STATE statement to accept a space-separated   */
/*                  list of states as well as a comma-separated list        */
/*                                                                          */
/****************************************************************************/

#include <stdint.h>
#include "jamexprt.h"
#include "jamdefs.h"
#include "jamexec.h"
#include "jamutil.h"
#include "jamexp.h"
#include "jamsym.h"
#include "jamstack.h"
#include "jamheap.h"
#include "jamarray.h"
#include "jamjtag.h"
#include "jamcomp.h"

/****************************************************************************/
/*                                                                          */
/*  Global variables                                                        */
/*                                                                          */
/****************************************************************************/

/* pointer to memory buffer for variable, symbol and stack storage */
char *urj_jam_workspace = NULL;

/* size of available memory buffer */
int32_t urj_jam_workspace_size = 0L;

/* pointer to Jam program text */
char *urj_jam_program = NULL;

/* size of program buffer */
int32_t urj_jam_program_size = 0L;

/* current position in input stream */
int32_t urj_jam_current_file_position = 0L;

/* position in input stream of the beginning of the current statement */
int32_t urj_jam_current_statement_position = 0L;

/* position of the beginning of the next statement (the one after the */
/* current statement, but not necessarily the next one to be executed) */
int32_t urj_jam_next_statement_position = 0L;

/* name of desired action (Jam 2.0 only) */
char *urj_jam_action = NULL;

/* pointer to initialization list */
char **urj_jam_init_list = NULL;

/* buffer for constant literal boolean array data */
#define JAMC_MAX_LITERAL_ARRAYS 4
int32_t urj_jam_literal_array_buffer[JAMC_MAX_LITERAL_ARRAYS];

/* buffer for constant literal ACA array data */
int32_t *urj_jam_literal_aca_buffer[JAMC_MAX_LITERAL_ARRAYS];

/* number of vector signals */
int urj_jam_vector_signal_count = 0;

/* version of Jam language used:  0 = unknown */
int urj_jam_version = 0;

/* phase of Jam execution */
JAME_PHASE_TYPE urj_jam_phase = JAM_UNKNOWN_PHASE;

/* current procedure or data block */
JAMS_SYMBOL_RECORD *urj_jam_current_block = NULL;

/* this global flag indicates that we are processing the items in */
/* the "uses" list for a procedure, executing the data blocks if */
/* they have not yet been initialized, but not calling any procedures */
BOOL urj_jam_checking_uses_list = false;

/* function prototypes for forward reference */
int urj_jam_get_statement (char *statement_buffer, char *label_buffer);
JAME_INSTRUCTION urj_jam_get_instruction (char *statement);
int urj_jam_skip_instruction_name (const char *statement_buffer);
int urj_jam_find_keyword (const char *buffer, char *keyword);
int urj_jam_get_array_subrange (JAMS_SYMBOL_RECORD *symbol_record,
                            char *statement_buffer, int32_t *start_index,
                            int32_t *stop_index);
int urj_jam_convert_literal_binary (char *statement_buffer,
                                int32_t **output_buffer, int32_t *length,
                                int arg);
int urj_jam_convert_literal_array (char *statement_buffer,
                               int32_t **output_buffer, int32_t *length,
                               int arg);
int urj_jam_convert_literal_aca (char *statement_buffer, int32_t **output_buffer,
                             int32_t *length, int arg);
int urj_jam_get_array_argument (char *statement_buffer,
                            JAMS_SYMBOL_RECORD **symbol_record,
                            int32_t **literal_array_data,
                            int32_t *start_index, int32_t *stop_index,
                            int arg);
int urj_jam_find_argument (char *statement_buffer, int *begin, int *end,
                       int *delimiter);
int urj_jam_process_uses_item (char *block_name);
int urj_jam_process_uses_list (char *uses_list);
int urj_jam_call_procedure (char *procedure_name, BOOL *done, int *exit_code);
int urj_jam_call_procedure_from_action (char *procedure_name, BOOL *done,
                                    int *exit_code);
int urj_jam_call_procedure_from_procedure (char *procedure_name, BOOL *done,
                                       int *exit_code);
int urj_jam_process_action (char *statement_buffer, BOOL *done, int *exit_code);
int urj_jam_process_boolean (char *statement_buffer);
int urj_jam_process_call_or_goto (char *statement_buffer, BOOL call_statement,
                              BOOL *done, int *exit_code);
int urj_jam_process_data (char *statement_buffer);
int urj_jam_process_drscan_compare (char *statement_buffer, int32_t count_value,
                                int32_t *in_data, int32_t in_index);
int urj_jam_process_drscan_capture (char *statement_buffer, int32_t count_value,
                                int32_t *in_data, int32_t in_index);
int urj_jam_process_drscan (char *statement_buffer);
int urj_jam_process_drstop (char *statement_buffer);
int urj_jam_process_enddata (char *statement_buffer);
int urj_jam_process_exit (char *statement_buffer, BOOL *done, int *exit_code);
int urj_jam_process_export (char *statement_buffer);
int urj_jam_process_for (char *statement_buffer);
int urj_jam_process_frequency (char *statement_buffer);
int urj_jam_process_if (char *statement_buffer, BOOL *reuse_statement_buffer);
int urj_jam_process_integer (char *statement_buffer);
int urj_jam_process_irscan_compare (char *statement_buffer, int32_t count_value,
                                int32_t *in_data, int32_t in_index);
int urj_jam_process_irscan_capture (char *statement_buffer, int32_t count_value,
                                int32_t *in_data, int32_t in_index);
int urj_jam_process_irscan (char *statement_buffer);
int urj_jam_process_irstop (char *statement_buffer);
int urj_jam_copy_array_subrange (int32_t *source_heap_data,
                             int32_t source_subrange_begin,
                             int32_t source_subrange_end,
                             int32_t *dest_heap_data,
                             int32_t dest_subrange_begin,
                             int32_t dest_subrange_end);
BOOL urj_jam_check_assignment (char *statement_buffer);
int urj_jam_process_assignment (char *statement_buffer, BOOL let);
int urj_jam_process_next (char *statement_buffer);
int urj_jam_process_padding (char *statement_buffer);
int urj_jam_process_pop (char *statement_buffer);
int urj_jam_process_pre_post (JAME_INSTRUCTION instruction_code,
                          char *statement_buffer);
int urj_jam_process_print (char *statement_buffer);
int urj_jam_process_procedure (char *statement_buffer);
int urj_jam_process_push (char *statement_buffer);
int urj_jam_process_return (char *statement_buffer, BOOL endproc);
int urj_jam_find_state_argument (char *statement_buffer, int *begin, int *end,
                             int *delimiter);
int urj_jam_process_state (char *statement_buffer);
int urj_jam_process_trst (char *statement_buffer);
int urj_jam_process_vector_capture (char *statement_buffer, int signal_count,
                                int32_t *dir_vector, int32_t *data_vector);
int urj_jam_process_vector_compare (char *statement_buffer, int signal_count,
                                int32_t *dir_vector, int32_t *data_vector);
int urj_jam_process_vector (char *statement_buffer);
int urj_jam_process_vmap (char *statement_buffer);
int urj_jam_process_wait_cycles (char *statement_buffer,
                             JAME_JTAG_STATE wait_state);
int urj_jam_process_wait_microseconds (char *statement_buffer,
                                   JAME_JTAG_STATE wait_state);
int urj_jam_process_wait (char *statement_buffer);
void urj_jam_free_literal_aca_buffers (void);
int urj_jam_execute_statement (char *statement_buffer, BOOL *done,
                           BOOL *reuse_statement_buffer, int *exit_code);
int32_t urj_jam_get_line_of_position (int32_t position);
int urj_jam_execute (char *program, int32_t program_size, char *workspace,
                 int32_t workspace_size, char *action, char **init_list,
                 int reset_jtag, int32_t *error_line, int *exit_code,
                 int *format_version);

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

JAM_RETURN_TYPE
urj_jam_get_statement (char *statement_buffer, char *label_buffer)
/*                                                                          */
/*  Description:    This function reads a full statement from the input     */
/*                  stream, preprocesses it to remove comments, and stores  */
/*                  it in a buffer.  If the statement is an array           */
/*                  declaration the initialization data is not stored in    */
/*                  the buffer but must be read from the input stream when  */
/*                  the array is used.                                      */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int label_index = 0;
    int ch = 0;
    int last_ch = 0;
    BOOL comment = false;
    BOOL quoted_string = false;
    BOOL boolean_array_data = false;
    BOOL literal_aca_array = false;
    BOOL label_found = false;
    BOOL done = false;
    int32_t position = urj_jam_current_file_position;
    int32_t first_char_position = -1L;
    int32_t semicolon_position = -1L;
    int32_t left_quote_position = -1L;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    label_buffer[0] = JAMC_NULL_CHAR;
    statement_buffer[0] = JAMC_NULL_CHAR;

    while (!done)
    {
        last_ch = ch;
        ch = urj_jam_getc ();

        if ((!comment) && (!quoted_string))
        {
            if (ch == JAMC_COMMENT_CHAR)
            {
                /* beginning of comment */
                comment = true;
            }
            else if (ch == JAMC_QUOTE_CHAR)
            {
                /* beginning of quoted string */
                quoted_string = true;
                left_quote_position = position;
            }
            else if (ch == JAMC_COLON_CHAR)
            {
                /* statement contains a label */
                if (label_found)
                {
                    /* multiple labels found */
                    status = JAMC_SYNTAX_ERROR;
                    done = true;
                }
                else if (index <= JAMC_MAX_NAME_LENGTH)
                {
                    /* copy label into label_buffer */
                    for (label_index = 0; label_index < index; label_index++)
                    {
                        label_buffer[label_index] =
                            statement_buffer[label_index];
                    }
                    label_buffer[index] = JAMC_NULL_CHAR;
                    label_found = true;

                    /* delete label from statement_buffer */
                    index = 0;
                    statement_buffer[0] = JAMC_NULL_CHAR;
                    first_char_position = -1L;
                    ch = JAMC_SPACE_CHAR;
                }
                else
                {
                    /* label name was too int32_t */
                    status = JAMC_ILLEGAL_SYMBOL;
                    done = true;
                }
            }
            else if ((ch == JAMC_TAB_CHAR) ||
                     (ch == JAMC_NEWLINE_CHAR) || (ch == JAMC_RETURN_CHAR))
            {
                /* convert tab, CR, LF to space character */
                ch = JAMC_SPACE_CHAR;
            }
        }

        /* save character in statement_buffer */
        if ((!comment) && (index < JAMC_MAX_STATEMENT_LENGTH) &&
            ((first_char_position != -1L) || (ch != JAMC_SPACE_CHAR)) &&
            (quoted_string ||
             (ch != JAMC_SPACE_CHAR) || (last_ch != JAMC_SPACE_CHAR)))
        {
            /* save the character */
            /* convert to upper case except quotes and boolean arrays */
            if (quoted_string || boolean_array_data || literal_aca_array)
            {
                statement_buffer[index] = (char) ch;
            }
            else
            {
                statement_buffer[index] = (char)
                    (((ch >= 'a') && (ch <= 'z')) ? (ch - ('a' - 'A')) : ch);
            }
            ++index;
            if (first_char_position == -1L)
                first_char_position = position;

            /*
             *      Whenever we see a right bracket character, check if the
             *      statement is a Boolean array declaration statement.
             */
            if ((!boolean_array_data) && (ch == JAMC_RBRACKET_CHAR)
                && (statement_buffer[0] == 'B'))
            {
                if (strncmp (statement_buffer, "BOOLEAN", 7) == 0)
                {
                    boolean_array_data = true;
                }
            }

            /*
             *      Check for literal ACA array assignment
             */
            if ((!quoted_string) && (!boolean_array_data) &&
                (!literal_aca_array) && (ch == JAMC_AT_CHAR))
            {
                /* this is the beginning of a literal ACA array */
                literal_aca_array = true;
            }

            if (literal_aca_array &&
                (!isalnum ((char) ch)) &&
                (ch != JAMC_AT_CHAR) &&
                (ch != JAMC_UNDERSCORE_CHAR) && (ch != JAMC_SPACE_CHAR))
            {
                /* this is the end of the literal ACA array */
                literal_aca_array = false;
            }
        }

        if ((!comment) && (!quoted_string) && (ch == JAMC_SEMICOLON_CHAR))
        {
            /* end of statement */
            done = true;
            semicolon_position = position;
        }

        if (ch == EOF)
        {
            /* end of file */
            done = true;
            status = JAMC_UNEXPECTED_END;
        }

        if (comment &&
            ((ch == JAMC_NEWLINE_CHAR) || (ch == JAMC_RETURN_CHAR)))
        {
            /* end of comment */
            comment = false;
        }
        else if (quoted_string && (ch == JAMC_QUOTE_CHAR) &&
                 (position > left_quote_position))
        {
            /* end of quoted string */
            quoted_string = false;
        }

        ++position;             /* position of next character to be read */
    }

    if (index < JAMC_MAX_STATEMENT_LENGTH)
    {
        statement_buffer[index] = JAMC_NULL_CHAR;
    }
    else
    {
        statement_buffer[JAMC_MAX_STATEMENT_LENGTH] = JAMC_NULL_CHAR;
    }

    urj_jam_current_file_position = position;

    if (first_char_position != -1L)
    {
        urj_jam_current_statement_position = first_char_position;
    }

    if (semicolon_position != -1L)
    {
        urj_jam_next_statement_position = semicolon_position + 1;
    }

    return status;
}

struct JAMS_INSTR_MAP
{
    JAME_INSTRUCTION instruction;
    char string[JAMC_MAX_INSTR_LENGTH + 1];
} static const jam_instruction_table[] =
{
    {JAM_ACTION_INSTR, "ACTION"},
    {JAM_BOOLEAN_INSTR, "BOOLEAN"},
    {JAM_CALL_INSTR, "CALL"},
    {JAM_CRC_INSTR, "CRC"},
    {JAM_DATA_INSTR, "DATA"},
    {JAM_DRSCAN_INSTR, "DRSCAN"},
    {JAM_DRSTOP_INSTR, "DRSTOP"},
    {JAM_ENDDATA_INSTR, "ENDDATA"},
    {JAM_ENDPROC_INSTR, "ENDPROC"},
    {JAM_EXIT_INSTR, "EXIT"},
    {JAM_EXPORT_INSTR, "EXPORT"},
    {JAM_FOR_INSTR, "FOR"},
    {JAM_FREQUENCY_INSTR, "FREQUENCY"},
    {JAM_GOTO_INSTR, "GOTO"},
    {JAM_IF_INSTR, "IF"},
    {JAM_INTEGER_INSTR, "INTEGER"},
    {JAM_IRSCAN_INSTR, "IRSCAN"},
    {JAM_IRSTOP_INSTR, "IRSTOP"},
    {JAM_LET_INSTR, "LET"},
    {JAM_NEXT_INSTR, "NEXT"},
    {JAM_NOTE_INSTR, "NOTE"},
    {JAM_PADDING_INSTR, "PADDING"},
    {JAM_POP_INSTR, "POP"},
    {JAM_POSTDR_INSTR, "POSTDR"},
    {JAM_POSTIR_INSTR, "POSTIR"},
    {JAM_PREDR_INSTR, "PREDR"},
    {JAM_PREIR_INSTR, "PREIR"},
    {JAM_PRINT_INSTR, "PRINT"},
    {JAM_PROCEDURE_INSTR, "PROCEDURE"},
    {JAM_PUSH_INSTR, "PUSH"},
    {JAM_REM_INSTR, "REM"},
    {JAM_RETURN_INSTR, "RETURN"},
    {JAM_STATE_INSTR, "STATE"},
    {JAM_TRST_INSTR, "TRST"},
    {JAM_VECTOR_INSTR, "VECTOR"},
    {JAM_VMAP_INSTR, "VMAP"},
    {JAM_WAIT_INSTR, "WAIT"}
};

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

JAME_INSTRUCTION
urj_jam_get_instruction (char *statement)
/*                                                                          */
/*  Description:    This function extracts the instruction name from the    */
/*                  statement buffer and looks up the instruction code.     */
/*                                                                          */
/*  Returns:        instruction code                                        */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int instr_index = 0;
    int length = 0;
    BOOL done = false;
    JAME_INSTRUCTION instruction = JAM_ILLEGAL_INSTR;
    char instr_name[JAMC_MAX_INSTR_LENGTH + 1];

    /*
     *      Extract instruction name and convert to upper case
     */
    for (index = 0; (!done) && (index < JAMC_MAX_INSTR_LENGTH); index++)
    {
        /* copy characters until non-alphabetic character */
        if ((statement[index] >= 'A') && (statement[index] <= 'Z'))
        {
            instr_name[index] = statement[index];
        }
        else if ((statement[index] >= 'a') && (statement[index] <= 'z'))
        {
            /* convert to upper case */
            instr_name[index] = (char) ((statement[index] - 'a') + 'A');
        }
        else
        {
            /* end of instruction name */
            instr_name[index] = JAMC_NULL_CHAR;
            length = index;
            done = true;
        }
    }

    /*
     *      Search for instruction name in instruction table
     */
    if (done && (length > 0))
    {
        done = false;

        for (index = 0; (!done) && (index < ARRAY_SIZE(jam_instruction_table)); index++)
        {
            done = true;

            for (instr_index = 0; done && (instr_index < length);
                 instr_index++)
            {
                if (instr_name[instr_index] !=
                    jam_instruction_table[index].string[instr_index])
                {
                    done = false;
                }
            }

            if (done && (jam_instruction_table[index].string[length] != '\0'))
            {
                done = false;
            }

            if (done)
            {
                instruction = jam_instruction_table[index].instruction;
            }
        }
    }

    return instruction;
}

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

int
urj_jam_skip_instruction_name (const char *statement_buffer)
/*                                                                          */
/*  Description:    This function skips over the first "word" in the        */
/*                  statement buffer, which is assumed to be the name of    */
/*                  the instruction, and returns the index of the next      */
/*                  non-white-space character in the buffer.                */
/*                                                                          */
/*  Returns:        index of statement text after instruction name          */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;

    while ((isspace (statement_buffer[index])) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;                /* skip over white space */
    }

    while ((jam_is_name_char (statement_buffer[index])) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;                /* skip over instruction name */
    }

    while ((isspace (statement_buffer[index])) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;                /* skip over white space */
    }

    return index;
}

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

int
urj_jam_find_keyword (const char *buffer, char *keyword)
/*                                                                          */
/*  Description:    This function searches in the statement buffer for the  */
/*                  specified keyword.                                      */
/*                                                                          */
/*  Returns:        index of keyword in buffer, or -1 if keyword not found  */
/*                                                                          */
/****************************************************************************/
{
    BOOL found = false;
    int index = 0;
    int buffer_length = strlen (buffer);
    int keyword_length = strlen (keyword);

    /* look at beginning of string */
    if ((buffer[0] == keyword[0]) &&
        (strncmp (buffer, keyword, keyword_length) == 0) &&
        (!jam_is_name_char (buffer[keyword_length])))
    {
        found = true;
    }

    /* look inside string */
    while ((!found) && (index + keyword_length <= buffer_length))
    {
        if ((buffer[index + 1] == keyword[0]) &&
            (!jam_is_name_char (buffer[index])) &&
            (strncmp (&buffer[index + 1], keyword, keyword_length) == 0)
            && (!jam_is_name_char (buffer[index + keyword_length + 1])))
        {
            found = true;
        }

        ++index;
    }

    return found ? index : -1;
}

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

JAM_RETURN_TYPE urj_jam_get_array_subrange
    (JAMS_SYMBOL_RECORD *symbol_record,
     char *statement_buffer, int32_t *start_index, int32_t *stop_index)
/*                                                                          */
/*  Description:    Gets start_index and stop_index of an array subrange    */
/*                  specification of the form <start_index>..<stop_index>   */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    char save_ch = 0;
    BOOL found_elipsis = false;
    BOOL found = false;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;

    while ((statement_buffer[index] != JAMC_NULL_CHAR) && !found_elipsis)
    {
        if ((statement_buffer[index] == JAMC_PERIOD_CHAR) &&
            (statement_buffer[index + 1] == JAMC_PERIOD_CHAR))
        {
            expr_end = index;
            found_elipsis = true;
        }
        ++index;
    }

    if (found_elipsis && (expr_end > expr_begin))
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status =
            urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                     start_index, &expr_type);
        statement_buffer[expr_end] = save_ch;

        /*
         *      Check for integer expression
         */
        if ((status == JAMC_SUCCESS) &&
            (expr_type != JAM_INTEGER_EXPR) &&
            (expr_type != JAM_INT_OR_BOOL_EXPR))
        {
            status = JAMC_TYPE_MISMATCH;
        }
    }
    else
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        expr_begin = expr_end + 2;

        status =
            urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                     stop_index, &expr_type);

        if ((status == JAMC_SUCCESS) &&
            (expr_type != JAM_INTEGER_EXPR) &&
            (expr_type != JAM_INT_OR_BOOL_EXPR))
        {
            status = JAMC_TYPE_MISMATCH;
        }
        else
        {
            found = true;
        }
    }

    if ((status == JAMC_SUCCESS) && (!found))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if ((urj_jam_version == 2) && (!found_elipsis) && (symbol_record != NULL))
    {
        /* if there is nothing between the brackets, select the entire array */
        index = 0;

        while (isspace (statement_buffer[index]))
            ++index;

        if (statement_buffer[index] == JAMC_NULL_CHAR)
        {
            JAMS_HEAP_RECORD *heap_record =
                (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record == NULL)
            {
                status = JAMC_INTERNAL_ERROR;
            }
            else
            {
                *start_index = heap_record->dimension - 1;
                *stop_index = 0;
                status = JAMC_SUCCESS;
            }
        }
    }

    if ((status == JAMC_SUCCESS) && (urj_jam_version == 2))
    {
        /* for Jam 2.0, swap the start and stop indices */
        int32_t temp = *start_index;
        *start_index = *stop_index;
        *stop_index = temp;
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_convert_literal_binary
    (char *statement_buffer,
     int32_t **output_buffer, int32_t *length, int arg)
/*                                                                          */
/*  Description:    converts BINARY string in statement buffer into binary  */
/*                  values.  Stores binary result back into the buffer,     */
/*                  overwriting the input text.                             */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int in_index = 0;
    int out_index = 0;
    int rev_index = 0;
    int i = 0;
    int j = 0;
    char ch = 0;
    int data = 0;
    int32_t *long_ptr = NULL;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    while ((status == JAMC_SUCCESS) &&
           ((ch = statement_buffer[in_index]) != '\0'))
    {
        if ((ch == '0') || (ch == '1'))
        {
            data = (int) (ch - '0');
        }
        else
        {
            status = JAMC_SYNTAX_ERROR;
        }

        if (status == JAMC_SUCCESS)
        {
            if ((in_index & 7) == 0)
            {
                statement_buffer[out_index] = 0;
            }

            if (data)
            {
                statement_buffer[out_index] |= (1 << (in_index & 7));
            }

            if ((in_index & 7) == 7)
            {
                ++out_index;
            }
        }

        ++in_index;
    }

    if (status == JAMC_SUCCESS)
    {
        *length = (int32_t) in_index;

        /* reverse the order of binary data */
        rev_index = in_index / 2;
        while (rev_index > 0)
        {
            data = (statement_buffer[(rev_index - 1) >> 3] &
                    (1 << ((rev_index - 1) & 7)));

            if (statement_buffer[(in_index - rev_index) >> 3] &
                (1 << ((in_index - rev_index) & 7)))
            {
                statement_buffer[(rev_index - 1) >> 3] |=
                    (1 << ((rev_index - 1) & 7));
            }
            else
            {
                statement_buffer[(rev_index - 1) >> 3] &=
                    ~(1 << ((rev_index - 1) & 7));
            }

            if (data)
            {
                statement_buffer[(in_index - rev_index) >> 3] |=
                    (1 << ((in_index - rev_index) & 7));
            }
            else
            {
                statement_buffer[(in_index - rev_index) >> 3] &=
                    ~(1 << ((in_index - rev_index) & 7));
            }

            --rev_index;
        }

        out_index = (in_index + 7) / 8; /* number of bytes */
        rev_index = (out_index + 3) / 4;        /* number of longs */

        if (rev_index > 1)
        {
            long_ptr =
                (int32_t *) (((int32_t) statement_buffer) & 0xfffffffcL);
        }
        else if (arg < JAMC_MAX_LITERAL_ARRAYS)
        {
            long_ptr = &urj_jam_literal_array_buffer[arg];
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    if (status == JAMC_SUCCESS)
    {
        for (i = 0; i < rev_index; ++i)
        {
            j = i * 4;
            long_ptr[i] = ((((int32_t) statement_buffer[j + 3] << 24L) &
                            0xff000000L) | (((int32_t) statement_buffer[j + 2]
                                             << 16L) & 0x00ff0000L) |
                           (((int32_t) statement_buffer[j + 1] << 8L) &
                            0x0000ff00L) | (((int32_t) statement_buffer[j]) &
                                            0x000000ffL));
        }

        if (output_buffer != NULL)
            *output_buffer = long_ptr;
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_convert_literal_array
    (char *statement_buffer,
     int32_t **output_buffer, int32_t *length, int arg)
/*                                                                          */
/*  Description:    converts HEX string in statement buffer into binary     */
/*                  values.  Stores binary result back into the buffer,     */
/*                  overwriting the input text.                             */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int in_index = 0;
    int out_index = 0;
    int rev_index = 0;
    int i = 0;
    int j = 0;
    char ch = 0;
    int data = 0;
    int32_t *long_ptr = NULL;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    while ((status == JAMC_SUCCESS) &&
           ((ch = statement_buffer[in_index]) != '\0'))
    {
        if ((ch >= 'A') && (ch <= 'F'))
        {
            data = (int) (ch + 10 - 'A');
        }
        else if ((ch >= 'a') && (ch <= 'f'))
        {
            data = (int) (ch + 10 - 'a');
        }
        else if ((ch >= '0') && (ch <= '9'))
        {
            data = (int) (ch - '0');
        }
        else
        {
            status = JAMC_SYNTAX_ERROR;
        }

        if (status == JAMC_SUCCESS)
        {
            if (in_index & 1)
            {
                /* odd nibble is lower nibble */
                data |= (statement_buffer[out_index] & 0xf0);
                statement_buffer[out_index] = (char) data;
                ++out_index;
            }
            else
            {
                /* even nibble is upper nibble */
                statement_buffer[out_index] = (char) (data << 4);
            }
        }

        ++in_index;
    }

    if (status == JAMC_SUCCESS)
    {
        *length = (int32_t) in_index *4L;

        if (in_index & 1)
        {
            /* odd number of nibbles - do a nibble-shift */
            out_index = in_index / 2;
            while (out_index > 0)
            {
                statement_buffer[out_index] = (char)
                    (((statement_buffer[out_index - 1] & 0x0f) << 4) |
                     ((statement_buffer[out_index] & 0xf0) >> 4));
                --out_index;
            }
            statement_buffer[0] = (char) ((statement_buffer[0] & 0xf0) >> 4);
            ++in_index;
        }

        /* reverse the order of binary data */
        out_index = in_index / 2;       /* number of bytes */
        rev_index = out_index / 2;
        while (rev_index > 0)
        {
            ch = statement_buffer[rev_index - 1];
            statement_buffer[rev_index - 1] =
                statement_buffer[out_index - rev_index];
            statement_buffer[out_index - rev_index] = ch;
            --rev_index;
        }

        out_index = (in_index + 1) / 2; /* number of bytes */
        rev_index = (out_index + 3) / 4;        /* number of longs */

        if (rev_index > 1)
        {
            long_ptr =
                (int32_t *) (((int32_t) statement_buffer) & 0xfffffffcL);
        }
        else if (arg < JAMC_MAX_LITERAL_ARRAYS)
        {
            long_ptr = &urj_jam_literal_array_buffer[arg];
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    if (status == JAMC_SUCCESS)
    {
        for (i = 0; i < rev_index; ++i)
        {
            j = i * 4;
            long_ptr[i] = ((((int32_t) statement_buffer[j + 3] << 24L) &
                            0xff000000L) | (((int32_t) statement_buffer[j + 2]
                                             << 16L) & 0x00ff0000L) |
                           (((int32_t) statement_buffer[j + 1] << 8L) &
                            0x0000ff00L) | (((int32_t) statement_buffer[j]) &
                                            0x000000ffL));
        }

        if (output_buffer != NULL)
            *output_buffer = long_ptr;
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_convert_literal_aca
    (char *statement_buffer,
     int32_t **output_buffer, int32_t *length, int arg)
/*                                                                          */
/*  Description:    Uncompress ASCII ACA data in "statement buffer".        */
/*                  Store resulting uncompressed literal data in global var */
/*                  urj_jam_literal_aca_buffer                                  */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error        */
/*                                                                          */
/****************************************************************************/
{
    int bit = 0;
    int value = 0;
    int index = 0;
    int index2 = 0;
    int i = 0;
    int j = 0;
    int long_count = 0;
    int32_t binary_compressed_length = 0L;
    int32_t uncompressed_length = 0L;
    char *buffer = NULL;
    int32_t *long_ptr = NULL;
    int32_t out_size = 0L;
    int32_t address = 0L;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    if ((arg < 0) || (arg >= JAMC_MAX_LITERAL_ARRAYS))
    {
        status = JAMC_INTERNAL_ERROR;
    }

    /* remove all white space */
    while (statement_buffer[index] != JAMC_NULL_CHAR)
    {
        if ((!isspace (statement_buffer[index])) &&
            (statement_buffer[index] != JAMC_TAB_CHAR) &&
            (statement_buffer[index] != JAMC_RETURN_CHAR) &&
            (statement_buffer[index] != JAMC_NEWLINE_CHAR))
        {
            statement_buffer[index2] = statement_buffer[index];
            ++index2;
        }
        ++index;
    }
    statement_buffer[index2] = JAMC_NULL_CHAR;

    /* convert 6-bit encoded characters to binary -- in the same buffer */
    index = 0;
    while ((status == JAMC_SUCCESS) &&
           (isalnum (statement_buffer[index]) ||
            (statement_buffer[index] == JAMC_AT_CHAR) ||
            (statement_buffer[index] == JAMC_UNDERSCORE_CHAR)))
    {
        value = urj_jam_6bit_char (statement_buffer[index]);
        statement_buffer[index] = 0;

        if (value == -1)
        {
            status = JAMC_SYNTAX_ERROR;
        }
        else
        {
            for (bit = 0; bit < 6; ++bit)
            {
                if (value & (1 << (bit % 6)))
                {
                    statement_buffer[address >> 3] |= (1L << (address & 7));
                }
                else
                {
                    statement_buffer[address >> 3] &=
                        ~(unsigned int) (1 << (address & 7));
                }
                ++address;
            }
        }

        ++index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[index] != JAMC_NULL_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    /* Compute length of binary data string in statement_buffer */
    binary_compressed_length = (address >> 3) + ((address & 7) ? 1 : 0);

    /* Get uncompressed length from first DWORD of compressed data */
    uncompressed_length = ((((int32_t) statement_buffer[3] << 24L) &
                            0xff000000L) | (((int32_t) statement_buffer[2] <<
                                             16L) & 0x00ff0000L) | (((int32_t)
                                                                     statement_buffer
                                                                     [1] <<
                                                                     8L) &
                                                                    0x0000ff00L)
                           | (((int32_t) statement_buffer[0]) & 0x000000ffL));

    /* Allocate memory for literal binary data */
    if (status == JAMC_SUCCESS)
    {
        buffer = malloc (uncompressed_length + 4);
        long_ptr = (int32_t *) malloc (uncompressed_length + 4);

        if ((buffer == NULL) || (long_ptr == NULL))
        {
            status = JAMC_OUT_OF_MEMORY;
        }
    }

    /* Uncompress encoded binary into literal binary data */
    out_size = urj_jam_uncompress (statement_buffer,
                               binary_compressed_length,
                               buffer, uncompressed_length, urj_jam_version);

    if (out_size != uncompressed_length)
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        /*
         *      Convert uncompressed data to array of int32_t integers
         */
        long_count = (out_size + 3) / 4;        /* number of longs */

        for (i = 0; i < long_count; ++i)
        {
            j = i * 4;
            long_ptr[i] = ((((int32_t) buffer[j + 3] << 24L) & 0xff000000L) |
                           (((int32_t) buffer[j + 2] << 16L) & 0x00ff0000L) |
                           (((int32_t) buffer[j + 1] << 8L) & 0x0000ff00L) |
                           (((int32_t) buffer[j]) & 0x000000ffL));
        }

        urj_jam_literal_aca_buffer[arg] = long_ptr;

        if (output_buffer != NULL)
            *output_buffer = long_ptr;

        if (length != NULL)
            *length = uncompressed_length * 8L;
    }

    if (buffer != NULL)
        free (buffer);

    /* urj_jam_literal_aca_buffer[arg] will be freed later */

    return status;
}

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

JAM_RETURN_TYPE urj_jam_get_array_argument
    (char *statement_buffer,
     JAMS_SYMBOL_RECORD **symbol_record,
     int32_t **literal_array_data,
     int32_t *start_index, int32_t *stop_index, int arg)
/*                                                                          */
/*  Description:    Looks for a sub-range-indexed array argument in the     */
/*                  statement buffer.  Calls expression parser to evaluate  */
/*                  the start_index and end_index arguments.                */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int bracket_count = 0;
    int32_t literal_array_length = 0;
    char save_ch = 0;
    JAMS_SYMBOL_RECORD *tmp_symbol_rec = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    /* first look for literal array constant */
    while ((isspace (statement_buffer[index])) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;                /* skip over white space */
    }

    if ((urj_jam_version == 2) && (statement_buffer[index] == JAMC_POUND_CHAR))
    {
        /* literal array, binary representation */
        *symbol_record = NULL;
        ++index;
        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }
        expr_begin = index;

        while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
               (statement_buffer[index] != JAMC_COMMA_CHAR) &&
               (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }
        while ((index > expr_begin)
               && isspace (statement_buffer[index - 1]))
        {
            --index;
        }
        expr_end = index;
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_convert_literal_binary (&statement_buffer[expr_begin],
                                             literal_array_data,
                                             &literal_array_length, arg);
        statement_buffer[expr_end] = save_ch;

        *start_index = 0L;
        *stop_index = literal_array_length - 1;
    }
    else if ((urj_jam_version == 2) &&
             (statement_buffer[index] == JAMC_DOLLAR_CHAR))
    {
        /* literal array, hex representation */
        *symbol_record = NULL;
        ++index;
        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }
        expr_begin = index;

        while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
               (statement_buffer[index] != JAMC_COMMA_CHAR) &&
               (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }
        while ((index > expr_begin)
               && isspace (statement_buffer[index - 1]))
        {
            --index;
        }
        expr_end = index;
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_convert_literal_array (&statement_buffer[expr_begin],
                                            literal_array_data,
                                            &literal_array_length, arg);
        statement_buffer[expr_end] = save_ch;

        *start_index = 0L;
        *stop_index = literal_array_length - 1;
    }
    else if ((urj_jam_version == 2) && (statement_buffer[index] == JAMC_AT_CHAR))
    {
        /* literal array, ACA representation */
        *symbol_record = NULL;
        ++index;
        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }
        expr_begin = index;

        while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
               (statement_buffer[index] != JAMC_COMMA_CHAR) &&
               (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }
        while ((index > expr_begin)
               && isspace (statement_buffer[index - 1]))
        {
            --index;
        }
        expr_end = index;
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_convert_literal_aca (&statement_buffer[expr_begin],
                                          literal_array_data,
                                          &literal_array_length, arg);
        statement_buffer[expr_end] = save_ch;

        *start_index = 0L;
        *stop_index = literal_array_length - 1;
    }
    else if ((urj_jam_version == 2) &&
             (strncmp (&statement_buffer[index], "BOOL(", 5) == 0))
    {
        /*
         *      Convert integer expression to Boolean array
         */
        expr_begin = index + 4;
        while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
               (statement_buffer[index] != JAMC_COMMA_CHAR) &&
               (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }

        expr_end = index;
        ++index;

        if (expr_end > expr_begin)
        {
            save_ch = statement_buffer[expr_end];
            statement_buffer[expr_end] = JAMC_NULL_CHAR;
            status = urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                              &urj_jam_literal_array_buffer[arg],
                                              &expr_type);
            statement_buffer[expr_end] = save_ch;
        }

        /*
         *      Check for integer expression
         */
        if ((status == JAMC_SUCCESS) &&
            (expr_type != JAM_INTEGER_EXPR) &&
            (expr_type != JAM_INT_OR_BOOL_EXPR))
        {
            status = JAMC_TYPE_MISMATCH;
        }

        if (status == JAMC_SUCCESS)
        {
            *symbol_record = NULL;
            *literal_array_data = &urj_jam_literal_array_buffer[arg];
            *start_index = 0L;
            *stop_index = 31L;
        }
    }
    else if ((urj_jam_version != 2) && (isdigit (statement_buffer[index])))
    {
        /* it is a literal array constant */
        *symbol_record = NULL;
        expr_begin = index;

        while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
               (statement_buffer[index] != JAMC_COMMA_CHAR) &&
               (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }
        while ((index > expr_begin)
               && isspace (statement_buffer[index - 1]))
        {
            --index;
        }
        expr_end = index;
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_convert_literal_array (&statement_buffer[expr_begin],
                                            literal_array_data,
                                            &literal_array_length, arg);
        statement_buffer[expr_end] = save_ch;

        *start_index = 0L;
        *stop_index = literal_array_length - 1;
    }
    else
    {
        /* it is not a literal constant, look for array variable */
        *literal_array_data = NULL;

        while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
               (statement_buffer[index] != JAMC_LBRACKET_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }

        if (statement_buffer[index] != JAMC_LBRACKET_CHAR)
        {
            status = JAMC_SYNTAX_ERROR;
        }
        else
        {
            expr_end = index;
            ++index;

            save_ch = statement_buffer[expr_end];
            statement_buffer[expr_end] = JAMC_NULL_CHAR;
            status = urj_jam_get_symbol_record (&statement_buffer[expr_begin],
                                            &tmp_symbol_rec);
            statement_buffer[expr_end] = save_ch;

            if (status == JAMC_SUCCESS)
            {
                *symbol_record = tmp_symbol_rec;

                if ((tmp_symbol_rec->type != JAM_BOOLEAN_ARRAY_WRITABLE) &&
                    (tmp_symbol_rec->type != JAM_BOOLEAN_ARRAY_INITIALIZED))
                {
                    status = JAMC_TYPE_MISMATCH;
                }
                else
                {
                    /* it is a Boolean array variable */
                    while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                           (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                           ((statement_buffer[index] != JAMC_RBRACKET_CHAR) ||
                            (bracket_count > 0)) &&
                           (index < JAMC_MAX_STATEMENT_LENGTH))
                    {
                        if (statement_buffer[index] == JAMC_LBRACKET_CHAR)
                        {
                            ++bracket_count;
                        }
                        else if (statement_buffer[index] ==
                                 JAMC_RBRACKET_CHAR)
                        {
                            --bracket_count;
                        }

                        ++index;
                    }

                    if (statement_buffer[index] != JAMC_RBRACKET_CHAR)
                    {
                        status = JAMC_SYNTAX_ERROR;
                    }
                    else
                    {
                        statement_buffer[index] = JAMC_NULL_CHAR;

                        status = urj_jam_get_array_subrange (tmp_symbol_rec,
                                                         &statement_buffer
                                                         [expr_end + 1],
                                                         start_index,
                                                         stop_index);
                        statement_buffer[index] = JAMC_RBRACKET_CHAR;
                        ++index;

                        if (status == JAMC_SUCCESS)
                        {
                            heap_record = (JAMS_HEAP_RECORD *)
                                tmp_symbol_rec->value;

                            if (heap_record == NULL)
                            {
                                status = JAMC_INTERNAL_ERROR;
                            }
                            else if ((*start_index < 0) || (*stop_index < 0)
                                     || (*start_index >=
                                         heap_record->dimension)
                                     || (*stop_index >=
                                         heap_record->dimension))
                            {
                                status = JAMC_BOUNDS_ERROR;
                            }
                            else
                            {
                                while (isspace (statement_buffer[index]))
                                {
                                    ++index;
                                }

                                /* there should be no more characters */
                                if (statement_buffer[index] != JAMC_NULL_CHAR)
                                {
                                    status = JAMC_SYNTAX_ERROR;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_find_argument
    (char *statement_buffer, int *begin, int *end, int *delimiter)
/*                                                                          */
/*  Description:    Finds the next argument in the statement buffer, where  */
/*                  the delimiters are COLON or SEMICOLON.  Returns indices */
/*                  of begin and end of argument, and the delimiter after   */
/*                  the argument.                                           */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    while ((isspace (statement_buffer[index])) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;                /* skip over white space */
    }

    *begin = index;

    while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
           (statement_buffer[index] != JAMC_COMMA_CHAR) &&
           (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;
    }

    if ((statement_buffer[index] != JAMC_COMMA_CHAR) &&
        (statement_buffer[index] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }
    else
    {
        *delimiter = index;     /* delimiter is position of comma or semicolon */

        while (isspace (statement_buffer[index - 1]))
        {
            --index;            /* skip backwards over white space */
        }

        *end = index;           /* end is position after last argument character */
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_uses_item (char *block_name)
/*                                                                          */
/*  Description:    Checks validity of one block-name from a USES clause.   */
/*                  If it is a data block name, initialize the data block.  */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    char save_ch = 0;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    int32_t current_position = 0L;
    int32_t return_position = urj_jam_next_statement_position;
    int32_t block_position = -1L;
    char block_buffer[JAMC_MAX_NAME_LENGTH + 1];
    char label_buffer[JAMC_MAX_NAME_LENGTH + 1];
    char *statement_buffer = NULL;
    JAME_INSTRUCTION instruction_code = JAM_ILLEGAL_INSTR;
    BOOL found = false;
    BOOL enddata = false;
    JAMS_STACK_RECORD *original_stack_position = NULL;
    BOOL reuse_statement_buffer = false;
    JAMS_SYMBOL_RECORD *tmp_current_block = urj_jam_current_block;
    JAME_PHASE_TYPE tmp_phase = urj_jam_phase;
    BOOL done = false;
    int exit_code = 0;

    statement_buffer = malloc (JAMC_MAX_STATEMENT_LENGTH + 1024);

    if (statement_buffer == NULL)
    {
        status = JAMC_OUT_OF_MEMORY;
    }
    else if (isalpha (block_name[index]))
    {
        /* locate block name */
        while ((jam_is_name_char (block_name[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over block name */
        }

        /*
         *      Look in symbol table for block name
         */
        save_ch = block_name[index];
        block_name[index] = JAMC_NULL_CHAR;
        strcpy (block_buffer, block_name);
        block_name[index] = save_ch;
        status = urj_jam_get_symbol_record (block_buffer, &symbol_record);

        if ((status == JAMC_SUCCESS) &&
            ((symbol_record->type == JAM_PROCEDURE_BLOCK) ||
             (symbol_record->type == JAM_DATA_BLOCK)))
        {
            /*
             *      Name is defined - get the address of the block
             */
            block_position = symbol_record->position;
        }
        else if (status == JAMC_UNDEFINED_SYMBOL)
        {
            /*
             *      Block name is not defined... may be a forward reference.
             *      Search through the file to find the symbol.
             */
            current_position = urj_jam_current_statement_position;

            status = JAMC_SUCCESS;

            while ((!found) && (status == JAMC_SUCCESS))
            {
                /*
                 *      Get statements without executing them
                 */
                status = urj_jam_get_statement (statement_buffer, label_buffer);

                if ((status == JAMC_SUCCESS) &&
                    (label_buffer[0] != JAMC_NULL_CHAR) && (urj_jam_version != 2))
                {
                    /*
                     *      If there is a label, add it to the symbol table
                     */
                    status = urj_jam_add_symbol (JAM_LABEL, label_buffer, 0L,
                                             urj_jam_current_statement_position);
                }

                /*
                 *      Is this a PROCEDURE or DATA statement?
                 */
                if (status == JAMC_SUCCESS)
                {
                    instruction_code = urj_jam_get_instruction (statement_buffer);

                    switch (instruction_code)
                    {
                    case JAM_DATA_INSTR:
                        status = urj_jam_process_data (statement_buffer);

                        /* check if this is the block we want to process */
                        if (status == JAMC_SUCCESS)
                        {
                            status = urj_jam_get_symbol_record (block_buffer,
                                                            &symbol_record);

                            if (status == JAMC_SUCCESS)
                            {
                                found = true;
                                block_position = symbol_record->position;
                            }
                            else if (status == JAMC_UNDEFINED_SYMBOL)
                            {
                                /* ignore undefined symbol errors */
                                status = JAMC_SUCCESS;
                            }
                        }
                        break;

                    case JAM_PROCEDURE_INSTR:
                        status = urj_jam_process_procedure (statement_buffer);

                        /* check if this is the block we want to process */
                        if (status == JAMC_SUCCESS)
                        {
                            status = urj_jam_get_symbol_record (block_buffer,
                                                            &symbol_record);

                            if (status == JAMC_SUCCESS)
                            {
                                found = true;
                                block_position = symbol_record->position;
                            }
                            else if (status == JAMC_UNDEFINED_SYMBOL)
                            {
                                /* ignore undefined symbol errors */
                                status = JAMC_SUCCESS;
                            }
                        }
                        break;
                    default:
                        break;
                    }
                }
            }

            if (!found)
            {
                /* label was not found -- report "undefined symbol" */
                /* rather than "unexpected EOF" */
                status = JAMC_UNDEFINED_SYMBOL;

                /* seek to location of the ACTION or PROCEDURE statement */
                /* that caused the error */
                urj_jam_seek (current_position);
                urj_jam_current_file_position = current_position;
                urj_jam_current_statement_position = current_position;
            }
        }

        if ((status == JAMC_SUCCESS) &&
            ((block_position == (-1L)) || (symbol_record == NULL)))
        {
            status = JAMC_INTERNAL_ERROR;
        }

        if ((status == JAMC_SUCCESS) &&
            (symbol_record->type != JAM_PROCEDURE_BLOCK) &&
            (symbol_record->type != JAM_DATA_BLOCK))
        {
            status = JAMC_SYNTAX_ERROR;
        }

        /*
         *      Call a data block to initialize the variables inside
         */
        if ((status == JAMC_SUCCESS) &&
            (symbol_record->type == JAM_DATA_BLOCK) &&
            (symbol_record->value == 0))
        {
            /*
             *      Push a CALL record onto the stack
             */
            if (status == JAMC_SUCCESS)
            {
                original_stack_position = urj_jam_peek_stack_record ();
                status = urj_jam_push_callret_record (return_position);
            }

            /*
             *      Now seek to the desired position so we can execute that
             *      statement next
             */
            if (status == JAMC_SUCCESS)
            {
                if (urj_jam_seek (block_position) == 0)
                {
                    urj_jam_current_file_position = block_position;
                }
                else
                {
                    /* seek failed */
                    status = JAMC_IO_ERROR;
                }
            }

            /*
             *      Set urj_jam_current_block to the data block about to be executed
             */
            if (status == JAMC_SUCCESS)
            {
                urj_jam_current_block = symbol_record;
                urj_jam_phase = JAM_DATA_PHASE;
            }

            /*
             *      Get program statements and execute them
             */
            while ((!(done)) && (!enddata) && (status == JAMC_SUCCESS))
            {
                if (!reuse_statement_buffer)
                {
                    status = urj_jam_get_statement
                        (statement_buffer, label_buffer);

                    if ((status == JAMC_SUCCESS)
                        && (label_buffer[0] != JAMC_NULL_CHAR))
                    {
                        status = urj_jam_add_symbol
                            (JAM_LABEL,
                             label_buffer,
                             0L, urj_jam_current_statement_position);
                    }
                }
                else
                {
                    /* statement buffer will be reused -- clear the flag */
                    reuse_statement_buffer = false;
                }

                if (status == JAMC_SUCCESS)
                {
                    status = urj_jam_execute_statement
                        (statement_buffer,
                         &done, &reuse_statement_buffer, &exit_code);

                    if ((status == JAMC_SUCCESS) &&
                        (urj_jam_get_instruction (statement_buffer)
                         == JAM_ENDDATA_INSTR) &&
                        (urj_jam_peek_stack_record () == original_stack_position))
                    {
                        enddata = true;
                    }
                }
            }

            if (done && (status == JAMC_SUCCESS))
            {
                /* an EXIT statement was processed -- impossible! */
                status = JAMC_INTERNAL_ERROR;
            }

            /* indicate that this data block has been initialized */
            symbol_record->value = 1;
        }
    }

    urj_jam_current_block = tmp_current_block;
    urj_jam_phase = tmp_phase;

    if (statement_buffer != NULL)
        free (statement_buffer);

    return status;
}

JAM_RETURN_TYPE
urj_jam_process_uses_list (char *uses_list)
{
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    int name_begin = 0;
    int name_end = 0;
    int index = 0;
    char save_ch = 0;

    urj_jam_checking_uses_list = true;

    while ((status == JAMC_SUCCESS) &&
           (uses_list[index] != JAMC_SEMICOLON_CHAR) &&
           (uses_list[index] != 0x0) && (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        while ((isspace (uses_list[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        name_begin = index;

        while ((jam_is_name_char (uses_list[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over procedure name */
        }

        name_end = index;

        while ((isspace (uses_list[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        if ((name_end > name_begin) &&
            ((uses_list[index] == JAMC_COMMA_CHAR) ||
             (uses_list[index] == JAMC_SEMICOLON_CHAR)))
        {
            save_ch = uses_list[name_end];
            uses_list[name_end] = JAMC_NULL_CHAR;
            status = urj_jam_process_uses_item (&uses_list[name_begin]);
            uses_list[name_end] = save_ch;

            if (uses_list[index] == JAMC_COMMA_CHAR)
            {
                ++index;        /* skip over comma */
            }
        }
        else
        {
            status = JAMC_SYNTAX_ERROR;
        }
    }

    if ((status == JAMC_SUCCESS) && (uses_list[index] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    urj_jam_checking_uses_list = false;

    return status;
}

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

JAM_RETURN_TYPE urj_jam_call_procedure
    (char *procedure_name, BOOL *done, int *exit_code)
/*                                                                          */
/*  Description:    Calls the specified procedure, and executes the         */
/*                  statements in the procedure.                            */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    char save_ch = 0;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAME_INSTRUCTION instruction_code = JAM_ILLEGAL_INSTR;
    int32_t current_position = 0L;
    int32_t proc_position = -1L;
    int32_t return_position = urj_jam_next_statement_position;
    char procedure_buffer[JAMC_MAX_NAME_LENGTH + 1];
    char label_buffer[JAMC_MAX_NAME_LENGTH + 1];
    char *statement_buffer = NULL;
    BOOL found = false;
    BOOL endproc = false;
    JAMS_STACK_RECORD *original_stack_position = NULL;
    BOOL reuse_statement_buffer = false;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAMS_SYMBOL_RECORD *tmp_current_block = urj_jam_current_block;
    JAME_PHASE_TYPE tmp_phase = urj_jam_phase;

    statement_buffer = malloc (JAMC_MAX_STATEMENT_LENGTH + 1024);

    if (statement_buffer == NULL)
    {
        status = JAMC_OUT_OF_MEMORY;
    }
    else if (isalpha (procedure_name[index]))
    {
        /* locate procedure name */
        while ((jam_is_name_char (procedure_name[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over procedure name */
        }

        /*
         *      Look in symbol table for procedure name
         */
        save_ch = procedure_name[index];
        procedure_name[index] = JAMC_NULL_CHAR;
        strcpy (procedure_buffer, procedure_name);
        procedure_name[index] = save_ch;
        status = urj_jam_get_symbol_record (procedure_buffer, &symbol_record);

        if ((status == JAMC_SUCCESS) &&
            (symbol_record->type == JAM_PROCEDURE_BLOCK))
        {
            /*
             *      Label is defined - get the address for the jump
             */
            proc_position = symbol_record->position;
        }
        else if (status == JAMC_UNDEFINED_SYMBOL)
        {
            /*
             *      Label is not defined... may be a forward reference.
             *      Search through the file to find the symbol.
             */
            current_position = urj_jam_current_statement_position;

            status = JAMC_SUCCESS;

            while ((!found) && (status == JAMC_SUCCESS))
            {
                /*
                 *      Get statements without executing them
                 */
                status = urj_jam_get_statement (statement_buffer, label_buffer);

                if ((status == JAMC_SUCCESS) &&
                    (label_buffer[0] != JAMC_NULL_CHAR) && (urj_jam_version != 2))
                {
                    /*
                     *      If there is a label, add it to the symbol table
                     */
                    status = urj_jam_add_symbol (JAM_LABEL, label_buffer, 0L,
                                             urj_jam_current_statement_position);
                }

                /*
                 *      Is this a PROCEDURE or DATA statement?
                 */
                if (status == JAMC_SUCCESS)
                {
                    instruction_code = urj_jam_get_instruction (statement_buffer);

                    switch (instruction_code)
                    {
                    case JAM_DATA_INSTR:
                        status = urj_jam_process_data (statement_buffer);
                        break;

                    case JAM_PROCEDURE_INSTR:
                        status = urj_jam_process_procedure (statement_buffer);

                        /* check if this is the procedure we want to call */
                        if (status == JAMC_SUCCESS)
                        {
                            status = urj_jam_get_symbol_record (procedure_buffer,
                                                            &symbol_record);

                            if (status == JAMC_SUCCESS)
                            {
                                found = true;
                                proc_position = symbol_record->position;
                            }
                            else if (status == JAMC_UNDEFINED_SYMBOL)
                            {
                                /* ignore undefined symbol errors */
                                status = JAMC_SUCCESS;
                            }
                        }
                        break;
                    default:
                        break;
                    }
                }
            }

            if (!found)
            {
                /* procedure was not found -- report "undefined symbol" */
                /* rather than "unexpected EOF" */
                status = JAMC_UNDEFINED_SYMBOL;

                /* seek to location of the ACTION or CALL statement */
                /* that caused the error */
                urj_jam_seek (current_position);
                urj_jam_current_file_position = current_position;
                urj_jam_current_statement_position = current_position;
            }
        }

        if ((status == JAMC_SUCCESS) && (symbol_record->value != 0L))
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;
            status = urj_jam_process_uses_list ((char *) heap_record->data);
        }

        /*
         *      Push a CALL record onto the stack
         */
        if ((status == JAMC_SUCCESS) && (proc_position != (-1L)))
        {
            original_stack_position = urj_jam_peek_stack_record ();
            status = urj_jam_push_callret_record (return_position);
        }

        /*
         *      Now seek to the desired position so we can execute that
         *      statement next
         */
        if ((status == JAMC_SUCCESS) && (proc_position != (-1L)))
        {
            if (urj_jam_seek (proc_position) == 0)
            {
                urj_jam_current_file_position = proc_position;
            }
            else
            {
                /* seek failed */
                status = JAMC_IO_ERROR;
            }
        }
    }

    /*
     *      Set urj_jam_current_block to the procedure about to be executed
     */
    if (status == JAMC_SUCCESS)
    {
        urj_jam_current_block = symbol_record;
        urj_jam_phase = JAM_PROCEDURE_PHASE;
    }

    /*
     *      Get program statements and execute them
     */
    while ((!(*done)) && (!endproc) && (status == JAMC_SUCCESS))
    {
        if (!reuse_statement_buffer)
        {
            status = urj_jam_get_statement (statement_buffer, label_buffer);

            if ((status == JAMC_SUCCESS)
                && (label_buffer[0] != JAMC_NULL_CHAR))
            {
                status = urj_jam_add_symbol
                    (JAM_LABEL,
                     label_buffer, 0L, urj_jam_current_statement_position);
            }
        }
        else
        {
            /* statement buffer will be reused -- clear the flag */
            reuse_statement_buffer = false;
        }

        if (status == JAMC_SUCCESS)
        {
            status = urj_jam_execute_statement
                (statement_buffer, done, &reuse_statement_buffer, exit_code);

            if ((status == JAMC_SUCCESS) &&
                (urj_jam_get_instruction (statement_buffer) == JAM_ENDPROC_INSTR)
                && (urj_jam_peek_stack_record () == original_stack_position))
            {
                endproc = true;
            }
        }
    }

    urj_jam_current_block = tmp_current_block;
    urj_jam_phase = tmp_phase;

    if (statement_buffer != NULL)
        free (statement_buffer);

    return status;
}

JAM_RETURN_TYPE urj_jam_call_procedure_from_action
    (char *procedure_name, BOOL *done, int *exit_code)
{
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;
    int index = 0;
    int procname_end = 0;
    int variable_begin = 0;
    int variable_end = 0;
    char save_ch = 0;
    BOOL call_it = false;
    BOOL init_value_set = false;
    int32_t init_value = 0L;

    if (isalpha (procedure_name[index]))
    {
        while ((jam_is_name_char (procedure_name[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over procedure name */
        }

        procname_end = index;
        save_ch = procedure_name[procname_end];
        procedure_name[procname_end] = JAMC_NULL_CHAR;

        if (urj_jam_check_init_list (procedure_name, &init_value))
        {
            init_value_set = true;
        }

        procedure_name[procname_end] = save_ch;

        while ((isspace (procedure_name[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        if (procedure_name[index] == JAMC_NULL_CHAR)
        {
            /*
             *      This is a mandatory procedure -- there is no
             *      OPTIONAL or RECOMMENDED keyword.  Just call it.
             */
            status = JAMC_SUCCESS;
            call_it = true;
        }
        else
        {
            variable_begin = index;

            while ((jam_is_name_char (procedure_name[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over procedure name */
            }

            variable_end = index;

            while ((isspace (procedure_name[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over white space */
            }

            if (procedure_name[index] == JAMC_NULL_CHAR)
            {
                /* examine the keyword */
                save_ch = procedure_name[variable_end];
                procedure_name[variable_end] = JAMC_NULL_CHAR;

                if (strcasecmp (&procedure_name[variable_begin], "OPTIONAL")
                    == 0)
                {
                    /* OPTIONAL - don't call it unless specifically requested */
                    status = JAMC_SUCCESS;
                    call_it = false;
                    if (init_value_set && (init_value != 0))
                    {
                        /* it was requested -- call it */
                        call_it = true;
                    }
                }
                else if (strcasecmp
                         (&procedure_name[variable_begin],
                          "RECOMMENDED") == 0)
                {
                    /* RECOMMENDED - call it unless specifically directed otherwise */
                    status = JAMC_SUCCESS;
                    call_it = true;
                    if (init_value_set && (init_value == 0))
                    {
                        /* it was declined -- don't call it */
                        call_it = false;
                    }
                }
                else
                {
                    /* the string did not match "OPTIONAL" or "RECOMMENDED" */
                    status = JAMC_SYNTAX_ERROR;
                }

                procedure_name[variable_end] = save_ch;
            }
            else
            {
                /* something else is lurking here -- syntax error */
                status = JAMC_SYNTAX_ERROR;
            }
        }
    }

    if ((status == JAMC_SUCCESS) && call_it)
    {
        status = urj_jam_call_procedure (procedure_name, done, exit_code);
    }

    return status;
}

JAM_RETURN_TYPE urj_jam_call_procedure_from_procedure
    (char *procedure_name, BOOL *done, int *exit_code)
{
    JAM_RETURN_TYPE status = JAMC_SCOPE_ERROR;
    JAMS_HEAP_RECORD *heap_record = NULL;
    char *uses_list = NULL;
    char save_ch = 0;
    int ch_index = 0;
    int name_begin = 0;
    int name_end = 0;

    if (urj_jam_version != 2)
    {
        status = JAMC_SUCCESS;
    }
    else
    {
        /*
         *      Check if procedure being called is listed in the
         *      "uses list", or is a recursive call to the calling
         *      procedure itself
         */
        if ((urj_jam_current_block != NULL) &&
            (urj_jam_current_block->type == JAM_PROCEDURE_BLOCK))
        {
            heap_record = (JAMS_HEAP_RECORD *) urj_jam_current_block->value;

            if (heap_record != NULL)
            {
                uses_list = (char *) heap_record->data;
            }

            if (strcasecmp (procedure_name, urj_jam_current_block->name) == 0)
            {
                /* any procedure may always call itself */
                status = JAMC_SUCCESS;
            }
        }

        if ((status != JAMC_SUCCESS) && (uses_list != NULL))
        {
            name_begin = 0;
            ch_index = 0;
            while ((uses_list[ch_index] != JAMC_NULL_CHAR) &&
                   (status != JAMC_SUCCESS))
            {
                name_end = 0;
                while ((uses_list[ch_index] != JAMC_NULL_CHAR) &&
                       (!jam_is_name_char (uses_list[ch_index])))
                {
                    ++ch_index;
                }
                if (jam_is_name_char (uses_list[ch_index]))
                {
                    name_begin = ch_index;
                }
                while ((uses_list[ch_index] != JAMC_NULL_CHAR) &&
                       (jam_is_name_char (uses_list[ch_index])))
                {
                    ++ch_index;
                }
                name_end = ch_index;

                if (name_end > name_begin)
                {
                    save_ch = uses_list[name_end];
                    uses_list[name_end] = JAMC_NULL_CHAR;
                    if (strcasecmp (&uses_list[name_begin],
                                     procedure_name) == 0)
                    {
                        /* symbol is in scope */
                        status = JAMC_SUCCESS;
                    }
                    uses_list[name_end] = save_ch;
                }
            }
        }
    }

    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_call_procedure (procedure_name, done, exit_code);
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_action
    (char *statement_buffer, BOOL *done, int *exit_code)
/*                                                                          */
/*  Description:    Processes an ACTION statement.  Calls specified         */
/*                  procedure blocks in sequence.                           */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    BOOL execute = false;
    int index = 0;
    int variable_begin = 0;
    int variable_end = 0;
    char save_ch = 0;

    if (urj_jam_version == 0)
        urj_jam_version = 2;

    if (urj_jam_version == 1)
        status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_phase == JAM_UNKNOWN_PHASE) || (urj_jam_phase == JAM_NOTE_PHASE))
    {
        urj_jam_phase = JAM_ACTION_PHASE;
    }

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_ACTION_PHASE))
    {
        status = JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    if (isalpha (statement_buffer[index]))
    {
        /*
         *      Get the action name
         */
        variable_begin = index;
        while ((jam_is_name_char (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over variable name */
        }
        variable_end = index;

        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        save_ch = statement_buffer[variable_end];
        statement_buffer[variable_end] = JAMC_NULL_CHAR;
        if (urj_jam_action == NULL)
        {
            /*
             *      If no action name was specified, this is a fatal error
             */
            status = JAMC_ACTION_NOT_FOUND;
        }
        else if (strcasecmp (&statement_buffer[variable_begin],
                              urj_jam_action) == 0)
        {
            /* this action name matches the desired action name - execute it */
            execute = true;
            urj_jam_phase = JAM_PROCEDURE_PHASE;
        }
        statement_buffer[variable_end] = save_ch;

        if (execute && (statement_buffer[index] == JAMC_QUOTE_CHAR))
        {
            /*
             *      Get the action description string (if there is one)
             */
            ++index;            /* step over quote char */
            variable_begin = index;

            /* find matching quote */
            while ((statement_buffer[index] != JAMC_QUOTE_CHAR) &&
                   (statement_buffer[index] != JAMC_NULL_CHAR) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;
            }

            if (statement_buffer[index] == JAMC_QUOTE_CHAR)
            {
                variable_end = index;

                ++index;        /* skip over quote character */

                while ((isspace (statement_buffer[index])) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;    /* skip over white space */
                }
            }
        }

        if (execute && (statement_buffer[index] == JAMC_EQUAL_CHAR))
        {
            ++index;            /* skip over equal character */

            /*
             *      Call procedures
             */
            while ((status == JAMC_SUCCESS) &&
                   (statement_buffer[index] != JAMC_NULL_CHAR) &&
                   (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                while ((isspace (statement_buffer[index])) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;    /* skip over white space */
                }

                variable_begin = index;

                while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                       (statement_buffer[index] != JAMC_COMMA_CHAR) &&
                       (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;
                }

                if ((statement_buffer[index] == JAMC_COMMA_CHAR) ||
                    (statement_buffer[index] == JAMC_SEMICOLON_CHAR))
                {
                    variable_end = index;

                    save_ch = statement_buffer[variable_end];
                    statement_buffer[variable_end] = JAMC_NULL_CHAR;
                    status =
                        urj_jam_call_procedure_from_action (&statement_buffer
                                                        [variable_begin],
                                                        done, exit_code);
                    statement_buffer[variable_end] = save_ch;
                }

                if (statement_buffer[index] == JAMC_COMMA_CHAR)
                {
                    ++index;    /* step over comma */
                }
            }

            if ((status == JAMC_SUCCESS) && !(*done))
            {
                *done = true;
                *exit_code = 0; /* success */
            }
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_boolean (char *statement_buffer)
/*                                                                          */
/*  Description:    Processes a BOOLEAN variable declaration statement      */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int variable_begin = 0;
    int variable_end = 0;
    int dim_begin = 0;
    int dim_end = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int32_t dim_value = 0L;
    int32_t init_value = 0L;
    char save_ch = 0;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if (urj_jam_version == 0)
        urj_jam_version = 1;

    if ((urj_jam_version == 2) &&
        (urj_jam_phase != JAM_PROCEDURE_PHASE) && (urj_jam_phase != JAM_DATA_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    if (isalpha (statement_buffer[index]))
    {
        /* locate variable name */
        variable_begin = index;
        while ((jam_is_name_char (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over variable name */
        }
        variable_end = index;

        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        if (statement_buffer[index] == JAMC_LBRACKET_CHAR)
        {
            /*
             *      Array declaration
             */
            dim_begin = index + 1;
            while ((statement_buffer[index] != JAMC_RBRACKET_CHAR) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* find matching bracket */
            }
            if (statement_buffer[index] == JAMC_RBRACKET_CHAR)
            {
                dim_end = index;
                ++index;
            }
            while ((isspace (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over white space */
            }

            if (dim_end > dim_begin)
            {
                save_ch = statement_buffer[dim_end];
                statement_buffer[dim_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_evaluate_expression (&statement_buffer[dim_begin],
                                             &dim_value, &expr_type);
                statement_buffer[dim_end] = save_ch;
            }

            /*
             *      Check for integer expression
             */
            if ((status == JAMC_SUCCESS) &&
                (expr_type != JAM_INTEGER_EXPR) &&
                (expr_type != JAM_INT_OR_BOOL_EXPR))
            {
                status = JAMC_TYPE_MISMATCH;
            }

            if (status == JAMC_SUCCESS)
            {
                /*
                 *      Add the array name to the symbol table
                 */
                save_ch = statement_buffer[variable_end];
                statement_buffer[variable_end] = JAMC_NULL_CHAR;
                status = urj_jam_add_symbol (JAM_BOOLEAN_ARRAY_WRITABLE,
                                         &statement_buffer[variable_begin],
                                         0L, urj_jam_current_statement_position);

                /* get a pointer to the symbol record */
                if (status == JAMC_SUCCESS)
                {
                    status =
                        urj_jam_get_symbol_record (&statement_buffer
                                               [variable_begin],
                                               &symbol_record);
                }
                statement_buffer[variable_end] = save_ch;
            }

            /*
             *      Only initialize if array has not been initialized before
             */
            if ((status == JAMC_SUCCESS) &&
                (symbol_record->type == JAM_BOOLEAN_ARRAY_WRITABLE) &&
                (symbol_record->value == 0))
            {
                if (statement_buffer[index] == JAMC_EQUAL_CHAR)
                {
                    /*
                     *      Array has initialization data
                     */
                    symbol_record->type = JAM_BOOLEAN_ARRAY_INITIALIZED;

                    status = urj_jam_add_heap_record (symbol_record, &heap_record,
                                                  dim_value);

                    if (status == JAMC_SUCCESS)
                    {
                        symbol_record->value = (int32_t) heap_record;

                        /*
                         *      Initialize heap data for array
                         */
                        status = urj_jam_read_boolean_array_data (heap_record,
                                                              &statement_buffer
                                                              [index + 1]);
                    }
                }
                else if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
                {
                    /*
                     *      Array has no initialization data.
                     *      Allocate a buffer on the heap:
                     */
                    status = urj_jam_add_heap_record (symbol_record, &heap_record,
                                                  dim_value);

                    if (status == JAMC_SUCCESS)
                    {
                        symbol_record->value = (int32_t) heap_record;
                    }
                }
            }
        }
        else
        {
            /*
             *      Scalar variable declaration
             */
            if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
            {
                status = JAMC_SUCCESS;
            }
            else if (statement_buffer[index] == JAMC_EQUAL_CHAR)
            {
                /*
                 *      Evaluate initialization expression
                 */
                ++index;
                status = urj_jam_find_argument (&statement_buffer[index],
                                            &expr_begin, &expr_end,
                                            &delimiter);

                expr_begin += index;
                expr_end += index;
                delimiter += index;

                if ((status == JAMC_SUCCESS) &&
                    (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
                {
                    status = JAMC_SYNTAX_ERROR;
                }

                if ((status == JAMC_SUCCESS) && (expr_end > expr_begin))
                {
                    save_ch = statement_buffer[expr_end];
                    statement_buffer[expr_end] = JAMC_NULL_CHAR;
                    status =
                        urj_jam_evaluate_expression (&statement_buffer
                                                 [expr_begin], &init_value,
                                                 &expr_type);
                    statement_buffer[expr_end] = save_ch;
                }

                /*
                 *      Check for Boolean expression
                 */
                if ((status == JAMC_SUCCESS) &&
                    (expr_type != JAM_BOOLEAN_EXPR) &&
                    (expr_type != JAM_INT_OR_BOOL_EXPR))
                {
                    status = JAMC_TYPE_MISMATCH;
                }
            }

            if (status == JAMC_SUCCESS)
            {
                /*
                 *      Add the variable name to the symbol table
                 */
                save_ch = statement_buffer[variable_end];
                statement_buffer[variable_end] = JAMC_NULL_CHAR;
                status = urj_jam_add_symbol (JAM_BOOLEAN_SYMBOL,
                                         &statement_buffer[variable_begin],
                                         init_value,
                                         urj_jam_current_statement_position);
                statement_buffer[variable_end] = save_ch;
            }
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_call_or_goto
    (char *statement_buffer, BOOL call_statement, BOOL *done, int *exit_code)
/*                                                                          */
/*  Description:    Processes a CALL or GOTO statement.  If it is a CALL    */
/*                  statement, a stack record is pushed onto the stack.     */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int label_begin = 0;
    int label_end = 0;
    char save_ch = 0;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAME_SYMBOL_TYPE symbol_type = JAM_LABEL;
    int32_t current_position = 0L;
    int32_t goto_position = -1L;
    int32_t return_position = urj_jam_next_statement_position;
    char label_buffer[JAMC_MAX_NAME_LENGTH + 1];
    char goto_label[JAMC_MAX_NAME_LENGTH + 1];
    BOOL found = false;

    if (urj_jam_version == 0)
        urj_jam_version = 1;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    if ((urj_jam_version == 2) && call_statement)
    {
        symbol_type = JAM_PROCEDURE_BLOCK;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Extract the label name from the statement buffer.
     */
    if (isalpha (statement_buffer[index]) && !found)
    {
        /* locate label name */
        label_begin = index;
        while ((jam_is_name_char (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over label name */
        }
        label_end = index;

        save_ch = statement_buffer[label_end];
        statement_buffer[label_end] = JAMC_NULL_CHAR;
        strcpy (goto_label, &statement_buffer[label_begin]);
        statement_buffer[label_end] = save_ch;

        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
        {
            /*
             *      Look in symbol table for label
             */
            save_ch = statement_buffer[label_end];
            statement_buffer[label_end] = JAMC_NULL_CHAR;
            status =
                urj_jam_get_symbol_record (&statement_buffer[label_begin],
                                       &symbol_record);

            if ((status == JAMC_SUCCESS) &&
                (symbol_record->type == symbol_type))
            {
                /*
                 *      Label is defined - get the address for the jump
                 */
                goto_position = symbol_record->position;
            }
            else if (status == JAMC_UNDEFINED_SYMBOL)
            {
                /*
                 *      Label is not defined... may be a forward reference.
                 *      Search through the file to find the symbol.
                 */
                current_position = urj_jam_current_statement_position;

                status = JAMC_SUCCESS;

                while ((!found) && (status == JAMC_SUCCESS))
                {
                    /*
                     *      Get statements without executing them
                     */
                    status =
                        urj_jam_get_statement (statement_buffer, label_buffer);

                    if ((status == JAMC_SUCCESS) &&
                        (label_buffer[0] != JAMC_NULL_CHAR))
                    {
                        /*
                         *      If there is a label, add it to the symbol table
                         */
                        status = urj_jam_add_symbol (JAM_LABEL, label_buffer, 0L,
                                                 urj_jam_current_statement_position);

                        /*
                         *      Is it the label we are looking for?
                         */
                        if ((status == JAMC_SUCCESS) &&
                            (strcmp (label_buffer, goto_label) == 0))
                        {
                            /*
                             *      We found the label we were looking for.
                             *      Get the address for the jump.
                             */
                            found = true;
                            goto_position = urj_jam_current_statement_position;
                        }
                    }

                    /*
                     *      In Jam 2.0, only search inside current procedure
                     */
                    if ((status == JAMC_SUCCESS) && (!found) &&
                        (urj_jam_version == 2)
                        && (urj_jam_get_instruction (statement_buffer) ==
                            JAM_ENDPROC_INSTR))
                    {
                        status = JAMC_UNDEFINED_SYMBOL;
                    }
                }

                if (!found)
                {
                    /* label was not found -- report "undefined symbol" */
                    /* rather than "unexpected EOF" */
                    status = JAMC_UNDEFINED_SYMBOL;

                    /* seek to location of the CALL or GOTO statement */
                    /* which caused the error */
                    urj_jam_seek (current_position);
                    urj_jam_current_file_position = current_position;
                    urj_jam_current_statement_position = current_position;
                }
            }

            statement_buffer[label_end] = save_ch;

            /*
             *      If this is a CALL statement (not a GOTO) then push a CALL
             *      record onto the stack
             */
            if ((call_statement) && (status == JAMC_SUCCESS) &&
                (goto_position != (-1L)) && (urj_jam_version != 2))
            {
                status = urj_jam_push_callret_record (return_position);
            }

            /*
             *      Now seek to the desired position so we can execute that
             *      statement next
             */
            if ((status == JAMC_SUCCESS) && (goto_position != (-1L)) &&
                ((urj_jam_version != 2) || (!call_statement)))
            {
                if (urj_jam_seek (goto_position) == 0)
                {
                    urj_jam_current_file_position = goto_position;
                }
                else
                {
                    /* seek failed */
                    status = JAMC_IO_ERROR;
                }
            }

            /*
             *      Call a procedure block in Jam 2.0
             */
            if (call_statement && (urj_jam_version == 2))
            {
                status =
                    urj_jam_call_procedure_from_procedure (goto_label, done,
                                                       exit_code);
            }
        }
    }

    return status;
}

JAM_RETURN_TYPE
urj_jam_process_data (char *statement_buffer)
{
    int index = 0;
    int name_begin = 0;
    int name_end = 0;
    char save_ch = 0;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;

    if (urj_jam_version == 0)
        urj_jam_version = 2;

    if (urj_jam_version == 1)
        status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) &&
        (urj_jam_phase != JAM_PROCEDURE_PHASE) && (urj_jam_phase != JAM_DATA_PHASE))
    {
        status = JAMC_PHASE_ERROR;
    }

    if ((urj_jam_version == 2) && (urj_jam_phase == JAM_ACTION_PHASE))
    {
        status = JAMC_ACTION_NOT_FOUND;
    }

    if (status == JAMC_SUCCESS)
    {
        index = urj_jam_skip_instruction_name (statement_buffer);

        if (isalpha (statement_buffer[index]))
        {
            /*
             *      Get the data block name
             */
            name_begin = index;
            while ((jam_is_name_char (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over data block name */
            }
            name_end = index;

            save_ch = statement_buffer[name_end];
            statement_buffer[name_end] = JAMC_NULL_CHAR;
            status = urj_jam_add_symbol (JAM_DATA_BLOCK,
                                     &statement_buffer[name_begin], 0L,
                                     urj_jam_current_statement_position);

            /* get a pointer to the symbol record */
            if (status == JAMC_SUCCESS)
            {
                status =
                    urj_jam_get_symbol_record (&statement_buffer[name_begin],
                                           &symbol_record);
            }
            statement_buffer[name_end] = save_ch;

            while ((isspace (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over white space */
            }
        }
        else
        {
            status = JAMC_SYNTAX_ERROR;
        }

        if ((status == JAMC_SUCCESS) &&
            (statement_buffer[index] != JAMC_SEMICOLON_CHAR))
        {
            status = JAMC_SYNTAX_ERROR;
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_drscan_compare
    (char *statement_buffer,
     int32_t count_value, int32_t *in_data, int32_t in_index)
/*                                                                          */
/*  Description:    Processes the arguments for the COMPARE version of the  */
/*                  DRSCAN statement.  Calls urj_jam_swap_dr() to access the    */
/*                  JTAG hardware interface.                                */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{

/* syntax: DRSCAN <length> [, <data>] [COMPARE <array>, <mask>, <result>] ; */

    int bit = 0;
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int actual = 0;
    int expected = 0;
    int mask = 0;
    int32_t comp_start_index = 0L;
    int32_t comp_stop_index = 0L;
    int32_t mask_start_index = 0L;
    int32_t mask_stop_index = 0L;
    int32_t start_index = 0;
    char save_ch = 0;
    int32_t *temp_array = NULL;
    BOOL result = true;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    int32_t *comp_data = NULL;
    int32_t *mask_data = NULL;
    int32_t *literal_array_data = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    int32_t *tdi_data = NULL;

    if ((strncmp (statement_buffer, "CAPTURE", 7) == 0) &&
        (isspace (statement_buffer[7])))
    {

        int32_t stop_index;

        /* Next argument should be the capture array */

        statement_buffer += 8;

        status = urj_jam_find_argument (statement_buffer,
                                    &expr_begin, &expr_end, &delimiter);

        if (status == JAMC_SUCCESS)
        {
            save_ch = statement_buffer[expr_end];
            statement_buffer[expr_end] = JAMC_NULL_CHAR;
            status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                             &symbol_record,
                                             &literal_array_data,
                                             &start_index, &stop_index, 1);
            statement_buffer[expr_end] = save_ch;
        }

        if ((status == JAMC_SUCCESS) && (literal_array_data != NULL))
        {
            /* literal array may not be used for capture buffer */
            status = JAMC_SYNTAX_ERROR;
        }

        if ((status == JAMC_SUCCESS) &&
            (stop_index != start_index + count_value - 1))
        {
            status = JAMC_BOUNDS_ERROR;
        }

        if (status == JAMC_SUCCESS)
        {
            if (symbol_record != NULL)
            {
                heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

                if (heap_record != NULL)
                {
                    tdi_data = heap_record->data;
                }
                else
                {
                    status = JAMC_INTERNAL_ERROR;
                }
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }

        if (status == JAMC_SUCCESS)
        {
            if (statement_buffer[delimiter] == JAMC_SEMICOLON_CHAR)
            {
                status = urj_jam_swap_dr (count_value, in_data, in_index,
                                      tdi_data, start_index);
                return status;
            }
            else if (statement_buffer[delimiter] == JAMC_COMMA_CHAR)
            {
                statement_buffer = statement_buffer + delimiter + 1;
            }
            else
            {
                status = JAMC_SYNTAX_ERROR;
                return status;
            }
        }

    }

    if ((strncmp (statement_buffer, "COMPARE", 7) == 0) &&
        (isspace (statement_buffer[7])))
    {
        statement_buffer += 8;
    }
    else
    {
        status = JAMC_SYNTAX_ERROR;
        return status;
    }

    /*
     *      Statement buffer should contain the part of the statement string
     *      after the COMPARE keyword.
     *
     *      The first argument should be the compare array.
     */
    status = urj_jam_find_argument (statement_buffer,
                                &expr_begin, &expr_end, &delimiter);

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &comp_start_index, &comp_stop_index,
                                         1);
        statement_buffer[expr_end] = save_ch;
        index = delimiter + 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (literal_array_data != NULL) &&
        (comp_start_index == 0) && (comp_stop_index > count_value - 1))
    {
        comp_stop_index = count_value - 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (comp_stop_index != comp_start_index + count_value - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                comp_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            comp_data = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Find the next argument -- should be the mask array
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &mask_start_index, &mask_stop_index,
                                         2);
        statement_buffer[expr_end] = save_ch;
        index = delimiter + 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (literal_array_data != NULL) &&
        (mask_start_index == 0) && (mask_stop_index > count_value - 1))
    {
        mask_stop_index = count_value - 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (mask_stop_index != mask_start_index + count_value - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                mask_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            mask_data = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Find the third argument -- should be the result variable
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    /*
     *      Result must be a scalar Boolean variable
     */
    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_symbol_record (&statement_buffer[expr_begin],
                                        &symbol_record);
        statement_buffer[expr_end] = save_ch;

        if ((status == JAMC_SUCCESS) &&
            (symbol_record->type != JAM_BOOLEAN_SYMBOL))
        {
            status = JAMC_TYPE_MISMATCH;
        }
    }

    /*
     *      Find some free memory on the heap
     */
    if (status == JAMC_SUCCESS)
    {
        if (tdi_data != NULL)
        {
            temp_array = tdi_data;
        }
        else
        {
            temp_array = urj_jam_get_temp_workspace ((count_value >> 3) + 4);

            if (temp_array == NULL)
            {
                status = JAMC_OUT_OF_MEMORY;
            }
            start_index = 0;
        }
    }

    /*
     *      Do the JTAG operation, saving the result in temp_array
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_swap_dr (count_value, in_data, in_index, temp_array,
                              start_index);
    }

    /*
     *      Mask the data and do the comparison
     */
    if (status == JAMC_SUCCESS)
    {
        int32_t end_index = start_index + count_value;
        for (bit = start_index; (bit < end_index) && result; ++bit)
        {
            actual = temp_array[bit >> 5] & (1L << (bit & 0x1f)) ? 1 : 0;
            expected = comp_data[(bit + comp_start_index) >> 5]
                & (1L << ((bit + comp_start_index) & 0x1f)) ? 1 : 0;
            mask = mask_data[(bit + mask_start_index) >> 5]
                & (1L << ((bit + mask_start_index) & 0x1f)) ? 1 : 0;

            if ((actual & mask) != (expected & mask))
            {
                result = false;
            }
        }

        symbol_record->value = result ? 1L : 0L;
    }

    if (tdi_data == NULL)
    {
        if (temp_array != NULL)
            urj_jam_free_temp_workspace (temp_array);
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_drscan_capture
    (char *statement_buffer,
     int32_t count_value, int32_t *in_data, int32_t in_index)
/*                                                                          */
/*  Description:    Processes the arguments for the CAPTURE version of the  */
/*                  DRSCAN statement.  Calls urj_jam_swap_dr() to access the    */
/*                  JTAG hardware interface.                                */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    /* syntax:  DRSCAN <length> [, <data>] [CAPTURE <array>] ; */

    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int32_t start_index = 0L;
    int32_t stop_index = 0L;
    char save_ch = 0;
    int32_t *tdi_data = NULL;
    int32_t *literal_array_data = NULL;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    /*
     *      Statement buffer should contain the part of the statement string
     *      after the CAPTURE keyword.
     *
     *      The only argument should be the capture array.
     */
    status = urj_jam_find_argument (statement_buffer,
                                &expr_begin, &expr_end, &delimiter);

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &start_index, &stop_index, 1);
        statement_buffer[expr_end] = save_ch;
    }

    if ((status == JAMC_SUCCESS) && (literal_array_data != NULL))
    {
        /* literal array may not be used for capture buffer */
        status = JAMC_SYNTAX_ERROR;
    }

    if ((status == JAMC_SUCCESS) &&
        (stop_index != start_index + count_value - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                tdi_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Perform the JTAG operation, capturing data into the heap buffer
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_swap_dr (count_value, in_data, in_index,
                              tdi_data, start_index);
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_drscan (char *statement_buffer)
/*                                                                          */
/*  Description:    Processes DRSCAN statement, which shifts data through   */
/*                  a data register of the JTAG interface                   */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    /* syntax:  DRSCAN <length> [, <data>] [CAPTURE <array>] ; */
    /* or:  DRSCAN <length> [, <data>] [COMPARE <array>, <mask>, <result>] ; */

    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int32_t count_value = 0L;
    int32_t start_index = 0L;
    int32_t stop_index = 0L;
    char save_ch = 0;
    int32_t *tdi_data = NULL;
    int32_t *literal_array_data = NULL;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /* locate length */
    status = urj_jam_find_argument (&statement_buffer[index],
                                &expr_begin, &expr_end, &delimiter);

    expr_begin += index;
    expr_end += index;
    delimiter += index;

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status =
            urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                     &count_value, &expr_type);
        statement_buffer[expr_end] = save_ch;
    }

    /*
     *      Check for integer expression
     */
    if ((status == JAMC_SUCCESS) &&
        (expr_type != JAM_INTEGER_EXPR) &&
        (expr_type != JAM_INT_OR_BOOL_EXPR))
    {
        status = JAMC_TYPE_MISMATCH;
    }

    /*
     *      Look for array variable with sub-range index
     */
    if (status == JAMC_SUCCESS)
    {
        index = delimiter + 1;
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &start_index, &stop_index, 0);
        statement_buffer[expr_end] = save_ch;
    }

    if ((status == JAMC_SUCCESS) &&
        (literal_array_data != NULL) &&
        (start_index == 0) && (stop_index > count_value - 1))
    {
        stop_index = count_value - 1;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                tdi_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            tdi_data = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] == JAMC_SEMICOLON_CHAR))
    {
        /*
         *      Do a simple DRSCAN operation -- no capture or compare
         */
        status = urj_jam_do_drscan (count_value, tdi_data, start_index);
    }
    else if ((status == JAMC_SUCCESS) &&
             (statement_buffer[delimiter] == JAMC_COMMA_CHAR))
    {
        /*
         *      Delimiter was a COMMA, so look for CAPTURE or COMPARE keyword
         */
        index = delimiter + 1;
        while (isspace (statement_buffer[index]))
        {
            ++index;            /* skip over white space */
        }

        /*
         *      Do a DRSCAN with compare and or capture
         */
        status = urj_jam_process_drscan_compare (&statement_buffer[index],
                                             count_value, tdi_data,
                                             start_index);
    }
    else
    {
        status = JAMC_SYNTAX_ERROR;
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_drstop (char *statement_buffer)
/*                                                                          */
/*  Description:    Sets stop-state for DR scan operations                  */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    JAME_JTAG_STATE state = JAM_ILLEGAL_JTAG_STATE;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Get next argument
     */
    status = urj_jam_find_argument (&statement_buffer[index],
                                &expr_begin, &expr_end, &delimiter);

    expr_begin += index;
    expr_end += index;
    delimiter += index;

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        state = urj_jam_get_jtag_state_from_name (&statement_buffer[expr_begin]);

        if (state == JAM_ILLEGAL_JTAG_STATE)
        {
            status = JAMC_SYNTAX_ERROR;
        }
        else
        {
            /*
             *      Set DRSCAN stop state to the specified state
             */
            status = urj_jam_set_drstop_state (state);
        }
    }

    return status;
}

JAM_RETURN_TYPE
urj_jam_process_enddata (char *statement_buffer)
{
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    if (urj_jam_version == 0)
        urj_jam_version = 2;

    if (urj_jam_version == 1)
        status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        status = JAMC_PHASE_ERROR;
    }

    statement_buffer = statement_buffer;

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_exit
    (char *statement_buffer, BOOL *done, int *exit_code)
/*                                                                          */
/*  Description:    This function terminates an JAM program.  The 'done'    */
/*                  flag is set, halting program execution, and the         */
/*                  exit_code value is set as specified in the statement.   */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    char save_ch = 0;
    int32_t exit_code_value = 0L;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Evaluate expression for exit code value
     */
    expr_begin = index;
    while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;
    }
    while ((statement_buffer[index] != JAMC_SEMICOLON_CHAR) && (index > 0))
    {
        --index;
    }
    expr_end = index;

    if (expr_end > expr_begin)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status =
            urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                     &exit_code_value, &expr_type);
        statement_buffer[expr_end] = save_ch;
    }

    /*
     *      Check for integer expression
     */
    if ((status == JAMC_SUCCESS) &&
        (expr_type != JAM_INTEGER_EXPR) &&
        (expr_type != JAM_INT_OR_BOOL_EXPR))
    {
        status = JAMC_TYPE_MISMATCH;
    }

    /*
     *      Check range of exit code -- must be in range of signed 16-bit number
     *      (from -32767 to 32767) for compatibility with 16-bit systems.
     */
    if (((status == JAMC_SUCCESS) &&
         ((exit_code_value < -32767L))) || (exit_code_value > 32767L))
    {
        status = JAMC_INTEGER_OVERFLOW;
    }

    if (status == JAMC_SUCCESS)
    {
        /*
         *      Terminate the program
         */
        *done = true;
        *exit_code = (int) exit_code_value;
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_export (char *statement_buffer)
/*                                                                          */
/*  Description:    Exports data outside the JAM interpreter (to the        */
/*                  calling program)                                        */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int key_begin = 0;
    int key_end = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int32_t value = 0L;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    /* boolean array variables */
    char ba_save_ch = 0;
    int ba_expr_begin = 0;
    int ba_expr_end = 0;
    int32_t ba_start_index = 0L;
    int32_t ba_stop_index = 0L;
    int32_t *ba_literal_array_data = NULL;
    JAMS_SYMBOL_RECORD *ba_symbol_record = NULL;
    JAMS_HEAP_RECORD *ba_heap_record = NULL;
    unsigned char *ba_source_heap_data = NULL;
    /* end of boolean array variables */

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Find key string
     */
    key_begin = index;
    while (isspace (statement_buffer[index]) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;
    }

    /* the first argument must be a quoted string */
    if (statement_buffer[index] == JAMC_QUOTE_CHAR)
    {
        ++index;                /* step over quote char */
        key_begin = index;

        /* find matching quote */
        while ((statement_buffer[index] != JAMC_QUOTE_CHAR) &&
               (statement_buffer[index] != JAMC_NULL_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }

        if (statement_buffer[index] == JAMC_QUOTE_CHAR)
        {
            key_end = index;
            ++index;            /* step over quote char */

            while (isspace (statement_buffer[index]) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;
            }

            if (statement_buffer[index] == JAMC_COMMA_CHAR)
            {
                ++index;        /* step over comma */
                expr_begin = index;

                /* check if it is a boolean array */
                while (isspace (statement_buffer[index]) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;
                }
                ba_expr_begin = index;
                if (jam_is_name_char (statement_buffer[index]) &&
                    (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;
                    while (jam_is_name_char (statement_buffer[index]) &&
                           (index < JAMC_MAX_STATEMENT_LENGTH))
                    {
                        ++index;
                    }
                    while (isspace (statement_buffer[index]) &&
                           (index < JAMC_MAX_STATEMENT_LENGTH))
                    {
                        ++index;
                    }
                    if (statement_buffer[index] == JAMC_LBRACKET_CHAR)
                    {
                        while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                               (index < JAMC_MAX_STATEMENT_LENGTH))
                        {
                            ++index;
                        }
                        while ((statement_buffer[index] !=
                                JAMC_SEMICOLON_CHAR) && (index > 0))
                        {
                            --index;
                        }
                        ba_expr_end = index;
                        ba_save_ch = statement_buffer[ba_expr_end];
                        statement_buffer[ba_expr_end] = JAMC_NULL_CHAR;
                        status =
                            urj_jam_get_array_argument (&statement_buffer
                                                    [ba_expr_begin],
                                                    &ba_symbol_record,
                                                    &ba_literal_array_data,
                                                    &ba_start_index,
                                                    &ba_stop_index, 0);
                        statement_buffer[ba_expr_end] = ba_save_ch;

                        if (status == JAMC_SUCCESS)
                        {
                            if (ba_symbol_record != NULL)
                            {
                                if ((ba_symbol_record->type ==
                                     JAM_BOOLEAN_ARRAY_WRITABLE) ||
                                    (ba_symbol_record->type ==
                                     JAM_BOOLEAN_ARRAY_INITIALIZED))
                                {
                                    ba_heap_record = (JAMS_HEAP_RECORD *)
                                        ba_symbol_record->value;
                                    if ((ba_start_index < 0L) ||
                                        (ba_start_index >=
                                         ba_heap_record->dimension)
                                        || (ba_stop_index < 0L)
                                        || (ba_stop_index >=
                                            ba_heap_record->dimension))
                                    {
                                        return JAMC_BOUNDS_ERROR;
                                    }
                                    ba_source_heap_data =
                                        (unsigned char *)
                                        ba_heap_record->data;
                                    statement_buffer[key_end] =
                                        JAMC_NULL_CHAR;
                                    urj_jam_export_boolean_array
                                        (&statement_buffer[key_begin],
                                         &ba_source_heap_data[ba_start_index],
                                         ba_stop_index - ba_start_index + 1L);
                                    return JAMC_SUCCESS;
                                }
                                else
                                    return JAMC_TYPE_MISMATCH;
                            }
                            else
                            {
                                return JAMC_INTERNAL_ERROR;
                            }
                        }
                        else
                        {
                            return status;
                        }
                    }
                }
                /* end of boolean array check */

                index = expr_begin;
                while ((statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                       (statement_buffer[index] != JAMC_NULL_CHAR) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;
                }

                if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
                {
                    expr_end = index;
                    statement_buffer[expr_end] = JAMC_NULL_CHAR;
                    status =
                        urj_jam_evaluate_expression (&statement_buffer
                                                 [expr_begin], &value,
                                                 &expr_type);

                    /*
                     *      May be integer or Boolean expression
                     */
                    if ((status == JAMC_SUCCESS) &&
                        (expr_type != JAM_INTEGER_EXPR) &&
                        (expr_type != JAM_BOOLEAN_EXPR) &&
                        (expr_type != JAM_INT_OR_BOOL_EXPR))
                    {
                        status = JAMC_TYPE_MISMATCH;
                    }

                    if (status == JAMC_SUCCESS)
                    {
                        /*
                         *      Export the key and value
                         */
                        statement_buffer[key_end] = JAMC_NULL_CHAR;
                        urj_jam_export_integer (&statement_buffer[key_begin],
                                            value);
                    }
                }
            }
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_for (char *statement_buffer)
/*                                                                          */
/*  Description:    This function processes a FOR statement.  It creates a  */
/*                  stack record and assigns the start value to the         */
/*                  iterator variable                                       */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int variable_begin = 0;
    int variable_end = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int32_t start_value = 0L;
    int32_t stop_value = 0L;
    int32_t step_value = 1L;
    char save_ch = 0;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    if (isalpha (statement_buffer[index]))
    {
        /* locate variable name */
        variable_begin = index;
        while ((jam_is_name_char (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over variable name */
        }
        variable_end = index;

        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        if (statement_buffer[index] == JAMC_EQUAL_CHAR)
        {
            /*
             *      Get start value for loop
             */
            expr_begin = index + 1;

            expr_end = urj_jam_find_keyword (&statement_buffer[expr_begin], "TO");

            if (expr_end > 0)
            {
                expr_end += expr_begin;
                save_ch = statement_buffer[expr_end];
                statement_buffer[expr_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                             &start_value, &expr_type);
                statement_buffer[expr_end] = save_ch;
                index = expr_end + 2;   /* step over "TO" */
            }

            /*
             *      Check for integer expression
             */
            if ((status == JAMC_SUCCESS) &&
                (expr_type != JAM_INTEGER_EXPR) &&
                (expr_type != JAM_INT_OR_BOOL_EXPR))
            {
                status = JAMC_TYPE_MISMATCH;
            }

            if (status == JAMC_SUCCESS)
            {
                /*
                 *      Get stop value for loop
                 */
                while ((isspace (statement_buffer[index])) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;    /* skip over white space */
                }

                expr_begin = index;

                expr_end = urj_jam_find_keyword (&statement_buffer[expr_begin],
                                             "STEP");

                status = JAMC_SYNTAX_ERROR;
                if (expr_end > 0)
                {
                    /* STEP found */
                    expr_end += expr_begin;
                    save_ch = statement_buffer[expr_end];
                    statement_buffer[expr_end] = JAMC_NULL_CHAR;
                    status =
                        urj_jam_evaluate_expression (&statement_buffer
                                                 [expr_begin], &stop_value,
                                                 &expr_type);
                    statement_buffer[expr_end] = save_ch;
                    index = expr_end + 4;       /* step over "STEP" */

                    /*
                     *      Check for integer expression
                     */
                    if ((status == JAMC_SUCCESS) &&
                        (expr_type != JAM_INTEGER_EXPR) &&
                        (expr_type != JAM_INT_OR_BOOL_EXPR))
                    {
                        status = JAMC_TYPE_MISMATCH;
                    }

                    if (status == JAMC_SUCCESS)
                    {
                        /*
                         *      Get step value
                         */
                        while ((isspace (statement_buffer[index])) &&
                               (index < JAMC_MAX_STATEMENT_LENGTH))
                        {
                            ++index;    /* skip over white space */
                        }

                        expr_begin = index;
                        expr_end = 0;
                        while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                               (statement_buffer[index] !=
                                JAMC_SEMICOLON_CHAR)
                               && (index < JAMC_MAX_STATEMENT_LENGTH))
                        {
                            ++index;
                        }

                        if ((statement_buffer[index] == JAMC_SEMICOLON_CHAR))
                        {
                            expr_end = index;
                        }

                        status = JAMC_SYNTAX_ERROR;
                        if (expr_end > expr_begin)
                        {
                            save_ch = statement_buffer[expr_end];
                            statement_buffer[expr_end] = JAMC_NULL_CHAR;
                            status =
                                urj_jam_evaluate_expression (&statement_buffer
                                                         [expr_begin],
                                                         &step_value,
                                                         &expr_type);
                            statement_buffer[expr_end] = save_ch;
                        }

                        /* step value zero is illegal */
                        if ((status == JAMC_SUCCESS) && (step_value == 0))
                        {
                            status = JAMC_SYNTAX_ERROR;
                        }

                        /*
                         *      Check for integer expression
                         */
                        if ((status == JAMC_SUCCESS) &&
                            (expr_type != JAM_INTEGER_EXPR) &&
                            (expr_type != JAM_INT_OR_BOOL_EXPR))
                        {
                            status = JAMC_TYPE_MISMATCH;
                        }
                    }
                }
                else
                {
                    /* STEP not found -- look for semicolon */
                    while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                           (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                           (index < JAMC_MAX_STATEMENT_LENGTH))
                    {
                        ++index;
                    }

                    if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
                    {
                        expr_end = index;
                    }

                    /*
                     *      Get stop value for loop
                     */
                    status = JAMC_SYNTAX_ERROR;
                    if (expr_end > expr_begin)
                    {
                        save_ch = statement_buffer[expr_end];
                        statement_buffer[expr_end] = JAMC_NULL_CHAR;
                        status =
                            urj_jam_evaluate_expression (&statement_buffer
                                                     [expr_begin],
                                                     &stop_value, &expr_type);
                        statement_buffer[expr_end] = save_ch;
                    }

                    /*
                     *      Step value defaults to one
                     */
                    step_value = 1L;

                    /*
                     *      Check for integer expression
                     */
                    if ((status == JAMC_SUCCESS) &&
                        (expr_type != JAM_INTEGER_EXPR) &&
                        (expr_type != JAM_INT_OR_BOOL_EXPR))
                    {
                        status = JAMC_TYPE_MISMATCH;
                    }
                }
            }
        }
    }

    /*
     *      We have extracted the variable name and the start, stop, and
     *      step values from the statement buffer.  Now set the variable
     *      to the start value and push a stack record onto the stack.
     */
    if (status == JAMC_SUCCESS)
    {
        /*
         *      Find the variable (must be an integer)
         */
        status = JAMC_SYNTAX_ERROR;
        save_ch = statement_buffer[variable_end];
        statement_buffer[variable_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_symbol_record (&statement_buffer[variable_begin],
                                        &symbol_record);

        if ((status == JAMC_SUCCESS) &&
            (symbol_record->type != JAM_INTEGER_SYMBOL))
        {
            status = JAMC_TYPE_MISMATCH;
        }

        if (status == JAMC_SUCCESS)
        {
            /*
             *      Set the variable to the start value
             */
            status = urj_jam_set_symbol_value (JAM_INTEGER_SYMBOL,
                                           &statement_buffer[variable_begin],
                                           start_value);
        }
        statement_buffer[variable_end] = save_ch;
    }

    if (status == JAMC_SUCCESS)
    {
        /*
         *      Push a record onto the stack
         */
        status = urj_jam_push_fornext_record (symbol_record,
                                          urj_jam_next_statement_position,
                                          stop_value, step_value);
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_frequency (char *statement_buffer)
/*                                                                          */
/*  Description:    This function processes a FREQUENCY statement.  If the  */
/*                  specified frequency (in cycles per second) is less than */
/*                  the expected frequency of an ISA parallel port about    */
/*                  (200 KHz) then delays will be added to each clock cycle.*/
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int ret = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int32_t expr_value = 0L;
    char save_ch = 0;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    if (urj_jam_version == 0)
        urj_jam_version = 2;

    if (urj_jam_version != 2)
        status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        status = JAMC_PHASE_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        index = urj_jam_skip_instruction_name (statement_buffer);

        while (isspace (statement_buffer[index]) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }

        expr_begin = index;

        while ((statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }

        expr_end = index;

        if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
        {
            if (expr_end > expr_begin)
            {
                save_ch = statement_buffer[expr_end];
                statement_buffer[expr_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                             &expr_value, &expr_type);
                statement_buffer[expr_end] = save_ch;

                if (status == JAMC_SUCCESS)
                {
                    //ret = jam_set_frequency (expr_value);
                }
            }
            else
            {
                //ret = jam_set_frequency (-1L);  /* set default frequency */
            }
        }
        else
        {
            /* semicolon not found */
            status = JAMC_SYNTAX_ERROR;
        }

        if ((status == JAMC_SUCCESS) && (ret != 0))
        {
            /* return code from jam_set_frequency() indicates an error */
            status = JAMC_BOUNDS_ERROR;
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_if
    (char *statement_buffer, BOOL *reuse_statement_buffer)
/*                                                                          */
/*  Description:    Processes an IF (conditional) statement.  If the        */
/*                  condition is true, then the input stream pointer is     */
/*                  set to the position of the statement to be executed     */
/*                  (whatever follows the THEN keyword) which will be       */
/*                  fetched normally and processed as the next statement.   */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int32_t conditional_value = 0L;
    int then_index = 0L;
    char save_ch = 0;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Evaluate conditional expression
     */
    expr_begin = index;
    then_index = urj_jam_find_keyword (&statement_buffer[expr_begin], "THEN");

    if (then_index > 0)
    {
        expr_end = expr_begin + then_index;

        if (expr_end > expr_begin)
        {
            save_ch = statement_buffer[expr_end];
            statement_buffer[expr_end] = JAMC_NULL_CHAR;
            status =
                urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                         &conditional_value, &expr_type);
            statement_buffer[expr_end] = save_ch;
        }

        /*
         *      Check for Boolean expression
         */
        if ((status == JAMC_SUCCESS) &&
            (expr_type != JAM_BOOLEAN_EXPR) &&
            (expr_type != JAM_INT_OR_BOOL_EXPR))
        {
            status = JAMC_TYPE_MISMATCH;
        }

        if (status == JAMC_SUCCESS)
        {
            if (conditional_value)
            {
                index = expr_end + 4;
                while ((isspace (statement_buffer[index])) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;    /* skip over white space */
                }

                /*
                 *      Copy whatever appears after "THEN" to beginning of buffer
                 *      so it can be reused.
                 */
                strcpy (statement_buffer, &statement_buffer[index]);
                *reuse_statement_buffer = true;
            }
            /*
             *      (else do nothing if conditional value is false)
             */
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_integer (char *statement_buffer)
/*                                                                          */
/*  Description:    Processes a INTEGER variable declaration statement      */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int variable_begin = 0;
    int variable_end = 0;
    int dim_begin = 0;
    int dim_end = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int32_t dim_value = 0L;
    int32_t init_value = 0L;
    char save_ch = 0;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) &&
        (urj_jam_phase != JAM_PROCEDURE_PHASE) && (urj_jam_phase != JAM_DATA_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    if (isalpha (statement_buffer[index]))
    {
        /* locate variable name */
        variable_begin = index;
        while ((jam_is_name_char (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over variable name */
        }
        variable_end = index;

        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        if (statement_buffer[index] == JAMC_LBRACKET_CHAR)
        {
            /*
             *      Array declaration
             */
            dim_begin = index + 1;
            while ((statement_buffer[index] != JAMC_RBRACKET_CHAR) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* find matching bracket */
            }
            if (statement_buffer[index] == JAMC_RBRACKET_CHAR)
            {
                dim_end = index;
                ++index;
            }
            while ((isspace (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over white space */
            }

            if (dim_end > dim_begin)
            {
                save_ch = statement_buffer[dim_end];
                statement_buffer[dim_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_evaluate_expression (&statement_buffer[dim_begin],
                                             &dim_value, &expr_type);
                statement_buffer[dim_end] = save_ch;
            }

            /*
             *      Check for integer expression
             */
            if ((status == JAMC_SUCCESS) &&
                (expr_type != JAM_INTEGER_EXPR) &&
                (expr_type != JAM_INT_OR_BOOL_EXPR))
            {
                status = JAMC_TYPE_MISMATCH;
            }

            if (status == JAMC_SUCCESS)
            {
                /*
                 *      Add the array name to the symbol table
                 */
                save_ch = statement_buffer[variable_end];
                statement_buffer[variable_end] = JAMC_NULL_CHAR;
                status = urj_jam_add_symbol (JAM_INTEGER_ARRAY_WRITABLE,
                                         &statement_buffer[variable_begin],
                                         0L, urj_jam_current_statement_position);

                /* get a pointer to the symbol record */
                if (status == JAMC_SUCCESS)
                {
                    status =
                        urj_jam_get_symbol_record (&statement_buffer
                                               [variable_begin],
                                               &symbol_record);
                }
                statement_buffer[variable_end] = save_ch;
            }

            if ((status == JAMC_SUCCESS) &&
                (symbol_record->type == JAM_INTEGER_ARRAY_WRITABLE) &&
                (symbol_record->value == 0))
            {
                if (statement_buffer[index] == JAMC_EQUAL_CHAR)
                {
                    /*
                     *      Array has initialization data:  read it in.
                     */
                    status = urj_jam_add_heap_record (symbol_record, &heap_record,
                                                  dim_value);

                    if (status == JAMC_SUCCESS)
                    {
                        symbol_record->value = (int32_t) heap_record;

                        status = urj_jam_read_integer_array_data (heap_record,
                                                              &statement_buffer
                                                              [index + 1]);
                    }
                }
                else if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
                {
                    /*
                     *      Array has no initialization data.
                     *      Allocate a buffer on the heap:
                     */
                    status = urj_jam_add_heap_record (symbol_record, &heap_record,
                                                  dim_value);

                    if (status == JAMC_SUCCESS)
                    {
                        symbol_record->value = (int32_t) heap_record;
                    }
                }
            }
            else
            {
                /* this should be end of the statement */
                if (status == JAMC_SUCCESS)
                    status = JAMC_SYNTAX_ERROR;
            }
        }
        else
        {
            /*
             *      Scalar variable declaration
             */
            if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
            {
                status = JAMC_SUCCESS;
            }
            else if (statement_buffer[index] == JAMC_EQUAL_CHAR)
            {
                /*
                 *      Evaluate initialization expression
                 */
                expr_begin = index + 1;
                while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;
                }
                while ((statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                       (index > 0))
                {
                    --index;
                }
                expr_end = index;

                if (expr_end > expr_begin)
                {
                    save_ch = statement_buffer[expr_end];
                    statement_buffer[expr_end] = JAMC_NULL_CHAR;
                    status =
                        urj_jam_evaluate_expression (&statement_buffer
                                                 [expr_begin], &init_value,
                                                 &expr_type);
                    statement_buffer[expr_end] = save_ch;
                }

                /*
                 *      Check for integer expression
                 */
                if ((status == JAMC_SUCCESS) &&
                    (expr_type != JAM_INTEGER_EXPR) &&
                    (expr_type != JAM_INT_OR_BOOL_EXPR))
                {
                    status = JAMC_TYPE_MISMATCH;
                }
            }

            if (status == JAMC_SUCCESS)
            {
                /*
                 *      Add the variable name to the symbol table
                 */
                save_ch = statement_buffer[variable_end];
                statement_buffer[variable_end] = JAMC_NULL_CHAR;
                status = urj_jam_add_symbol (JAM_INTEGER_SYMBOL,
                                         &statement_buffer[variable_begin],
                                         init_value,
                                         urj_jam_current_statement_position);
                statement_buffer[variable_end] = save_ch;
            }
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_irscan_compare
    (char *statement_buffer,
     int32_t count_value, int32_t *in_data, int32_t in_index)
/*                                                                          */
/*  Description:    Processes the arguments for the COMPARE version of the  */
/*                  IRSCAN statement.  Calls urj_jam_swap_ir() to access the    */
/*                  JTAG hardware interface.                                */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{

/* syntax: IRSCAN <length> [, <data>] [COMPARE <array>, <mask>, <result>] ; */

    int bit = 0;
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int actual = 0;
    int expected = 0;
    int mask = 0;
    int32_t comp_start_index = 0L;
    int32_t comp_stop_index = 0L;
    int32_t mask_start_index = 0L;
    int32_t mask_stop_index = 0L;
    char save_ch = 0;
    int32_t *temp_array = NULL;
    BOOL result = true;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    int32_t *comp_data = NULL;
    int32_t *mask_data = NULL;
    int32_t *literal_array_data = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    /*
     *      Statement buffer should contain the part of the statement string
     *      after the COMPARE keyword.
     *
     *      The first argument should be the compare array.
     */
    status = urj_jam_find_argument (statement_buffer,
                                &expr_begin, &expr_end, &delimiter);

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &comp_start_index, &comp_stop_index,
                                         1);
        statement_buffer[expr_end] = save_ch;
        index = delimiter + 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (literal_array_data != NULL) &&
        (comp_start_index == 0) && (comp_stop_index > count_value - 1))
    {
        comp_stop_index = count_value - 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (comp_stop_index != comp_start_index + count_value - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                comp_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            comp_data = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Find the next argument -- should be the mask array
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &mask_start_index, &mask_stop_index,
                                         2);
        statement_buffer[expr_end] = save_ch;
        index = delimiter + 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (literal_array_data != NULL) &&
        (mask_start_index == 0) && (mask_stop_index > count_value - 1))
    {
        mask_stop_index = count_value - 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (mask_stop_index != mask_start_index + count_value - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                mask_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            mask_data = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Find the third argument -- should be the result variable
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    /*
     *      Result must be a scalar Boolean variable
     */
    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_symbol_record (&statement_buffer[expr_begin],
                                        &symbol_record);
        statement_buffer[expr_end] = save_ch;

        if ((status == JAMC_SUCCESS) &&
            (symbol_record->type != JAM_BOOLEAN_SYMBOL))
        {
            status = JAMC_TYPE_MISMATCH;
        }
    }

    /*
     *      Find some free memory on the heap
     */
    if (status == JAMC_SUCCESS)
    {
        temp_array = urj_jam_get_temp_workspace ((count_value >> 3) + 4);

        if (temp_array == NULL)
        {
            status = JAMC_OUT_OF_MEMORY;
        }
    }

    /*
     *      Do the JTAG operation, saving the result in temp_array
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_swap_ir (count_value, in_data, in_index, temp_array, 0);
    }

    /*
     *      Mask the data and do the comparison
     */
    if (status == JAMC_SUCCESS)
    {
        for (bit = 0; (bit < count_value) && result; ++bit)
        {
            actual = temp_array[bit >> 5] & (1L << (bit & 0x1f)) ? 1 : 0;
            expected = comp_data[(bit + comp_start_index) >> 5]
                & (1L << ((bit + comp_start_index) & 0x1f)) ? 1 : 0;
            mask = mask_data[(bit + mask_start_index) >> 5]
                & (1L << ((bit + mask_start_index) & 0x1f)) ? 1 : 0;

            if ((actual & mask) != (expected & mask))
            {
                result = false;
            }
        }

        symbol_record->value = result ? 1L : 0L;
    }

    if (temp_array != NULL)
        urj_jam_free_temp_workspace (temp_array);

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_irscan_capture
    (char *statement_buffer,
     int32_t count_value, int32_t *in_data, int32_t in_index)
/*                                                                          */
/*  Description:    Processes the arguments for the CAPTURE version of the  */
/*                  IRSCAN statement.  Calls urj_jam_swap_ir() to access the    */
/*                  JTAG hardware interface.                                */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    /* syntax:  IRSCAN <length> [, <data>] [CAPTURE <array>] ; */

    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int32_t start_index = 0L;
    int32_t stop_index = 0L;
    char save_ch = 0;
    int32_t *tdi_data = NULL;
    int32_t *literal_array_data = NULL;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    /*
     *      Statement buffer should contain the part of the statement string
     *      after the CAPTURE keyword.
     *
     *      The only argument should be the capture array.
     */
    status = urj_jam_find_argument (statement_buffer,
                                &expr_begin, &expr_end, &delimiter);

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &start_index, &stop_index, 1);
        statement_buffer[expr_end] = save_ch;
    }

    if ((status == JAMC_SUCCESS) && (literal_array_data != NULL))
    {
        /* literal array may not be used for capture buffer */
        status = JAMC_SYNTAX_ERROR;
    }

    if ((status == JAMC_SUCCESS) &&
        (stop_index != start_index + count_value - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                tdi_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Perform the JTAG operation, capturing data into the heap buffer
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_swap_ir (count_value, in_data, in_index,
                              tdi_data, start_index);
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_irscan (char *statement_buffer)
/*                                                                          */
/*  Description:    Processes IRSCAN statement, which shifts data through   */
/*                  an instruction register of the JTAG interface           */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    /* syntax:  IRSCAN <length> [, <data>] [CAPTURE <array>] ; */
    /* or:  IRSCAN <length> [, <data>] [COMPARE <array>, <mask>, <result>] ; */

    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0L;
    int32_t count_value = 0L;
    int32_t start_index = 0L;
    int32_t stop_index = 0L;
    char save_ch = 0;
    int32_t *tdi_data = NULL;
    int32_t *literal_array_data = NULL;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /* locate length */
    status = urj_jam_find_argument (&statement_buffer[index],
                                &expr_begin, &expr_end, &delimiter);

    expr_begin += index;
    expr_end += index;
    delimiter += index;

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status =
            urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                     &count_value, &expr_type);
        statement_buffer[expr_end] = save_ch;
    }

    /*
     *      Check for integer expression
     */
    if ((status == JAMC_SUCCESS) &&
        (expr_type != JAM_INTEGER_EXPR) &&
        (expr_type != JAM_INT_OR_BOOL_EXPR))
    {
        status = JAMC_TYPE_MISMATCH;
    }

    /*
     *      Look for array variable with sub-range index
     */
    if (status == JAMC_SUCCESS)
    {
        index = delimiter + 1;
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &start_index, &stop_index, 0);
        statement_buffer[expr_end] = save_ch;
    }

    if ((status == JAMC_SUCCESS) &&
        (literal_array_data != NULL) &&
        (start_index == 0) && (stop_index > count_value - 1))
    {
        stop_index = count_value - 1;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                tdi_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            tdi_data = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] == JAMC_SEMICOLON_CHAR))
    {
        /*
         *      Do a simple IRSCAN operation -- no capture or compare
         */
        status = urj_jam_do_irscan (count_value, tdi_data, start_index);
    }
    else if ((status == JAMC_SUCCESS) &&
             (statement_buffer[delimiter] == JAMC_COMMA_CHAR))
    {
        /*
         *      Delimiter was a COMMA, so look for CAPTURE or COMPARE keyword
         */
        index = delimiter + 1;
        while (isspace (statement_buffer[index]))
        {
            ++index;            /* skip over white space */
        }

        if ((strncmp (&statement_buffer[index], "CAPTURE", 7) == 0) &&
            (isspace (statement_buffer[index + 7])))
        {
            /*
             *      Do an IRSCAN with capture
             */
            status = urj_jam_process_irscan_capture (&statement_buffer[index + 8],
                                                 count_value, tdi_data,
                                                 start_index);
        }
        else if ((strncmp (&statement_buffer[index], "COMPARE", 7) == 0)
                 && (isspace (statement_buffer[index + 7])))
        {
            /*
             *      Do an IRSCAN with compare
             */
            status = urj_jam_process_irscan_compare (&statement_buffer[index + 8],
                                                 count_value, tdi_data,
                                                 start_index);
        }
        else
        {
            status = JAMC_SYNTAX_ERROR;
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_irstop (char *statement_buffer)
/*                                                                          */
/*  Description:    Sets stop-state for IR scan operations                  */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    JAME_JTAG_STATE state = JAM_ILLEGAL_JTAG_STATE;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Get next argument
     */
    status = urj_jam_find_argument (&statement_buffer[index],
                                &expr_begin, &expr_end, &delimiter);

    expr_begin += index;
    expr_end += index;
    delimiter += index;

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        state = urj_jam_get_jtag_state_from_name (&statement_buffer[expr_begin]);

        if (state == JAM_ILLEGAL_JTAG_STATE)
        {
            status = JAMC_SYNTAX_ERROR;
        }
        else
        {
            /*
             *      Set IRSCAN stop state to the specified state
             */
            status = urj_jam_set_irstop_state (state);
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_copy_array_subrange
    (int32_t *source_heap_data,
     int32_t source_subrange_begin,
     int32_t source_subrange_end,
     int32_t *dest_heap_data,
     int32_t dest_subrange_begin, int32_t dest_subrange_end)
/*                                                                          */
/*  Description:    Copies bits from one BOOLEAN array buffer to another    */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int32_t source_length = 1 + source_subrange_end - source_subrange_begin;
    int32_t dest_length = 1 + dest_subrange_end - dest_subrange_begin;
    int32_t length = source_length;
    int32_t index = 0L;
    int32_t source_index = 0L;
    int32_t dest_index = 0L;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    /* find minimum of source_length and dest_length */
    if (length > dest_length)
        length = dest_length;

    if (length <= 0L)
    {
        status = JAMC_BOUNDS_ERROR;
    }
    else
    {
        /* copy the bits */
        for (index = 0L; index < length; ++index)
        {
            source_index = index + source_subrange_begin;
            dest_index = index + dest_subrange_begin;

            if (source_heap_data[source_index >> 5] &
                (1L << (source_index & 0x1f)))
            {
                /* set a single bit */
                dest_heap_data[dest_index >> 5] |=
                    (1L << (dest_index & 0x1f));
            }
            else
            {
                /* clear a single bit */
                dest_heap_data[dest_index >> 5] &=
                    (~(uint32_t) (1L << (dest_index & 0x1f)));
            }
        }
    }

    return status;
}

BOOL
urj_jam_check_assignment (char *statement_buffer)
{
    BOOL assignment = false;
    int index = 0;
    char save_ch = 0;
    int variable_begin = 0;
    int variable_end = 0;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;

    while ((jam_is_name_char (statement_buffer[index])) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;                /* skip over variable name */
    }

    if (index < JAMC_MAX_NAME_LENGTH)
    {
        /* check if this is a variable name */
        variable_end = index;
        save_ch = statement_buffer[variable_end];
        statement_buffer[variable_end] = JAMC_NULL_CHAR;

        if (urj_jam_get_symbol_record (&statement_buffer[variable_begin],
                                   &symbol_record) == JAMC_SUCCESS)
        {
            if ((symbol_record->type == JAM_INTEGER_SYMBOL) ||
                (symbol_record->type == JAM_BOOLEAN_SYMBOL) ||
                (symbol_record->type == JAM_INTEGER_ARRAY_WRITABLE) ||
                (symbol_record->type == JAM_BOOLEAN_ARRAY_WRITABLE) ||
                (symbol_record->type == JAM_INTEGER_ARRAY_INITIALIZED) ||
                (symbol_record->type == JAM_BOOLEAN_ARRAY_INITIALIZED))
            {
                assignment = true;
            }
        }

        statement_buffer[variable_end] = save_ch;
    }

    return assignment;
}

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

JAM_RETURN_TYPE
urj_jam_process_assignment (char *statement_buffer, BOOL let)
/*                                                                          */
/*  Description:    Processes a LET (assignment) statement.                 */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int variable_begin = 0;
    int variable_end = 0;
    int dim_begin = 0;
    int dim_end = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int bracket_count = 0;
    int32_t dim_value = 0L;
    int32_t assign_value = 0L;
    char save_ch = 0;
    int32_t source_subrange_begin = 0L;
    int32_t source_subrange_end = 0L;
    int32_t dest_subrange_begin = 0L;
    int32_t dest_subrange_end = 0L;
    BOOL is_array = false;
    BOOL full_array = false;
    BOOL array_subrange = false;
    int32_t *source_heap_data = NULL;
    int32_t *dest_heap_data = NULL;
    int32_t *literal_array_data = NULL;
    JAME_EXPRESSION_TYPE assign_type = JAM_ILLEGAL_EXPR_TYPE;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;


    if (let & (urj_jam_version == 0))
        urj_jam_version = 1;

    if ((!let) & (urj_jam_version == 0))
        urj_jam_version = 2;

    if (((!let) & (urj_jam_version == 1)) || (let & (urj_jam_version == 2)))
    {
        return JAMC_SYNTAX_ERROR;
    }

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    if (let)
    {
        index = urj_jam_skip_instruction_name (statement_buffer);
    }

    if (isalpha (statement_buffer[index]))
    {
        /* locate variable name */
        variable_begin = index;
        while ((jam_is_name_char (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over variable name */
        }
        variable_end = index;

        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        status = JAMC_SUCCESS;

        if (statement_buffer[index] == JAMC_LBRACKET_CHAR)
        {
            /*
             *      Assignment to array element
             */
            ++index;
            is_array = true;
            dim_begin = index;
            while ((isspace (statement_buffer[dim_begin])) &&
                   (dim_begin < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++dim_begin;    /* skip over white space */
            }
            while (((statement_buffer[index] != JAMC_RBRACKET_CHAR) ||
                    (bracket_count > 0)) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                if (statement_buffer[index] == JAMC_LBRACKET_CHAR)
                {
                    ++bracket_count;
                }
                else if (statement_buffer[index] == JAMC_RBRACKET_CHAR)
                {
                    --bracket_count;
                }

                ++index;        /* find matching bracket */
            }
            if (statement_buffer[index] == JAMC_RBRACKET_CHAR)
            {
                dim_end = index;
            }

            if (dim_end == dim_begin)
            {
                /* full array notation */
                full_array = true;
            }
            else if (dim_end > dim_begin)
            {
                /* look for ".." in array index expression */
                index = dim_begin;
                while ((index < dim_end) && !array_subrange)
                {
                    if ((statement_buffer[index] == JAMC_PERIOD_CHAR) &&
                        (statement_buffer[index + 1] == JAMC_PERIOD_CHAR))
                    {
                        array_subrange = true;
                    }
                    ++index;
                }
            }
            else
            {
                /* right bracket not found */
                status = JAMC_SYNTAX_ERROR;
            }

            if (status == JAMC_SUCCESS)
            {
                index = dim_end + 1;
                while ((isspace (statement_buffer[index])) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;    /* skip over white space */
                }

                /* get pointer to symbol record */
                save_ch = statement_buffer[variable_end];
                statement_buffer[variable_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_get_symbol_record (&statement_buffer[variable_begin],
                                           &symbol_record);
                statement_buffer[variable_end] = save_ch;

                /* check array type */
                if (status == JAMC_SUCCESS)
                {
                    switch (symbol_record->type)
                    {
                    case JAM_INTEGER_ARRAY_WRITABLE:
                        assign_type = JAM_INTEGER_EXPR;
                        break;

                    case JAM_BOOLEAN_ARRAY_WRITABLE:
                        assign_type = JAM_BOOLEAN_EXPR;
                        break;

                    case JAM_INTEGER_ARRAY_INITIALIZED:
                    case JAM_BOOLEAN_ARRAY_INITIALIZED:
                        status = JAMC_ASSIGN_TO_CONST;
                        break;

                    default:
                        status = JAMC_TYPE_MISMATCH;
                        break;
                    }
                }

                /* get pointer to heap record */
                if (status == JAMC_SUCCESS)
                {
                    heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

                    if (heap_record == NULL)
                    {
                        status = JAMC_INTERNAL_ERROR;
                    }
                    else
                    {
                        dest_heap_data = heap_record->data;
                    }
                }
            }

            if (status == JAMC_SUCCESS)
            {
                if (full_array || array_subrange)
                {
                    if (assign_type == JAM_BOOLEAN_EXPR)
                    {
                        if (full_array)
                        {
                            dest_subrange_begin = 0L;
                            dest_subrange_end = heap_record->dimension - 1L;
                            array_subrange = true;
                        }
                        else
                        {
                            save_ch = statement_buffer[dim_end];
                            statement_buffer[dim_end] = JAMC_NULL_CHAR;
                            status = urj_jam_get_array_subrange (symbol_record,
                                                             &statement_buffer
                                                             [dim_begin],
                                                             &dest_subrange_begin,
                                                             &dest_subrange_end);
                            statement_buffer[dim_end] = save_ch;

                            /* check array bounds */
                            if ((status == JAMC_SUCCESS) &&
                                ((dest_subrange_begin < 0L) ||
                                 (dest_subrange_begin >=
                                  heap_record->dimension)
                                 || (dest_subrange_end < 0L)
                                 || (dest_subrange_end >=
                                     heap_record->dimension)))
                            {
                                status = JAMC_BOUNDS_ERROR;
                            }
                        }
                    }
                    else
                    {
                        /* can't assign to an integer array */
                        status = JAMC_SYNTAX_ERROR;
                    }
                }
                else
                {
                    /* assign to array element */
                    save_ch = statement_buffer[dim_end];
                    statement_buffer[dim_end] = JAMC_NULL_CHAR;
                    status =
                        urj_jam_evaluate_expression (&statement_buffer[dim_begin],
                                                 &dim_value, &expr_type);
                    statement_buffer[dim_end] = save_ch;

                    /*
                     *      Check for integer expression
                     */
                    if ((status == JAMC_SUCCESS) &&
                        (expr_type != JAM_INTEGER_EXPR) &&
                        (expr_type != JAM_INT_OR_BOOL_EXPR))
                    {
                        status = JAMC_TYPE_MISMATCH;
                    }
                }
            }
        }
        else
        {
            /*
             *      Get type of variable on left-hand-side
             */
            save_ch = statement_buffer[variable_end];
            statement_buffer[variable_end] = JAMC_NULL_CHAR;
            status =
                urj_jam_get_symbol_record (&statement_buffer[variable_begin],
                                       &symbol_record);
            statement_buffer[variable_end] = save_ch;

            if (status == JAMC_SUCCESS)
            {
                switch (symbol_record->type)
                {
                case JAM_INTEGER_SYMBOL:
                    assign_type = JAM_INTEGER_EXPR;
                    break;

                case JAM_BOOLEAN_SYMBOL:
                    assign_type = JAM_BOOLEAN_EXPR;
                    break;

                default:
                    status = JAMC_TYPE_MISMATCH;
                    break;
                }
            }
        }

        /*
         *      Evaluate assignment expression
         */
        if (status == JAMC_SUCCESS)
        {
            status = JAMC_SYNTAX_ERROR;

            if (statement_buffer[index] == JAMC_EQUAL_CHAR)
            {
                /*
                 *      Evaluate assignment expression
                 */
                expr_begin = index + 1;
                while ((isspace (statement_buffer[expr_begin])) &&
                       (expr_begin < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++expr_begin;       /* skip over white space */
                }
                while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;
                }
                while ((statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                       (index > 0))
                {
                    --index;
                }
                expr_end = index;

                if (expr_end > expr_begin)
                {
                    if (array_subrange)
                    {
                        symbol_record = NULL;
                        save_ch = statement_buffer[expr_end];
                        statement_buffer[expr_end] = JAMC_NULL_CHAR;
                        status =
                            urj_jam_get_array_argument (&statement_buffer
                                                    [expr_begin],
                                                    &symbol_record,
                                                    &literal_array_data,
                                                    &source_subrange_begin,
                                                    &source_subrange_end, 0);
                        statement_buffer[expr_end] = save_ch;

                        if (status == JAMC_SUCCESS)
                        {
                            if (symbol_record != NULL)
                            {
                                if ((symbol_record->type ==
                                     JAM_BOOLEAN_ARRAY_WRITABLE) ||
                                    (symbol_record->type ==
                                     JAM_BOOLEAN_ARRAY_INITIALIZED))
                                {
                                    heap_record = (JAMS_HEAP_RECORD *)
                                        symbol_record->value;

                                    /* check array bounds */
                                    if ((source_subrange_begin < 0L) ||
                                        (source_subrange_begin >=
                                         heap_record->dimension) ||
                                        (source_subrange_end < 0L) ||
                                        (source_subrange_end >=
                                         heap_record->dimension))
                                    {
                                        status = JAMC_BOUNDS_ERROR;
                                    }
                                    else
                                    {
                                        source_heap_data = heap_record->data;
                                    }
                                }
                                else
                                {
                                    status = JAMC_TYPE_MISMATCH;
                                }
                            }
                            else if (literal_array_data != NULL)
                            {
                                source_heap_data = literal_array_data;
                            }
                            else
                            {
                                status = JAMC_INTERNAL_ERROR;
                            }
                        }
                    }
                    else
                    {
                        save_ch = statement_buffer[expr_end];
                        statement_buffer[expr_end] = JAMC_NULL_CHAR;
                        status =
                            urj_jam_evaluate_expression (&statement_buffer
                                                     [expr_begin],
                                                     &assign_value,
                                                     &expr_type);
                        statement_buffer[expr_end] = save_ch;
                    }
                }
            }
        }

        if (status == JAMC_SUCCESS)
        {
            /*
             *      Check type of expression against type of variable
             *      being assigned
             */
            if (array_subrange)
            {
                /* copy array data */
                status = urj_jam_copy_array_subrange (source_heap_data,
                                                  source_subrange_begin,
                                                  source_subrange_end,
                                                  dest_heap_data,
                                                  dest_subrange_begin,
                                                  dest_subrange_end);
            }
            else if ((expr_type != JAM_ILLEGAL_EXPR_TYPE) &&
                     (assign_type != JAM_ILLEGAL_EXPR_TYPE) &&
                     ((expr_type == assign_type) ||
                      (expr_type == JAM_INT_OR_BOOL_EXPR)))
            {
                /*
                 *      Set the variable to the computed value
                 */
                if (is_array)
                {
                    /* check array bounds */
                    if ((dim_value >= 0) &&
                        (dim_value < heap_record->dimension))
                    {
                        if (assign_type == JAM_INTEGER_EXPR)
                        {
                            dest_heap_data[dim_value] = assign_value;
                        }
                        else if (assign_type == JAM_BOOLEAN_EXPR)
                        {
                            if (assign_value == 0)
                            {
                                /* clear a single bit */
                                dest_heap_data[dim_value >> 5] &=
                                    (~(uint32_t) (1L << (dim_value & 0x1f)));
                            }
                            else
                            {
                                /* set a single bit */
                                dest_heap_data[dim_value >> 5] |=
                                    (1L << (dim_value & 0x1f));
                            }
                        }
                        else
                        {
                            status = JAMC_INTERNAL_ERROR;
                        }
                    }
                    else
                    {
                        status = JAMC_BOUNDS_ERROR;
                    }
                }
                else
                {
                    symbol_record->value = assign_value;
                }
            }
            else
            {
                status = JAMC_TYPE_MISMATCH;
            }
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_next (char *statement_buffer)
/*                                                                          */
/*  Description:    Processes a NEXT statement.  The NEXT statement is      */
/*                  used to mark the bottom of a FOR loop.  When a NEXT     */
/*                  statement is processed, there must be a corresponding   */
/*                  FOR loop stack record on top of the stack.              */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int variable_begin = 0;
    int variable_end = 0;
    char save_ch = 0;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_STACK_RECORD *stack_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    if (isalpha (statement_buffer[index]))
    {
        /* locate variable name */
        variable_begin = index;
        while ((jam_is_name_char (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over variable name */
        }
        variable_end = index;

        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
        {
            /*
             *      Look in symbol table for iterator variable
             */
            save_ch = statement_buffer[variable_end];
            statement_buffer[variable_end] = JAMC_NULL_CHAR;
            status =
                urj_jam_get_symbol_record (&statement_buffer[variable_begin],
                                       &symbol_record);
            statement_buffer[variable_end] = save_ch;

            if ((status == JAMC_SUCCESS) &&
                (symbol_record->type != JAM_INTEGER_SYMBOL))
            {
                status = JAMC_TYPE_MISMATCH;
            }
        }

        if (status == JAMC_SUCCESS)
        {
            /*
             *      Get stack record at top of stack
             */
            stack_record = urj_jam_peek_stack_record ();

            /*
             *      Compare iterator to stack record
             */
            if ((stack_record == NULL) ||
                (stack_record->type != JAM_STACK_FOR_NEXT) ||
                (stack_record->iterator != symbol_record))
            {
                status = JAMC_NEXT_UNEXPECTED;
            }
            else
            {
                /*
                 *      Check if loop has run to completion
                 */
                if (((stack_record->step_value > 0) &&
                     (symbol_record->value >= stack_record->stop_value)) ||
                    ((stack_record->step_value < 0) &&
                     (symbol_record->value <= stack_record->stop_value)))
                {
                    /*
                     *      Loop has run to completion -- pop the stack record.
                     *      (Do not jump back to FOR statement position.)
                     */
                    status = urj_jam_pop_stack_record ();
                }
                else
                {
                    /*
                     *      Increment (or step) the iterator variable
                     */
                    symbol_record->value += stack_record->step_value;

                    /*
                     *      Jump back to the top of the loop
                     */
                    if (urj_jam_seek (stack_record->for_position) == 0)
                    {
                        urj_jam_current_file_position =
                            stack_record->for_position;
                        status = JAMC_SUCCESS;
                    }
                    else
                    {
                        status = JAMC_IO_ERROR;
                    }
                }
            }
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_padding (char *statement_buffer)
/*                                                                          */
/*  Description:    Processes a PADDING statement.  This sets the number    */
/*                  of padding bits to be used before and after the data    */
/*                  indicated for each DRSCAN and IRSCAN operation.         */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int argc = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    char save_ch = 0;
    int32_t padding[4] = { 0 };
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    if (urj_jam_version == 0)
        urj_jam_version = 1;

    if (urj_jam_version == 2)
    {
        /* The PADDING statement is not supported in Jam 2.0 */
        status = JAMC_SYNTAX_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    for (argc = 0; (argc < 4) && (status == JAMC_SUCCESS); ++argc)
    {
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        if (status == JAMC_SUCCESS)
        {
            padding[argc] = -1L;

            expr_begin += index;
            expr_end += index;
            delimiter += index;

            if (((argc < 3) &&
                 (statement_buffer[delimiter] == JAMC_COMMA_CHAR)) ||
                ((argc == 3) &&
                 (statement_buffer[delimiter] == JAMC_SEMICOLON_CHAR)))
            {
                save_ch = statement_buffer[expr_end];
                statement_buffer[expr_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                             &padding[argc], &expr_type);
                statement_buffer[expr_end] = save_ch;

                /*
                 *      Check for integer expression
                 */
                if ((status == JAMC_SUCCESS) &&
                    (expr_type != JAM_INTEGER_EXPR) &&
                    (expr_type != JAM_INT_OR_BOOL_EXPR))
                {
                    status = JAMC_TYPE_MISMATCH;
                }

                /*
                 *      Check the range -- padding value must be between 0 and 1000
                 */
                if ((status == JAMC_SUCCESS) &&
                    ((padding[argc] < 0L) || (padding[argc] > 1000L)))
                {
                    status = JAMC_SYNTAX_ERROR;
                }
                else
                {
                    index = expr_end + 1;
                }
            }
            else
            {
                status = JAMC_SYNTAX_ERROR;
            }
        }
    }

    /*
     *      Store the new padding values
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_set_dr_preamble ((int) padding[0], 0, NULL);

        if (status == JAMC_SUCCESS)
        {
            status = urj_jam_set_dr_postamble ((int) padding[1], 0, NULL);
        }

        if (status == JAMC_SUCCESS)
        {
            status = urj_jam_set_ir_preamble ((int) padding[2], 0, NULL);
        }

        if (status == JAMC_SUCCESS)
        {
            status = urj_jam_set_ir_postamble ((int) padding[3], 0, NULL);
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_pop (char *statement_buffer)
/*                                                                          */
/*  Description:    Pops a data element (integer or Boolean) from the       */
/*                  internal stack.  The data value is stored in the        */
/*                  variable specified.  If the type of data is not         */
/*                  compatible with the variable type, a type mismatch      */
/*                  error results.                                          */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int32_t push_value = 0L;
    int32_t dim_value = 0L;
    int variable_begin = 0;
    int variable_end = 0;
    int dim_begin = 0;
    int dim_end = 0;
    int bracket_count = 0;
    char save_ch = 0;
    BOOL is_array = false;
    int32_t *heap_data = NULL;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_STACK_RECORD *stack_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAME_EXPRESSION_TYPE assign_type = JAM_ILLEGAL_EXPR_TYPE;
    JAME_EXPRESSION_TYPE value_type = JAM_ILLEGAL_EXPR_TYPE;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Get the variable name
     */
    if (isalpha (statement_buffer[index]))
    {
        variable_begin = index;
        while ((jam_is_name_char (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over variable name */
        }
        variable_end = index;

        while ((isspace (statement_buffer[index])) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;            /* skip over white space */
        }

        if (statement_buffer[index] == JAMC_LBRACKET_CHAR)
        {
            /*
             *      Pop value into array element
             */
            ++index;
            is_array = true;
            dim_begin = index;
            while (((statement_buffer[index] != JAMC_RBRACKET_CHAR) ||
                    (bracket_count > 0)) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                if (statement_buffer[index] == JAMC_LBRACKET_CHAR)
                {
                    ++bracket_count;
                }
                else if (statement_buffer[index] == JAMC_RBRACKET_CHAR)
                {
                    --bracket_count;
                }

                ++index;        /* find matching bracket */
            }
            if (statement_buffer[index] == JAMC_RBRACKET_CHAR)
            {
                dim_end = index;
                ++index;
            }
            while ((isspace (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over white space */
            }

            if (dim_end > dim_begin)
            {
                save_ch = statement_buffer[dim_end];
                statement_buffer[dim_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_evaluate_expression (&statement_buffer[dim_begin],
                                             &dim_value, &expr_type);
                statement_buffer[dim_end] = save_ch;
            }

            /*
             *      Check for integer expression
             */
            if ((status == JAMC_SUCCESS) &&
                (expr_type != JAM_INTEGER_EXPR) &&
                (expr_type != JAM_INT_OR_BOOL_EXPR))
            {
                status = JAMC_TYPE_MISMATCH;
            }

            if (status == JAMC_SUCCESS)
            {
                /* get pointer to symbol record */
                save_ch = statement_buffer[variable_end];
                statement_buffer[variable_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_get_symbol_record (&statement_buffer[variable_begin],
                                           &symbol_record);
                statement_buffer[variable_end] = save_ch;

                /* check array type */
                if (status == JAMC_SUCCESS)
                {
                    switch (symbol_record->type)
                    {
                    case JAM_INTEGER_ARRAY_WRITABLE:
                        assign_type = JAM_INTEGER_EXPR;
                        break;

                    case JAM_BOOLEAN_ARRAY_WRITABLE:
                        assign_type = JAM_BOOLEAN_EXPR;
                        break;

                    case JAM_INTEGER_ARRAY_INITIALIZED:
                    case JAM_BOOLEAN_ARRAY_INITIALIZED:
                        status = JAMC_ASSIGN_TO_CONST;
                        break;

                    default:
                        status = JAMC_TYPE_MISMATCH;
                        break;
                    }
                }

                /* get pointer to heap record */
                if (status == JAMC_SUCCESS)
                {
                    heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

                    if (heap_record == NULL)
                    {
                        status = JAMC_INTERNAL_ERROR;
                    }
                    else
                    {
                        heap_data = &heap_record->data[0];
                    }
                }
            }
        }
        else
        {
            /*
             *      Poping value into scalar (not array) variable
             */
            if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
            {
                /*
                 *      Get variable type
                 */
                save_ch = statement_buffer[variable_end];
                statement_buffer[variable_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_get_symbol_record (&statement_buffer[variable_begin],
                                           &symbol_record);
                statement_buffer[variable_end] = save_ch;

                if (status == JAMC_SUCCESS)
                {
                    switch (symbol_record->type)
                    {
                    case JAM_INTEGER_SYMBOL:
                        assign_type = JAM_INTEGER_EXPR;
                        break;

                    case JAM_BOOLEAN_SYMBOL:
                        assign_type = JAM_BOOLEAN_EXPR;
                        break;

                    default:
                        status = JAMC_TYPE_MISMATCH;
                        break;
                    }
                }
            }
            else
            {
                status = JAMC_SYNTAX_ERROR;
            }
        }

        /*
         *      Get stack record at top of stack
         */
        stack_record = urj_jam_peek_stack_record ();

        /*
         *      Check that stack record corresponds to a PUSH statement
         */
        if ((stack_record != NULL) &&
            (stack_record->type == JAM_STACK_PUSH_POP))
        {
            /*
             *      Stack record is the correct type -- pop it off the stack.
             */
            push_value = stack_record->push_value;
            status = urj_jam_pop_stack_record ();

            /*
             *      Now set the variable to the push value
             */
            if (status == JAMC_SUCCESS)
            {
                /*
                 *      Check type of expression against type of variable
                 *      being assigned
                 */
                if ((push_value == 0) || (push_value == 1))
                {
                    value_type = JAM_INT_OR_BOOL_EXPR;
                }
                else
                    value_type = JAM_INTEGER_EXPR;

                if ((assign_type != JAM_ILLEGAL_EXPR_TYPE) &&
                    ((value_type == assign_type) ||
                     (value_type == JAM_INT_OR_BOOL_EXPR)))
                {
                    /*
                     *      Set the variable to the computed value
                     */
                    if (is_array)
                    {
                        if (assign_type == JAM_INTEGER_EXPR)
                        {
                            heap_data[dim_value] = push_value;
                        }
                        else if (assign_type == JAM_BOOLEAN_EXPR)
                        {
                            if (push_value == 0)
                            {
                                /* clear a single bit */
                                heap_data[dim_value >> 5] &=
                                    (~(uint32_t) (1L << (dim_value & 0x1f)));
                            }
                            else
                            {
                                /* set a single bit */
                                heap_data[dim_value >> 5] |=
                                    (1L << (dim_value & 0x1f));
                            }
                        }
                        else
                            status = JAMC_INTERNAL_ERROR;
                    }
                    else
                    {
                        symbol_record->value = push_value;
                    }
                }
                else
                {
                    status = JAMC_TYPE_MISMATCH;
                }
            }
        }
        else
        {
            /*
             *      Top of stack did not have a PUSH/POP record
             */
            status = JAMC_POP_UNEXPECTED;
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_pre_post
    (JAME_INSTRUCTION instruction_code, char *statement_buffer)
/*                                                                          */
/*  Description:    Processes the PREDR, PREIR, POSTDR, and POSTIR          */
/*                  statements.  These statements together replace the      */
/*                  PADDING statement from the JAM 1.0 language spec.       */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    char save_ch = 0;
    int32_t count = 0L;
    int32_t start_index = 0L;
    int32_t stop_index = 0L;
    int32_t *literal_array_data = NULL;
    int32_t *padding_data = NULL;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      First, get the count value
     */
    status = urj_jam_find_argument (&statement_buffer[index],
                                &expr_begin, &expr_end, &delimiter);

    expr_begin += index;
    expr_end += index;
    delimiter += index;

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status =
            urj_jam_evaluate_expression (&statement_buffer[expr_begin], &count,
                                     &expr_type);
        statement_buffer[expr_end] = save_ch;

        /*
         *      Check for integer expression
         */
        if ((status == JAMC_SUCCESS) &&
            (expr_type != JAM_INTEGER_EXPR) &&
            (expr_type != JAM_INT_OR_BOOL_EXPR))
        {
            status = JAMC_TYPE_MISMATCH;
        }

        /*
         *      Check the range -- count value must be between 0 and 1000
         */
        if ((status == JAMC_SUCCESS) && ((count < 0L) || (count > 1000L)))
        {
            status = JAMC_SYNTAX_ERROR;
        }
    }

    /*
     *      Second, get the optional padding data pattern (Boolean array)
     */
    if (status == JAMC_SUCCESS)
    {
        if (statement_buffer[delimiter] == JAMC_COMMA_CHAR)
        {
            expr_begin = delimiter + 1;
            expr_end = expr_begin;
            while ((isspace (statement_buffer[expr_begin])) &&
                   (expr_begin < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++expr_begin;   /* skip over white space */
            }
            while ((statement_buffer[expr_end] != JAMC_NULL_CHAR) &&
                   (expr_end < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++expr_end;
            }
            while ((statement_buffer[expr_end] != JAMC_SEMICOLON_CHAR) &&
                   (expr_end > 0))
            {
                --expr_end;
            }

            if (expr_end > expr_begin)
            {
                save_ch = statement_buffer[expr_end];
                statement_buffer[expr_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                            &symbol_record,
                                            &literal_array_data, &start_index,
                                            &stop_index, 0);
                statement_buffer[expr_end] = save_ch;

                if ((status == JAMC_SUCCESS) &&
                    (stop_index < (start_index + count - 1)))
                {
                    status = JAMC_BOUNDS_ERROR;
                }

                if (status == JAMC_SUCCESS)
                {
                    if (symbol_record != NULL)
                    {
                        heap_record =
                            (JAMS_HEAP_RECORD *) symbol_record->value;

                        if (heap_record != NULL)
                        {
                            padding_data = heap_record->data;
                        }
                        else
                        {
                            status = JAMC_INTERNAL_ERROR;
                        }
                    }
                    else if (literal_array_data != NULL)
                    {
                        padding_data = literal_array_data;
                    }
                    else
                    {
                        status = JAMC_INTERNAL_ERROR;
                    }
                }
            }
            else
            {
                status = JAMC_SYNTAX_ERROR;
            }
        }
        else if (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR)
        {
            status = JAMC_SYNTAX_ERROR;
        }
    }

    /*
     *      Store the new padding value
     */
    if (status == JAMC_SUCCESS)
    {
        switch (instruction_code)
        {
        case JAM_POSTDR_INSTR:
            status = urj_jam_set_dr_postamble ((int) count, (int) start_index,
                                           padding_data);
            break;

        case JAM_POSTIR_INSTR:
            status = urj_jam_set_ir_postamble ((int) count, (int) start_index,
                                           padding_data);
            break;

        case JAM_PREDR_INSTR:
            status = urj_jam_set_dr_preamble ((int) count, (int) start_index,
                                          padding_data);
            break;

        case JAM_PREIR_INSTR:
            status = urj_jam_set_ir_preamble ((int) count, (int) start_index,
                                          padding_data);
            break;

        default:
            status = JAMC_INTERNAL_ERROR;
            break;
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_print (char *statement_buffer)
/*                                                                          */
/*  Description:    Processes a PRINT statement.  Only constant literal     */
/*                  strings and INTEGER or BOOLEAN expressions are          */
/*                  supported.                                              */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int dest_index = 0;
    char *text_buffer = NULL;
    int expr_begin = 0;
    int expr_end = 0;
    char save_ch = 0;
    int32_t expr_value = 0L;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    text_buffer = malloc (JAMC_MAX_STATEMENT_LENGTH + 1024);

    if (text_buffer == NULL)
    {
        status = JAMC_OUT_OF_MEMORY;
    }
    else
    {
        index = urj_jam_skip_instruction_name (statement_buffer);
    }

    while ((status == JAMC_SUCCESS) &&
           (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        /*
         *      Get arguments from statement and concatenate onto string
         */
        if (statement_buffer[index] == JAMC_QUOTE_CHAR)
        {
            /*
             *      Argument is explicit string - copy it
             */
            ++index;
            while ((statement_buffer[index] != JAMC_QUOTE_CHAR) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH) &&
                   (dest_index < JAMC_MAX_STATEMENT_LENGTH))
            {
                text_buffer[dest_index++] = statement_buffer[index++];
            }
            text_buffer[dest_index] = '\0';

            if (statement_buffer[index] == JAMC_QUOTE_CHAR)
            {
                /* skip over terminating quote character */
                ++index;
            }
            else
            {
                /* terminating quote character not found */
                status = JAMC_SYNTAX_ERROR;
            }
        }
        else if ((statement_buffer[index] == 'C') &&
                 (statement_buffer[index + 1] == 'H') &&
                 (statement_buffer[index + 2] == 'R') &&
                 (statement_buffer[index + 3] == JAMC_DOLLAR_CHAR) &&
                 (statement_buffer[index + 4] == JAMC_LPAREN_CHAR))
        {
            /*
             *      Convert integer expression to character code
             */
            index += 4;         /* skip over CHR$, point to left parenthesis */
            expr_begin = index;
            expr_end = 0;

            while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                   (statement_buffer[index] != JAMC_COMMA_CHAR) &&
                   (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;
            }

            if ((statement_buffer[index] == JAMC_COMMA_CHAR) ||
                (statement_buffer[index] == JAMC_SEMICOLON_CHAR))
            {
                expr_end = index;
            }

            if (expr_end > expr_begin)
            {
                save_ch = statement_buffer[expr_end];
                statement_buffer[expr_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                             &expr_value, NULL);
                statement_buffer[expr_end] = save_ch;
            }
            else
            {
                status = JAMC_SYNTAX_ERROR;
            }

            /*
             *      Allow any seven-bit character code (zero to 127)
             */
            if ((status == JAMC_SUCCESS) &&
                ((expr_value < 0) || (expr_value > 127)))
            {
                /* character code out of range */

                /* instead of flagging an error, force the value to 127 */
                expr_value = 127;
            }

            if ((status == JAMC_SUCCESS) &&
                (dest_index >= JAMC_MAX_STATEMENT_LENGTH))
            {
                /* no space in output buffer */
                status = JAMC_SYNTAX_ERROR;
            }

            if (status == JAMC_SUCCESS)
            {
                /*
                 *      Put the character code directly into the output buffer
                 */
                text_buffer[dest_index++] = (char) expr_value;
                text_buffer[dest_index] = '\0';
            }
        }
        else
        {
            /*
             *      Process it as an integer expression
             */
            expr_begin = index;
            expr_end = 0;
            status = JAMC_SYNTAX_ERROR;

            while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
                   (statement_buffer[index] != JAMC_COMMA_CHAR) &&
                   (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;
            }

            if ((statement_buffer[index] == JAMC_COMMA_CHAR) ||
                (statement_buffer[index] == JAMC_SEMICOLON_CHAR))
            {
                expr_end = index;
            }

            if (expr_end > expr_begin)
            {
                save_ch = statement_buffer[expr_end];
                statement_buffer[expr_end] = JAMC_NULL_CHAR;
                status =
                    urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                             &expr_value, NULL);
                statement_buffer[expr_end] = save_ch;
            }

            if (status == JAMC_SUCCESS)
            {
                /*
                 *      Convert integer and concatenate to output string
                 */
                jam_ltoa (&text_buffer[dest_index], expr_value);

                /* advance pointer to new end of string */
                while ((text_buffer[dest_index] != JAMC_NULL_CHAR) &&
                       (dest_index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++dest_index;
                }
            }
        }

        if (status == JAMC_SUCCESS)
        {
            while ((isspace (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over white space */
            }

            if (statement_buffer[index] == JAMC_COMMA_CHAR)
            {
                /*
                 *      Skip over comma and white space to process next argument
                 */
                ++index;
                while ((isspace (statement_buffer[index])) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;    /* skip over white space */
                }
            }
            else if (statement_buffer[index] != JAMC_SEMICOLON_CHAR)
            {
                /*
                 *      If no comma to seperate arguments, statement must be
                 *      terminated by a semicolon
                 */
                status = JAMC_SYNTAX_ERROR;
            }
        }
    }

    if (status == JAMC_SUCCESS)
    {
        urj_jam_message (text_buffer);
    }

    if (text_buffer != NULL)
        free (text_buffer);

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_procedure (char *statement_buffer)
/*                                                                          */
/*  Description:    Initializes a procedure block.  This function does not  */
/*                  actually execute the procedure, it merely adds it to    */
/*                  the symbol table so it may be executed later.           */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int procname_begin = 0;
    int procname_end = 0;
    char save_ch = 0;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;

    if (urj_jam_version == 0)
        urj_jam_version = 2;

    if (urj_jam_version == 1)
        status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        status = JAMC_PHASE_ERROR;
    }

    if ((urj_jam_version == 2) && (urj_jam_phase == JAM_ACTION_PHASE))
    {
        status = JAMC_ACTION_NOT_FOUND;
    }

    if (status == JAMC_SUCCESS)
    {
        index = urj_jam_skip_instruction_name (statement_buffer);

        if (isalpha (statement_buffer[index]))
        {
            /*
             *      Get the procedure name
             */
            procname_begin = index;
            while ((jam_is_name_char (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over procedure name */
            }
            procname_end = index;

            save_ch = statement_buffer[procname_end];
            statement_buffer[procname_end] = JAMC_NULL_CHAR;
            status = urj_jam_add_symbol (JAM_PROCEDURE_BLOCK,
                                     &statement_buffer[procname_begin], 0L,
                                     urj_jam_current_statement_position);
            /* get a pointer to the symbol record */
            if (status == JAMC_SUCCESS)
            {
                status =
                    urj_jam_get_symbol_record (&statement_buffer[procname_begin],
                                           &symbol_record);
            }
            statement_buffer[procname_end] = save_ch;

            while ((isspace (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over white space */
            }
        }
        else
        {
            status = JAMC_SYNTAX_ERROR;
        }
    }

    if (status == JAMC_SUCCESS)
    {
        /*
         *      Get list of USES blocks
         */
        if (statement_buffer[index] != JAMC_SEMICOLON_CHAR)
        {
            if ((strncmp (&statement_buffer[index], "USES", 4) == 0) &&
                (isspace (statement_buffer[index + 4])))
            {
                /*
                 *      Get list of USES blocks
                 */
                index += 4;     /* skip over USES keyword */

                while ((isspace (statement_buffer[index])) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;    /* skip over white space */
                }

                if (symbol_record->value == 0)
                {
                    status = urj_jam_add_heap_record (symbol_record, &heap_record,
                                                  strlen
                                                  (&statement_buffer[index]) +
                                                  1);

                    if (status == JAMC_SUCCESS)
                    {
                        symbol_record->value = (int32_t) heap_record;
                        strcpy ((char *) heap_record->data,
                                    &statement_buffer[index]);
                    }
                }
                else
                {
                    heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;
                }

                /*
                 *      Ignore the USES clause -- it will be processed later
                 */
                while ((statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
                       (statement_buffer[index] != JAMC_NULL_CHAR) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;
                }
            }
            else
            {
                /* error: expected USES keyword */
                status = JAMC_SYNTAX_ERROR;
            }
        }
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_push (char *statement_buffer)
/*                                                                          */
/*  Description:    Pushes an integer or Boolean value onto the stack       */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    char save_ch = 0;
    int32_t push_value = 0L;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Evaluate expression for the PUSH value
     */
    expr_begin = index;
    while ((statement_buffer[index] != JAMC_NULL_CHAR) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;
    }
    while ((statement_buffer[index] != JAMC_SEMICOLON_CHAR) && (index > 0))
    {
        --index;
    }
    expr_end = index;

    if (expr_end > expr_begin)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status =
            urj_jam_evaluate_expression (&statement_buffer[expr_begin],
                                     &push_value, NULL);
        statement_buffer[expr_end] = save_ch;
    }

    /*
     *      Push the value onto the stack
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_push_pushpop_record (push_value);
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_return (char *statement_buffer, BOOL endproc)
/*                                                                          */
/*  Description:    Returns from subroutine by popping the return address   */
/*                  off the stack                                           */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int32_t return_position = 0L;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;
    JAMS_STACK_RECORD *stack_record = NULL;

    if ((urj_jam_version == 0) && endproc)
        urj_jam_version = 2;

    if ((urj_jam_version == 0) && !endproc)
        urj_jam_version = 1;

    if ((urj_jam_version == 2) && !endproc)
    {
        /* Jam 2.0 does not support the RETURN statement */
        return JAMC_SYNTAX_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      The semicolon must be next.
     */
    if (statement_buffer[index] == JAMC_SEMICOLON_CHAR)
    {
        /*
         *      Get stack record at top of stack
         */
        stack_record = urj_jam_peek_stack_record ();

        /*
         *      Check that stack record corresponds to a CALL statement
         */
        if ((stack_record != NULL) &&
            (stack_record->type == JAM_STACK_CALL_RETURN))
        {
            /*
             *      Stack record is the correct type -- pop it off the stack.
             */
            return_position = stack_record->return_position;
            status = urj_jam_pop_stack_record ();

            /*
             *      Now jump to the return address
             */
            if (status == JAMC_SUCCESS)
            {
                if (urj_jam_seek (return_position) == 0)
                {
                    urj_jam_current_file_position = return_position;
                }
                else
                {
                    /* seek failed */
                    status = JAMC_IO_ERROR;
                }
            }
        }
        else
        {
            status = JAMC_RETURN_UNEXPECTED;
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_find_state_argument
    (char *statement_buffer, int *begin, int *end, int *delimiter)
/*                                                                          */
/*  Description:    Special version of urj_jam_find_argument() for state paths. */
/*                  Valid delimiters are whitespace, COMMA, or SEMICOLON.   */
/*                  Returns indices of begin and end of argument, and the   */
/*                  delimiter after the argument.                           */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    while ((isspace (statement_buffer[index])) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;                /* skip over white space */
    }

    *begin = index;

    /* loop until white space or comma or semicolon */
    while ((!isspace (statement_buffer[index])) &&
           (statement_buffer[index] != JAMC_NULL_CHAR) &&
           (statement_buffer[index] != JAMC_COMMA_CHAR) &&
           (statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
           (index < JAMC_MAX_STATEMENT_LENGTH))
    {
        ++index;
    }

    if ((!isspace (statement_buffer[index])) &&
        (statement_buffer[index] != JAMC_COMMA_CHAR) &&
        (statement_buffer[index] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }
    else
    {
        *end = index;           /* end is position after last argument character */

        *delimiter = index;     /* delimiter is position of comma or semicolon */

        /* check whether a comma or semicolon comes after the white space */
        while ((isspace (statement_buffer[index])) &&
               (statement_buffer[index] != JAMC_NULL_CHAR) &&
               (index < JAMC_MAX_STATEMENT_LENGTH))
        {
            ++index;
        }

        if ((statement_buffer[index] == JAMC_COMMA_CHAR) ||
            (statement_buffer[index] == JAMC_SEMICOLON_CHAR))
        {
            *delimiter = index; /* send the real delimiter */
        }

    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_state (char *statement_buffer)
/*                                                                          */
/*  Description:    Forces JTAG chain to specified state, or through        */
/*                  specified sequence of states                            */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    char save_ch = 0;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    JAME_JTAG_STATE state = JAM_ILLEGAL_JTAG_STATE;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    do
    {
        /*
         *      Get next argument
         */
        status = urj_jam_find_state_argument (&statement_buffer[index],
                                          &expr_begin, &expr_end, &delimiter);

        if (status == JAMC_SUCCESS)
        {
            expr_begin += index;
            expr_end += index;
            delimiter += index;

            save_ch = statement_buffer[expr_end];
            statement_buffer[expr_end] = JAMC_NULL_CHAR;
            state =
                urj_jam_get_jtag_state_from_name (&statement_buffer[expr_begin]);

            if (state == JAM_ILLEGAL_JTAG_STATE)
            {
                status = JAMC_SYNTAX_ERROR;
            }
            else
            {
                /*
                 *      Go to the specified state
                 */
                status = urj_jam_goto_jtag_state (state);
                index = delimiter + 1;
            }

            statement_buffer[expr_end] = save_ch;
        }
    }
    while ((status == JAMC_SUCCESS) &&
           ((isspace (statement_buffer[delimiter])) ||
            (statement_buffer[delimiter] == JAMC_COMMA_CHAR)));

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_trst (char *statement_buffer)
/*                                                                          */
/*  Description:    Asserts the TRST signal to the JTAG hardware interface. */
/*                  NOTE: this does not guarantee a chain reset, because    */
/*                  some devices in the chain may not use the TRST signal.  */
/*                                                                          */
/*                  TRST <integer-expr> CYCLES;     -or-                    */
/*                  TRST <integer-expr> USEC;       -or-                    */
/*                  TRST <integer-expr> CYCLES, <integer-expr> USEC;        */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    if (urj_jam_version == 0)
        urj_jam_version = 2;

    if (urj_jam_version == 1)
        status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        status = JAMC_PHASE_ERROR;
    }

    /* assert TRST...  NOT IMPLEMENTED YET! */

    status = urj_jam_process_wait (statement_buffer);

    /* release TRST...  NOT IMPLEMENTED YET! */

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_vector_capture
    (char *statement_buffer,
     int signal_count, int32_t *dir_vector, int32_t *data_vector)
/*                                                                          */
/*  Description:    Applies signals to non-JTAG hardware interface, reads   */
/*                  back signals from hardware, and stores values in the    */
/*                  capture array.  The syntax for the entire statement is: */
/*                                                                          */
/*                  VECTOR <dir>, <data>, CAPTURE <capture> ;               */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int32_t start_index = 0L;
    int32_t stop_index = 0L;
    char save_ch = 0;
    int32_t *literal_array_data = NULL;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    /*
     *      Statement buffer should contain the part of the statement string
     *      after the CAPTURE keyword.
     *
     *      The only argument should be the capture array.
     */
    status = urj_jam_find_argument (statement_buffer,
                                &expr_begin, &expr_end, &delimiter);

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &start_index, &stop_index, 2);
        statement_buffer[expr_end] = save_ch;
    }

    if ((status == JAMC_SUCCESS) && (literal_array_data != NULL))
    {
        /* literal array may not be used for capture buffer */
        status = JAMC_SYNTAX_ERROR;
    }

    if ((status == JAMC_SUCCESS) &&
        (stop_index != start_index + signal_count - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (!heap_record)
                status = JAMC_INTERNAL_ERROR;
        }
        else
            status = JAMC_INTERNAL_ERROR;
    }

    /*
     *      Perform the VECTOR operation, capturing data into the heap buffer
     */
    if (status == JAMC_SUCCESS)
    {
        //if (jam_vector_io (signal_count, dir_vector, data_vector,
        //                   capture_buffer) != signal_count)
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_vector_compare
    (char *statement_buffer,
     int signal_count, int32_t *dir_vector, int32_t *data_vector)
/*                                                                          */
/*  Description:    Applies signals to non-JTAG hardware interface, reads   */
/*                  back signals from hardware, and compares values to the  */
/*                  expected values.  Result is stored in a BOOLEAN         */
/*                  variable.  The syntax for the entire statement is:      */
/*                                                                          */
/*          VECTOR <dir>, <data>, COMPARE <expected>, <mask>, <result> ;    */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int bit = 0;
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int actual = 0;
    int expected = 0;
    int mask = 0;
    int32_t comp_start_index = 0L;
    int32_t comp_stop_index = 0L;
    int32_t mask_start_index = 0L;
    int32_t mask_stop_index = 0L;
    char save_ch = 0;
    int32_t *temp_array = NULL;
    BOOL result = true;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    int32_t *comp_data = NULL;
    int32_t *mask_data = NULL;
    int32_t *literal_array_data = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    /*
     *      Statement buffer should contain the part of the statement string
     *      after the COMPARE keyword.
     *
     *      The first argument should be the compare array.
     */
    status = urj_jam_find_argument (statement_buffer,
                                &expr_begin, &expr_end, &delimiter);

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &comp_start_index, &comp_stop_index,
                                         2);
        statement_buffer[expr_end] = save_ch;
        index = delimiter + 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (literal_array_data != NULL) &&
        (comp_start_index == 0) && (comp_stop_index > signal_count - 1))
    {
        comp_stop_index = signal_count - 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (comp_stop_index != comp_start_index + signal_count - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                comp_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            comp_data = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Find the next argument -- should be the mask array
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &mask_start_index, &mask_stop_index,
                                         3);
        statement_buffer[expr_end] = save_ch;
        index = delimiter + 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (literal_array_data != NULL) &&
        (mask_start_index == 0) && (mask_stop_index > signal_count - 1))
    {
        mask_stop_index = signal_count - 1;
    }

    if ((status == JAMC_SUCCESS) &&
        (mask_stop_index != mask_start_index + signal_count - 1))
    {
        status = JAMC_BOUNDS_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                mask_data = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            mask_data = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Find the third argument -- should be the result variable
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    /*
     *      Result must be a scalar Boolean variable
     */
    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_symbol_record (&statement_buffer[expr_begin],
                                        &symbol_record);
        statement_buffer[expr_end] = save_ch;

        if ((status == JAMC_SUCCESS) &&
            (symbol_record->type != JAM_BOOLEAN_SYMBOL))
        {
            status = JAMC_TYPE_MISMATCH;
        }
    }

    /*
     *      Find some free memory on the heap
     */
    if (status == JAMC_SUCCESS)
    {
        temp_array = urj_jam_get_temp_workspace ((signal_count >> 3) + 4);

        if (temp_array == NULL)
        {
            status = JAMC_OUT_OF_MEMORY;
        }
    }

    /*
     *      Do the VECTOR operation, saving the result in temp_array
     */
    if (status == JAMC_SUCCESS)
    {
        //if (jam_vector_io (signal_count, dir_vector, data_vector,
        //                   temp_array) != signal_count)
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Mask the data and do the comparison
     */
    if (status == JAMC_SUCCESS)
    {
        for (bit = 0; (bit < signal_count) && result; ++bit)
        {
            actual = temp_array[bit >> 5] & (1L << (bit & 0x1f)) ? 1 : 0;
            expected = comp_data[(bit + comp_start_index) >> 5]
                & (1L << ((bit + comp_start_index) & 0x1f)) ? 1 : 0;
            mask = mask_data[(bit + mask_start_index) >> 5]
                & (1L << ((bit + mask_start_index) & 0x1f)) ? 1 : 0;

            if ((actual & mask) != (expected & mask))
            {
                result = false;
            }
        }

        symbol_record->value = result ? 1L : 0L;
    }

    if (temp_array != NULL)
        urj_jam_free_temp_workspace (temp_array);

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_vector (char *statement_buffer)
/*                                                                          */
/*  Description:    Applies signals to non-JTAG hardware interface.  There  */
/*                  are three versions:  output only, compare, and capture. */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    /* syntax:  VECTOR <dir>, <data>; */
    /* or:      VECTOR <dir>, <data>, CAPTURE <capture> ; */
    /* or:      VECTOR <dir>, <data>, COMPARE <expected>, <mask>, <result> ; */

    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    int32_t dir_start_index = 0L;
    int32_t dir_stop_index = 0L;
    int32_t data_start_index = 0L;
    int32_t data_stop_index = 0L;
    char save_ch = 0;
    int32_t *dir_vector = NULL;
    int32_t *data_vector = NULL;
    int32_t *literal_array_data = NULL;
    JAMS_SYMBOL_RECORD *symbol_record = NULL;
    JAMS_HEAP_RECORD *heap_record = NULL;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    /*
     *      Get direction vector
     */
    status = urj_jam_find_argument (&statement_buffer[index],
                                &expr_begin, &expr_end, &delimiter);

    expr_begin += index;
    expr_end += index;
    delimiter += index;

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &dir_start_index, &dir_stop_index,
                                         0);
        statement_buffer[expr_end] = save_ch;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                dir_vector = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            dir_vector = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    /*
     *      Get data vector
     */
    if (status == JAMC_SUCCESS)
    {
        index = delimiter + 1;
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        expr_begin += index;
        expr_end += index;
        delimiter += index;
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_COMMA_CHAR) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        save_ch = statement_buffer[expr_end];
        statement_buffer[expr_end] = JAMC_NULL_CHAR;
        status = urj_jam_get_array_argument (&statement_buffer[expr_begin],
                                         &symbol_record, &literal_array_data,
                                         &data_start_index, &data_stop_index,
                                         1);
        statement_buffer[expr_end] = save_ch;
    }

    if (status == JAMC_SUCCESS)
    {
        if (symbol_record != NULL)
        {
            heap_record = (JAMS_HEAP_RECORD *) symbol_record->value;

            if (heap_record != NULL)
            {
                data_vector = heap_record->data;
            }
            else
            {
                status = JAMC_INTERNAL_ERROR;
            }
        }
        else if (literal_array_data != NULL)
        {
            data_vector = literal_array_data;
        }
        else
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] == JAMC_SEMICOLON_CHAR))
    {
        /*
         *      Do a simple VECTOR operation -- no capture or compare
         */
        //if (jam_vector_io (urj_jam_vector_signal_count,
        //                   dir_vector, data_vector,
        //                   NULL) != urj_jam_vector_signal_count)
        {
            status = JAMC_INTERNAL_ERROR;
        }
    }
    else if ((status == JAMC_SUCCESS) &&
             (statement_buffer[delimiter] == JAMC_COMMA_CHAR))
    {
        /*
         *      Delimiter was a COMMA, so look for CAPTURE or COMPARE keyword
         */
        index = delimiter + 1;
        while (isspace (statement_buffer[index]))
        {
            ++index;            /* skip over white space */
        }

        if ((strncmp (&statement_buffer[index], "CAPTURE", 7) == 0) &&
            (isspace (statement_buffer[index + 7])))
        {
            /*
             *      Do a VECTOR with capture
             */
            status = urj_jam_process_vector_capture (&statement_buffer[index + 8],
                                                 urj_jam_vector_signal_count,
                                                 dir_vector, data_vector);
        }
        else if ((strncmp (&statement_buffer[index], "COMPARE", 7) == 0)
                 && (isspace (statement_buffer[index + 7])))
        {
            /*
             *      Do a VECTOR with compare
             */
            status = urj_jam_process_vector_compare (&statement_buffer[index + 8],
                                                 urj_jam_vector_signal_count,
                                                 dir_vector, data_vector);
        }
        else
        {
            status = JAMC_SYNTAX_ERROR;
        }
    }

    return status;
}

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

#define JAMC_MAX_VECTOR_SIGNALS 256

JAM_RETURN_TYPE
urj_jam_process_vmap (char *statement_buffer)
/*                                                                          */
/*  Description:    Sets signal mapping for non-JTAG hardware interface.    */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int signal_count = 0;
    char *signal_names[JAMC_MAX_VECTOR_SIGNALS];
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    while ((statement_buffer[index] != JAMC_SEMICOLON_CHAR) &&
           (status == JAMC_SUCCESS) &&
           (index < JAMC_MAX_STATEMENT_LENGTH) &&
           (signal_count < JAMC_MAX_VECTOR_SIGNALS))
    {
        /*
         *      Get signal names from statement, add NULL terminination characters,
         *      and save a pointer to each name
         */
        if (statement_buffer[index] == JAMC_QUOTE_CHAR)
        {
            ++index;
            signal_names[signal_count] = &statement_buffer[index];
            while ((statement_buffer[index] != JAMC_QUOTE_CHAR) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;
            }
            if (statement_buffer[index] == JAMC_QUOTE_CHAR)
            {
                statement_buffer[index] = JAMC_NULL_CHAR;
                ++index;

                if (*signal_names[signal_count] == JAMC_NULL_CHAR)
                {
                    /* check for empty string */
                    status = JAMC_SYNTAX_ERROR;
                }
                else
                {
                    ++signal_count;
                }
            }
            else
            {
                /* terminating quote character not found */
                status = JAMC_SYNTAX_ERROR;
            }
        }
        else
        {
            /* argument is not a quoted string */
            status = JAMC_SYNTAX_ERROR;
        }

        if (status == JAMC_SUCCESS)
        {
            while ((isspace (statement_buffer[index])) &&
                   (index < JAMC_MAX_STATEMENT_LENGTH))
            {
                ++index;        /* skip over white space */
            }

            if (statement_buffer[index] == JAMC_COMMA_CHAR)
            {
                /*
                 *      Skip over comma and white space to process next argument
                 */
                ++index;
                while ((isspace (statement_buffer[index])) &&
                       (index < JAMC_MAX_STATEMENT_LENGTH))
                {
                    ++index;    /* skip over white space */
                }
            }
            else if (statement_buffer[index] != JAMC_SEMICOLON_CHAR)
            {
                /*
                 *      If no comma to seperate arguments, statement must be
                 *      terminated by a semicolon
                 */
                status = JAMC_SYNTAX_ERROR;
            }
        }
    }

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[index] != JAMC_SEMICOLON_CHAR))
    {
        /* exceeded statement buffer length or signal count limit */
        status = JAMC_SYNTAX_ERROR;
    }

    if (status == JAMC_SUCCESS)
    {
        if (urj_jam_version == 2)
        {
            /* For Jam 2.0, reverse the order of the signal names */
            for (index = signal_count / 2; index > 0; --index)
            {
                signal_names[signal_count] = signal_names[index - 1];
                signal_names[index - 1] = signal_names[signal_count - index];
                signal_names[signal_count - index] =
                    signal_names[signal_count];
            }
        }

        //if (jam_vector_map (signal_count, signal_names) == signal_count)
        //{
        //    urj_jam_vector_signal_count = signal_count;
        //}
        //else
        {
            status = JAMC_VECTOR_MAP_FAILED;
            urj_jam_vector_signal_count = 0;
        }
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_wait_cycles
    (char *statement_buffer, JAME_JTAG_STATE wait_state)
/*                                                                          */
/*  Description:    Causes JTAG hardware to loop in the specified stable    */
/*                  state for the specified number of TCK clock cycles.     */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int32_t cycles = 0L;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    /*
     *      Call parser to evaluate expression
     */
    status = urj_jam_evaluate_expression (statement_buffer, &cycles, &expr_type);

    /*
     *      Check for integer expression
     */
    if ((status == JAMC_SUCCESS) &&
        (expr_type != JAM_INTEGER_EXPR) &&
        (expr_type != JAM_INT_OR_BOOL_EXPR))
    {
        status = JAMC_TYPE_MISMATCH;
    }

    /*
     *      Do the JTAG hardware operation
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_do_wait_cycles (cycles, wait_state);
    }

    return status;
}

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

JAM_RETURN_TYPE urj_jam_process_wait_microseconds
    (char *statement_buffer, JAME_JTAG_STATE wait_state)
/*                                                                          */
/*  Description:    Causes JTAG hardware to sit in the specified stable     */
/*                  state for the specified duration of real time.          */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int32_t microseconds = 0L;
    JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    /*
     *      Call parser to evaluate expression
     */
    status = urj_jam_evaluate_expression (statement_buffer, &microseconds,
                                      &expr_type);

    /*
     *      Check for integer expression
     */
    if ((status == JAMC_SUCCESS) &&
        (expr_type != JAM_INTEGER_EXPR) &&
        (expr_type != JAM_INT_OR_BOOL_EXPR))
    {
        status = JAMC_TYPE_MISMATCH;
    }

    /*
     *      Do the JTAG hardware operation
     */
    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_do_wait_microseconds (microseconds, wait_state);
    }

    return status;
}

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

JAM_RETURN_TYPE
urj_jam_process_wait (char *statement_buffer)
/*                                                                          */
/*  Description:    Processes WAIT statement                                */
/*                                                                          */
/*                  syntax: WAIT [<wait-state>,] [<integer-expr> CYCLES,]   */
/*                               [<integer-expr> USEC,] [<end-state>];      */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    int index = 0;
    int expr_begin = 0;
    int expr_end = 0;
    int delimiter = 0;
    char save_ch = 0;
    BOOL found_wait_state = false;
    BOOL found_condition = false;
    BOOL found_end_state = false;
    JAME_JTAG_STATE state = JAM_ILLEGAL_JTAG_STATE;
    JAME_JTAG_STATE wait_state = IDLE;
    JAME_JTAG_STATE end_state = IDLE;
    JAM_RETURN_TYPE status = JAMC_SYNTAX_ERROR;

    if ((urj_jam_version == 2) && (urj_jam_phase != JAM_PROCEDURE_PHASE))
    {
        return JAMC_PHASE_ERROR;
    }

    index = urj_jam_skip_instruction_name (statement_buffer);

    do
    {
        /*
         *      Get next argument
         */
        status = urj_jam_find_argument (&statement_buffer[index],
                                    &expr_begin, &expr_end, &delimiter);

        if (status == JAMC_SUCCESS)
        {
            expr_begin += index;
            expr_end += index;
            delimiter += index;

            save_ch = statement_buffer[expr_end];
            statement_buffer[expr_end] = JAMC_NULL_CHAR;
            state =
                urj_jam_get_jtag_state_from_name (&statement_buffer[expr_begin]);

            if (state == JAM_ILLEGAL_JTAG_STATE)
            {
                /* first argument was not a JTAG state name */
                index = expr_end - 1;
                while ((index > expr_begin) &&
                       (!isspace (statement_buffer[index])))
                {
                    --index;
                }
                if ((index > expr_begin) &&
                    (isspace (statement_buffer[index])))
                {
                    ++index;

                    if (strcmp (&statement_buffer[index], "CYCLES") == 0)
                    {
                        statement_buffer[index] = JAMC_NULL_CHAR;
                        status =
                            urj_jam_process_wait_cycles (&statement_buffer
                                                     [expr_begin],
                                                     wait_state);
                        statement_buffer[index] = 'C';
                    }
                    else if (strcmp (&statement_buffer[index], "USEC") ==
                             0)
                    {
                        statement_buffer[index] = JAMC_NULL_CHAR;
                        status =
                            urj_jam_process_wait_microseconds (&statement_buffer
                                                           [expr_begin],
                                                           wait_state);
                        statement_buffer[index] = 'U';
                    }
                    else
                    {
                        status = JAMC_SYNTAX_ERROR;
                    }

                    found_condition = true;
                }

                index = delimiter + 1;
            }
            else
            {
                /* argument was a JTAG state name */
                if ((!found_condition) && (!found_wait_state))
                {
                    wait_state = state;
                    found_wait_state = true;
                }
                else if ((found_condition) && (!found_end_state))
                {
                    end_state = state;
                    found_end_state = true;
                }
                else
                {
                    status = JAMC_SYNTAX_ERROR;
                }

                index = delimiter + 1;
            }

            statement_buffer[expr_end] = save_ch;
        }
    }
    while ((status == JAMC_SUCCESS) &&
           (statement_buffer[delimiter] == JAMC_COMMA_CHAR));

    if ((status == JAMC_SUCCESS) &&
        (statement_buffer[delimiter] != JAMC_SEMICOLON_CHAR))
    {
        status = JAMC_SYNTAX_ERROR;
    }

    if ((status == JAMC_SUCCESS) && (!found_condition))
    {
        /* there must have been at least one condition argument */
        status = JAMC_SYNTAX_ERROR;
    }

    /*
     *      If end state was specified, go there
     */
    if ((status == JAMC_SUCCESS) && (end_state != IDLE))
    {
        status = urj_jam_goto_jtag_state (end_state);
    }

    return status;
}

void
urj_jam_free_literal_aca_buffers (void)
{
    int i;

    for (i = 0; i < JAMC_MAX_LITERAL_ARRAYS; ++i)
    {
        if (urj_jam_literal_aca_buffer[i] != NULL)
        {
            free (urj_jam_literal_aca_buffer[i]);
            urj_jam_literal_aca_buffer[i] = NULL;
        }
    }
}

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

JAM_RETURN_TYPE urj_jam_execute_statement
    (char *statement_buffer,
     BOOL *done, BOOL *reuse_statement_buffer, int *exit_code)
/*                                                                          */
/*  Description:    Processes a statement by calling the processing         */
/*                  sub-function which corresponds to the instruction type  */
/*                                                                          */
/*  Returns:        JAMC_SUCCESS for success, else appropriate error code   */
/*                                                                          */
/****************************************************************************/
{
    JAME_INSTRUCTION instruction_code = JAM_ILLEGAL_INSTR;
    JAM_RETURN_TYPE status = JAMC_SUCCESS;

    instruction_code = urj_jam_get_instruction (statement_buffer);

    switch (instruction_code)
    {
    case JAM_ACTION_INSTR:
        status = urj_jam_process_action (statement_buffer, done, exit_code);
        break;

    case JAM_BOOLEAN_INSTR:
        status = urj_jam_process_boolean (statement_buffer);
        break;

    case JAM_CALL_INSTR:
        status = urj_jam_process_call_or_goto (statement_buffer, true, done,
                                           exit_code);
        break;

    case JAM_CRC_INSTR:
        status = JAMC_PHASE_ERROR;
        break;

    case JAM_DATA_INSTR:
        status = urj_jam_process_data (statement_buffer);
        break;

    case JAM_DRSCAN_INSTR:
        status = urj_jam_process_drscan (statement_buffer);
        break;

    case JAM_DRSTOP_INSTR:
        status = urj_jam_process_drstop (statement_buffer);
        break;

    case JAM_ENDDATA_INSTR:
        status = urj_jam_process_return (statement_buffer, true);
        break;

    case JAM_ENDPROC_INSTR:
        status = urj_jam_process_return (statement_buffer, true);
        break;

    case JAM_EXIT_INSTR:
        status = urj_jam_process_exit (statement_buffer, done, exit_code);
        break;

    case JAM_EXPORT_INSTR:
        status = urj_jam_process_export (statement_buffer);
        break;

    case JAM_FOR_INSTR:
        status = urj_jam_process_for (statement_buffer);
        break;

    case JAM_FREQUENCY_INSTR:
        status = urj_jam_process_frequency (statement_buffer);
        break;

    case JAM_GOTO_INSTR:
        status = urj_jam_process_call_or_goto (statement_buffer, false, done,
                                           exit_code);
        break;

    case JAM_IF_INSTR:
        status = urj_jam_process_if (statement_buffer, reuse_statement_buffer);
        break;

    case JAM_INTEGER_INSTR:
        status = urj_jam_process_integer (statement_buffer);
        break;

    case JAM_IRSCAN_INSTR:
        status = urj_jam_process_irscan (statement_buffer);
        break;

    case JAM_IRSTOP_INSTR:
        status = urj_jam_process_irstop (statement_buffer);
        break;

    case JAM_LET_INSTR:
        status = urj_jam_process_assignment (statement_buffer, true);
        break;

    case JAM_NEXT_INSTR:
        status = urj_jam_process_next (statement_buffer);
        break;

    case JAM_NOTE_INSTR:
        /* ignore NOTE statements during execution */
        if (urj_jam_phase == JAM_UNKNOWN_PHASE)
        {
            urj_jam_phase = JAM_NOTE_PHASE;
        }
        if ((urj_jam_version == 2) && (urj_jam_phase != JAM_NOTE_PHASE))
        {
            status = JAMC_PHASE_ERROR;
        }
        break;

    case JAM_PADDING_INSTR:
        status = urj_jam_process_padding (statement_buffer);
        break;

    case JAM_POP_INSTR:
        status = urj_jam_process_pop (statement_buffer);
        break;

    case JAM_POSTDR_INSTR:
    case JAM_POSTIR_INSTR:
    case JAM_PREDR_INSTR:
    case JAM_PREIR_INSTR:
        status = urj_jam_process_pre_post (instruction_code, statement_buffer);
        break;

    case JAM_PRINT_INSTR:
        status = urj_jam_process_print (statement_buffer);
        break;

    case JAM_PROCEDURE_INSTR:
        status = urj_jam_process_procedure (statement_buffer);
        break;

    case JAM_PUSH_INSTR:
        status = urj_jam_process_push (statement_buffer);
        break;

    case JAM_REM_INSTR:
        /* ignore REM statements during execution */
        break;

    case JAM_RETURN_INSTR:
        status = urj_jam_process_return (statement_buffer, false);
        break;

    case JAM_STATE_INSTR:
        status = urj_jam_process_state (statement_buffer);
        break;

    case JAM_TRST_INSTR:
        status = urj_jam_process_trst (statement_buffer);
        break;

    case JAM_VECTOR_INSTR:
        status = urj_jam_process_vector (statement_buffer);
        break;

    case JAM_VMAP_INSTR:
        status = urj_jam_process_vmap (statement_buffer);
        break;

    case JAM_WAIT_INSTR:
        status = urj_jam_process_wait (statement_buffer);
        break;

    default:
        if ((urj_jam_version == 2) && (urj_jam_check_assignment (statement_buffer)))
        {
            status = urj_jam_process_assignment (statement_buffer, false);
        }
        else
        {
            status = JAMC_SYNTAX_ERROR;
        }
        break;
    }

    urj_jam_free_literal_aca_buffers ();

    return status;
}

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

int32_t
urj_jam_get_line_of_position (int32_t position)
/*                                                                          */
/*  Description:    Determines the line number in the input stream which    */
/*                  corresponds to the given position (offset) in the       */
/*                  stream.  This is used for error reporting.              */
/*                                                                          */
/*  Returns:        line number, or zero if it could not be determined      */
/*                                                                          */
/****************************************************************************/
{
    int32_t line = 0L;
    int32_t index = 0L;
    int ch;

    if (urj_jam_seek (0L) == 0)
    {
        ++line;                 /* first line is line 1, not zero */

        for (index = 0; index < position; ++index)
        {
            ch = urj_jam_getc ();

            if (ch == JAMC_NEWLINE_CHAR)
            {
                ++line;
            }
        }
    }

    return line;
}

/****************************************************************************/
/*                                                                          */
JAM_RETURN_TYPE urj_jam_execute
    (char *program,
     int32_t program_size,
     char *workspace,
     int32_t workspace_size,
     char *action,
     char **init_list,
     int reset_jtag,
     int32_t *error_line, int *exit_code, int *format_version)
/*                                                                          */
/*  Description:    This is the main entry point for executing a JAM        */
/*                  program.  It returns after execution has terminated.    */
/*                  The program data is not passed into this function,      */
/*                  but is accessed through the urj_jam_getc() function.        */
/*                                                                          */
/*  Return:         JAMC_SUCCESS for successful execution, otherwise one    */
/*                  of the error codes listed in <jamexprt.h>               */
/*                                                                          */
/****************************************************************************/
{
    JAM_RETURN_TYPE status = JAMC_SUCCESS;
    char *statement_buffer = NULL;
    char label_buffer[JAMC_MAX_NAME_LENGTH + 1];
    BOOL done = false;
    BOOL reuse_statement_buffer = false;
    int i = 0;

    urj_jam_program = program;
    urj_jam_program_size = program_size;
    urj_jam_workspace = workspace;
    urj_jam_workspace_size = workspace_size;
    urj_jam_action = action;
    urj_jam_init_list = init_list;

    urj_jam_current_file_position = 0L;
    urj_jam_current_statement_position = 0L;
    urj_jam_next_statement_position = 0L;
    urj_jam_vector_signal_count = 0;
    urj_jam_version = 0;
    urj_jam_phase = JAM_UNKNOWN_PHASE;
    urj_jam_current_block = NULL;

    for (i = 0; i < JAMC_MAX_LITERAL_ARRAYS; ++i)
    {
        urj_jam_literal_aca_buffer[i] = NULL;
    }

    /*
     *      Ensure that workspace is DWORD aligned
     */
    if (urj_jam_workspace != NULL)
    {
        urj_jam_workspace_size -= (((int32_t) urj_jam_workspace) & 3L);
        urj_jam_workspace_size &= (~3L);
        urj_jam_workspace = (char *) (((int32_t) urj_jam_workspace + 3L) & (~3L));
    }

    /*
     *      Initialize symbol table and stack
     */
    status = urj_jam_init_symbol_table ();

    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_init_stack ();
    }

    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_init_jtag ();
    }

    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_init_heap ();
    }

    if (status == JAMC_SUCCESS)
    {
        status = urj_jam_seek (0L);
    }

    if (status == JAMC_SUCCESS)
    {
        statement_buffer = malloc (JAMC_MAX_STATEMENT_LENGTH + 1024);

        if (statement_buffer == NULL)
        {
            status = JAMC_OUT_OF_MEMORY;
        }
    }

    /*
     *      Get program statements and execute them
     */
    while ((!done) && (status == JAMC_SUCCESS))
    {
        if (!reuse_statement_buffer)
        {
            status = urj_jam_get_statement (statement_buffer, label_buffer);

            if ((status == JAMC_SUCCESS)
                && (label_buffer[0] != JAMC_NULL_CHAR))
            {
                status = urj_jam_add_symbol
                    (JAM_LABEL,
                     label_buffer, 0L, urj_jam_current_statement_position);
            }
        }
        else
        {
            /* statement buffer will be reused -- clear the flag */
            reuse_statement_buffer = false;
        }

        if (status == JAMC_SUCCESS)
        {
            status = urj_jam_execute_statement
                (statement_buffer, &done, &reuse_statement_buffer, exit_code);
        }
    }

    if ((status != JAMC_SUCCESS) && (error_line != NULL))
    {
        *error_line =
            urj_jam_get_line_of_position (urj_jam_current_statement_position);
    }

    urj_jam_free_literal_aca_buffers ();
    urj_jam_free_jtag_padding_buffers (reset_jtag);
    urj_jam_free_heap ();
    urj_jam_free_stack ();
    urj_jam_free_symbol_table ();

    if (statement_buffer != NULL)
        free (statement_buffer);

    if (format_version != NULL)
        *format_version = urj_jam_version;

    return status;
}
